/**********************************************
file name: test.c
linux DNS socket forwarding
port number:530
IP add:
is test
//在orangepi zero 中编译使用
使用mysql_config 查询 lib库位置
Options:
--cflags [-I/www/server/mysql/include -g -DNDEBUG]
--include [-I/www/server/mysql/include]
--libs [-L/www/server/mysql/lib -lmysqlclient -lpthread -lm -ldl]
--libs_r [-L/www/server/mysql/lib -lmysqlclient_r -lpthread -lm -ld
使用lib库编译
gcc test.c -o test -L/www/server/mysql/lib -lmysqlclient -lpthread -lm -ldl
*/
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h> //文件操作
#include <pthread.h>
#include <stdbool.h>
#include <stdarg.h>
//#include </www/server/mysql/include/mysql.h>//绝对路径mysql数据库
#include "assert.h"
#include <time.h>
//#include <iostream.h>
#define DNS_CLIENT_BUF_MAX 80 //DNS请求客户IP地址和端口存储最大数量
//DNS info Type(查询类型)
#define T_A 1 //Ipv4 地址
#define T_NS 2 //域名服务器
#define T_CNAME 5 // 规范名称
#define T_SOA 6 /* 开始授权*/
#define T_WKS 11 //熟知服务
#define T_PTR 12 /* 请求把地址转换域名 */
#define T_HINFO 13 //主机信息
#define T_MX 15 //邮件交换服务
#define T_AAAA 28 //域名获得 IPv6 地址
#define T_AXFR 252 //传送整个区的请求
#define T_ANY 255 //对所有记录的请求
pthread_mutex_t g_mutex=PTHREAD_MUTEX_INITIALIZER; //网络状态计数锁
pthread_mutex_t ID_mutex=PTHREAD_MUTEX_INITIALIZER;//用于写入与读取客户IP信息锁
pthread_mutex_t ID_DNS_MUTEX=PTHREAD_MUTEX_INITIALIZER; //缓存操作锁 多线程插入、删除、统计 时建议加锁
pthread_mutex_t ID_TCP_MUTEX=PTHREAD_MUTEX_INITIALIZER;//用于TCP数据发送加锁,以防止数据无序发送
//msg_infomation
//DNS 协议头结构
struct DNS_HEADER
{
unsigned short id; // 标识号(事务ID)
//位数据从低开始
unsigned char rd :1; // 表示期望递归
unsigned char tc :1; // 表示可截断的
unsigned char aa :1; // 表示授权回答
unsigned char opcode :4; // 0 表示标准查询,1 表示反向查询,2 表示服务器状态请求
unsigned char qr :1; // 查询/响应标志,0 为查询,1 为响应
unsigned char rcode :4; // 表示返回码,0 表示没有差错,3 表示名字差错,2 表示服务器错误(Server Failure)
unsigned char cd :1; // checking disabled
unsigned char ad :1; // authenticated data
unsigned char z :1; // its z! reserved
unsigned char ra :1; // 表示可用递归
unsigned short q_count; // 问题数
unsigned short ans_count; // 回答数
unsigned short auth_count; // 权威答案数
unsigned short add_count; // 附加答案数
};
//问题信息结构
struct QUESTION
{
unsigned short qtype;
unsigned short qclass;
};
//记录信息结构
#pragma pack(push, 1)
struct R_DATA
{
unsigned short type;//表明资源纪录的类型
unsigned short _class;//对于 Internet 信息,总是 IN
unsigned short ttl_1;//以秒为单位,表示的是资源记录的生命周期
unsigned short ttl_2;//同上,共有四个字节
unsigned short data_len;//该字段是一个可变长字段,表示相关资源记录的数据长度
};
#pragma pack(pop)
//单个记录完整内容结构
struct RES_RECORD
{
unsigned char *name;
struct R_DATA *resource;
unsigned char *rdata;
};
//单个问题完全结构
typedef struct
{
unsigned char name[256];
struct QUESTION question;
} QUERY;
typedef struct msg_infomation//转发数据结构
{
char flag_bit[2];
char comm_bit[2];
char data_len[2];
char data_buf[2048];
}msg_info;
//UDP client ID event with IP addresses and port
typedef struct client_id_addr //事件ID与客户端关系结构
{
int id;
struct sockaddr_in sock_addr;
}this_cli_id;
//DNS缓存数据结构
typedef struct this_dns_record
{
unsigned char *name;
struct R_DATA *resource;
unsigned char *rdata;//缓存的数据
struct this_dns_record *pre;//列表时为0 或 NULL 时表示首个数据结构
struct this_dns_record *next;//列表时为0 或 NULL 时表示最后数据结构
}th_cli;
//pthread msg information
typedef struct pth_msg_info //线程共享数据结构体
{
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
int socket_tcp;
int socket_udp;
int connected_tcp;
int connected_udp;
//this_cli_id my_cli_id[DNS_CLIENT_BUF_MAX];
th_cli * Cache_dns;
int BROADCAST_on;
int connect_wait_test;//用来记录服务器的等待信息次数
int connect_stop_restart;
}this_pth_msg;
typedef struct CPU_PACKED
{
char name[20];
unsigned int user;
unsigned int nice;
unsigned int system;
unsigned int idle;
}CPU_OCCUPY;
//-----------------------mem--------------------
typedef struct MEM_PACKED
{
char name[20];
unsigned long total;
char name2[20];
}MEM_OCCUPY;
typedef struct MEM_PACK
{
double total;
double used_rate;
}MEM_PACK;
//定义全局
this_cli_id dns_client[DNS_CLIENT_BUF_MAX];//客户DNS ID 与 客户关系缓存
static unsigned char * protocol_getname(unsigned char *chunk, QUERY *dst, unsigned char *src);
static unsigned char * dns_parse_name(unsigned char *chunk, unsigned char *ptr, char *out, int *len);
static int is_pointer(int in);
th_cli * find_dns_record(th_cli * head,unsigned char * name,unsigned short type);
int delete_dns_record(th_cli ** head,th_cli * p);
const char * cache_name="DNS.cache";
//int count_dns_record(th_cli * head,int max = 10000);
//将BUFF中的数据打印到控制台
void dump_buff(char * buff,int bytes)
{
int i;
for(i=0;i<bytes;i++)
{
printf("0x%02x ",(unsigned char)buff[i]);
if(0== (i+1)%16)
printf("\n\r");
}
printf("\n\r");
}
/*将域名按规则插入BUFF
* dns :BUFF的指针
* host :域名字符串指针
* eg. www.google.com to 3www6google3com
*
* */
void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* buf)
{
int lock = 0 , i;
unsigned char host[256];
bzero(host,256);
strcpy(host,buf);
strcat((char*)host,".");//追加一个“.”到最后
for(i = 0 ; i < strlen((char*)host) ; i++)
{
if(host[i]=='.')
{
*dns++ = i-lock;
for(;lock<i;lock++)
{
*dns++=host[lock];
}
lock++; //or lock=i+1;
}
}
*dns++='\0';
}
//计算CPU使用率
int cal_cpuoccupy(CPU_OCCUPY *o, CPU_OCCUPY *n)
{
unsigned long od, nd;
unsigned long id, sd;
int cpu_use = 0;
od = (unsigned long) (o->user+ o->nice + o->system + o->idle);//第一次(用户+优先级+系统+空闲)的时间
nd = (unsigned long) (n->user + n->nice + n->system + n->idle); //第二次
id = (unsigned long) (n->user - o->user);
sd = (unsigned long) (n->system - o->system);
if((nd - od) != 0){
cpu_use = (int)((sd+id)*100)/(nd-od);
}else {
cpu_use = 0;
}
return cpu_use;
}
//获取CPU相关信息
void get_cpuoccupy(CPU_OCCUPY *cpust)
{
FILE *fd;
int n;
char buff[256];
CPU_OCCUPY *cpu_occupy;
cpu_occupy = cpust;
fd = fopen("/proc/stat","r");
fgets(buff,sizeof(buff),fd);
sscanf(buff,"%s %u %u %u %u",cpu_occupy->name,&cpu_occupy->user,&cpu_occupy->nice, &cpu_occupy->system, &cpu_occupy->idle);
fclose(fd);
}
//获取内存大小和使用情况
MEM_PACK get_memocupy()
{
FILE *fd;
int n;
double mem_total,mem_used_rate;
char buff[256];
MEM_OCCUPY *m = (MEM_OCCUPY*)malloc(sizeof(MEM_OCCUPY));
MEM_PACK p;
fd = fopen("/proc/meminfo", "r");
fgets(buff,sizeof (buff), fd);
sscanf(buff, "%s %lu %s\n", m->name, &m->total, m->name2);
mem_total = m->total;
fgets(buff,sizeof (buff),fd);
sscanf(buff, "%s %lu %s\n", m->name, &m->total,m->name2);
mem_used_rate = (1 - m->total/mem_total)*100;
mem_total = mem_total/(1024*1024);
p.total = mem_total;
p.used_rate = mem_used_rate;
fclose(fd);
free(m);
return p;
}
//获取CPU温度
int get_cpu_temp()
{
FILE *fd;
int temp;
char buff[256];
fd = fopen("/sys/class/thermal/thermal_zone0/temp","r");
fgets(buff,sizeof(buff),fd);
sscanf(buff, "%d", &temp);
fclose(fd);
return temp/1000;
}
//获取主板启动后的运行时间 eg: get_last_reboot("last reboot",lastreboot, 64);
int get_last_reboot(char *cmd,char *output, int size)
{
FILE *fp = NULL;
fp = popen(cmd,"r");
if(fp){
fgets(output,size,fp);
if(fgets(output,size,fp) != NULL){
if(output[strlen(output) - 1] == '\n')
output[strlen(output) - 1] = '\0';
}
pclose(fp);
}
return 0;
}
//插入DNS请求ID与客户端IP和端口信息
void insert_dns_client(int dns_id, struct sockaddr_in *add_r)
{
pthread_mutex_lock(&ID_mutex);
memmove(&dns_client[1], &dns_client[0], sizeof(this_cli_id) * (DNS_CLIENT_BUF_MAX - 1));
dns_client[0].id = dns_id;
memcpy(&(dns_client[0].sock_addr), add_r, sizeof(struct sockaddr_in));
pthread_mutex_unlock(&ID_mutex);
}
//根据Dns ID 获取发请求的客户机地址和端口
int get_dns_client(int dns_id,struct sockaddr_in *add_r)
{
int temp_i;
pthread_mutex_lock(&ID_mutex);
for(temp_i=0;temp_i<DNS_CLIENT_BUF_MAX;temp_i++)
{
if(dns_client[temp_i].id==dns_id)
{
memcpy(add_r,&(dns_client[temp_i].sock_addr),sizeof(struct sockaddr_in));
memmove(&dns_client[temp_i],&dns_client[temp_i+1],sizeof(this_cli_id) * (DNS_CLIENT_BUF_MAX -temp_i- 1));
pthread_mutex_unlock(&ID_mutex);
return 0;
}
}
pthread_mutex_unlock(&ID_mutex);
return -1;
}
//本程序打印信息函数,使用UDP广播或在控制台打印,在UDP启动后广播到指定端口
//arg :全局变量(this_pth_msg)结构指针 为 NULL 时全部输出到控制台
void my_printf(void *arg,const char * format,...)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
va_list ap;
char Debug_buff[512];
va_start(ap, format);
int expected = vsnprintf(Debug_buff, sizeof(Debug_buff), format, ap);
va_end(ap);
//Debug_buff[expected]=0;
if (expected<1)
{
return;
}
if( pthread_my!=NULL&&pthread_my->connected_udp==1&&pthread_my->BROADCAST_on==1)
{
struct sockaddr_in udp_temp;
bzero(&udp_temp,sizeof(struct sockaddr_in));
udp_temp.sin_family=AF_INET;
udp_temp.sin_addr.s_addr=inet_addr("255.255.255.255");
udp_temp.sin_port=htons(8000);
if(1>sendto(pthread_my->socket_udp,Debug_buff,expected,0,(struct sockaddr *)&udp_temp,sizeof(struct sockaddr)))
{
printf("TCP sendTO UDP DEBUG_BROADCAST failed !\r\n");
}
else
{
return;
}
}
printf("%s",Debug_buff);
}
//将DNS响应信息插入数据库(如果存在则更新,没有则插入)
//传入响应数据包指针 和 整个数据包长度
//arg : 用于打印 请传入(this_pth_msg)结构指针 或 直接传 NULL 打印到控制台(本程序打印信息函数,使用UDP广播或在控制台打印,在UDP启动后广播到指定端口)
//src : 需要存储的DNS响应数据包指针,解析后结果如果不为响应包或响应出错将不进行存储或更新
//lengths : 数据包大小值
void insert_to_mysql(void *arg,unsigned char *src,int lengths)
{/*
int t_lengths=2*lengths+2;
//unsigned char *t_src=(unsigned char *)malloc(t_lengths);
QUERY domain_name;//需存储的DNS名称
bzero(&domain_name,sizeof(domain_name));
unsigned char * temp_src=src;
temp_src+=12;
temp_src=protocol_getname(src,&domain_name,temp_src);
struct DNS_HEADER *t_dns_header=(struct DNS_HEADER *)src;
//my_printf(arg,"DEBUG: @@the response message %s--%d--%d \r\n",domain_name.name,ntohs(domain_name.question.qtype),ntohs(domain_name.question.qclass));
if(t_dns_header->rcode!=0 || ntohs(t_dns_header->ans_count)<1 || ntohs(t_dns_header->q_count)>1 || ntohs(domain_name.question.qclass)!=1) //响应信息服务器返回错误码或应答数少于1或问题数大于1 都认为是错误不做处理
{
my_printf(arg,"DEBUG: A service error occurred in the response message !\r\n");
return;
}
//Start reading answers take TTL
int t_ttl=60;//设置默认TTL 秒
char aname[128], ip[20], netip[4];
int len;
struct R_DATA anawers_data;
//my_printf(arg,"DEBUG: There are %d answers in the response message !\r\n",ntohs(t_dns_header->ans_count));
for (int i = 0;i < ntohs(t_dns_header->ans_count);i ++)
{
bzero(aname, sizeof(aname));
len = 0;
bzero(&anawers_data,sizeof(anawers_data));
temp_src=dns_parse_name(src, temp_src, aname, &len);
anawers_data=*(struct R_DATA *)temp_src;
temp_src += sizeof(anawers_data);
if(ntohs(anawers_data.data_len)>lengths)
{
my_printf(arg,"DEBUG: data lengths failed---------------------------------");
return;
}
if(t_ttl<ntohs(anawers_data.ttl_2))
{
t_ttl=ntohs(anawers_data.ttl_2);
}
temp_src+=ntohs(anawers_data.data_len);
}
unsigned char *t_src=(unsigned char *)malloc(t_lengths);
MYSQL mysql;
mysql_init(&mysql);
if( ! mysql_real_connect(&mysql, "localhost", "root", "tanling123", "DNS", 3306, NULL, 0))
{
my_printf(arg,"DEBUG: connect mysql failed! failed! Error: %s\r\n",mysql_error(&mysql));
}
//my_printf(arg,"DEBUG: connect mysql OK!\r\n");
mysql_query(&mysql,"SET NAMES BGK");//设置编码格式
//判断数据是否存在
char sql[2048] = {0};
snprintf(sql, 2048, "select 1 from dns where name = '%s' and qtype=%d and qclass=%d limit 1",domain_name.name,ntohs(domain_name.question.qtype),ntohs(domain_name.question.qclass));
int code = mysql_real_query(&mysql, sql, strlen(sql));//mysql_query(&mysql,"SELECT id,c_time FROM dns WHERE id = 1");
if (0 != code) //非0查询失败
{
my_printf(arg,"DEBUG: query failed! [%s] [%d] [%s] \n", sql, mysql_errno(&mysql), mysql_error(&mysql));
free(t_src);
mysql_close(&mysql);
return ;
}
//my_printf(arg,"DEBUG: query mysql OK!\r\n");
//保存查询结果
MYSQL_RES* res = mysql_store_result(&mysql);
bzero(sql,2048);
mysql_real_escape_string(&mysql,(unsigned char *)t_src,(unsigned char *)src,lengths);//转换数据方便my_sql 存储
if((unsigned long)mysql_num_rows(res)>0) //判断返回数据行数 (如果有数据则进行更新,如果不存在就插入)
{
//my_printf(arg,"DEBUG: query mysql UPDATE!\r\n");
snprintf(sql, 2048, "UPDATE `dns` SET `c_time`=NOW(),`ttl`=%d,`data_length`=%d,`dns_data`='%s' WHERE name='%s' and qtype=%d and qclass=%d",t_ttl,lengths,t_src,domain_name.name,ntohs(domain_name.question.qtype),ntohs(domain_name.question.qclass));
}
else
{
//my_printf(arg,"DEBUG: query mysql INSERT!\r\n");
snprintf(sql, 2048, "INSERT INTO `dns`( `name`, `c_time`, `ttl`, `qtype`, `qclass`, `data_length`,`dns_data`) VALUES ('%s',NOW(),'%d','%d','%d','%d','%s')",domain_name.name,t_ttl,ntohs(domain_name.question.qtype),ntohs(domain_name.question.qclass),lengths,t_src);
}
//mysql_free_result(res);//释放查询结果
code = mysql_real_query(&mysql, sql, strlen(sql));//mysql_query(&mysql,"SELECT id,c_time FROM dns WHERE id = 1");
if (0 != code) //非0查询失败
{
my_printf(arg,"DEBUG: query failed! [%s]--[%d]--[%s] \n",sql, mysql_errno(&mysql), mysql_error(&mysql));
//free(t_src);
//return ;
}
//my_printf(arg,"DEBUG: query mysql OK!\r\n");
//保存查询结果
//res = mysql_store_result(&mysql);
mysql_free_result(res);//释放查询结果
//my_printf(arg,"DEBUG: close my_sql\r\n");
free(t_src);
mysql_close(&mysql);
//getchar();
return ;*/
}
//从数据库中读取DNS数据
void get_dns_for_mysql(void *arg)
{
}
//获取DNS问题中的名称
//chunk :请求数据包
//dst :输出字符指针(问题信息结构)
//src : DNS请求中名称开始位置指针
//返回 :下一个需处理的首地址
static unsigned char * protocol_getname(unsigned char *chunk, QUERY *dst, unsigned char *src){
int i,j;
//将名称数据全部取出
for (i = 0, j = 1; 0 != src[j];i++, j++){
dst->name[i] = src[j];
}
j++;
dst->name[i] = '\0';
i = src[0];
//将数据中的关键部位进行转换
while (0 != src[i + 1]){
dst->name[i] = '.';
i = i + 1 + src[i + 1];
}
dst->question=*(struct QUESTION *)&src[j];
j+=sizeof(struct QUESTION);//4;
src+=j;
return src;
}
//判断是否为DNS名称指针
static int is_pointer(int in) {
return ((in & 0xC0) == 0xC0);
}
//获取响应回答数据段中的名称
//chunk :响应数据包
//ptr :名称在数据包中的位置首指针
//out :用于名称输出
//len :名称长度输出
//返回:下一个需处理的首地址
static unsigned char * dns_parse_name(unsigned char *chunk, unsigned char *ptr, char *out, int *len)
{
int flag = 0, n = 0, alen = 0;
char *pos = out + (*len);
//****************有问题,需修正
while (1) {
flag = (int)ptr[0];
if (flag == 0)
{
ptr++;
return ptr;
//break;
}
if (is_pointer(flag)) {
n = (int)ptr[1];
unsigned char *ptr_1 = chunk + n;
dns_parse_name(chunk, ptr_1, out, len);
ptr+=2;
return ptr;
//break;
} else {
ptr ++;
memcpy(pos, ptr, flag);
pos += flag;
ptr += flag;
*len += flag;
if ((int)ptr[0] != 0) {
memcpy(pos, ".", 1);
pos += 1;
(*len) += 1;
}
}
}
}
//新建一个空的DNS缓存结构
th_cli * new_dns_record()
{
th_cli *p=(th_cli *)malloc(sizeof(th_cli));
if(p == NULL)
{
perror("malloc memory faile !\r\n");
return NULL;
}
//bzero(p->event_id,sizeof(p->event_id));
//bzero(&(p->sock_addr),sizeof(p->sock_addr));
p->name=NULL;
p->resource=NULL;
p->rdata=NULL;
p->pre=0;
p->next=0;
return p;
}
//插入一个DNS响应数据到DNS缓存列表,会新建DNS缓存结构,并使用malloc分配内部的数据部分空间,请注意释放内存
//arg : 用于打印 请传入(this_pth_msg)结构指针 或 直接传 NULL 打印到控制台(本程序打印信息函数,使用UDP广播或在控制台打印,在UDP启动后广播到指定端口)
//head: 是指向th_cli *列表的指针的地址
//src : 需要存储的DNS响应数据包指针
//lengths : 数据包大小值
//return : 返回 0 成功,1为失败
int insert_dns_record(void *arg,th_cli ** head,unsigned char *src,int lengths)
{
th_cli * p=new_dns_record();
if(p==NULL)
{
my_printf(arg,"DEBUG: malloc cache-struct-memory faile !\r\n");
return 1;
}
//先将数据写入结构体
QUERY domain_name;//需存储的DNS名称
bzero(&domain_name,sizeof(domain_name));
unsigned char * temp_src=src;
temp_src+=12;
temp_src=protocol_getname(src,&domain_name,temp_src);
int q_name_length=strlen(domain_name.name);//temp_src - 12 - src;//计算name 需要的内存空间
if(q_name_length>128)
{
my_printf(arg,"DEBUG: DNS question name length is to big !\r\n");
goto error;
}
struct DNS_HEADER *t_dns_header=(struct DNS_HEADER *)src;
//判断DNS数据响应包是否符合要求
if(t_dns_header->rcode!=0 || ntohs(t_dns_header->ans_count)<1 || ntohs(t_dns_header->q_count)>1 || ntohs(domain_name.question.qclass)!=1) //响应信息服务器返回错误码或应答数少于1或问题数大于1或不为响应包 都认为是错误不做处理
{
//my_printf(arg,"DEBUG: A service error occurred in the response message !\r\n");
goto error;
}
int t_ttl=60;//设置默认TTL 秒
//char aname[128], ip[20], netip[4];
//int len;
//struct R_DATA anawers_data;
//my_printf(arg,"DEBUG: There are %d answers in the response message !\r\n",ntohs(t_dns_header->ans_count));
/*
for (int i = 0;i < ntohs(t_dns_header->ans_count);i ++)
{
bzero(aname, sizeof(aname));
len = 0;
bzero(&anawers_data,sizeof(anawers_data));
temp_src=dns_parse_name(src, temp_src, aname, &len);
anawers_data=*(struct R_DATA *)temp_src;
temp_src += sizeof(anawers_data);
if(ntohs(anawers_data.data_len)>lengths)
{
my_printf(arg,"DEBUG: data lengths failed---------------------------------");
goto error;
}
if(t_ttl<ntohs(anawers_data.ttl_2))
{
t_ttl=ntohs(anawers_data.ttl_2);
}
temp_src+=ntohs(anawers_data.data_len);
}*/
//my_printf(arg,"DEBUG: DNS question name length: %d name: %s\r\n",q_name_length,domain_name.name);
//删除原有缓存数据
if((* head)!=0 && (* head)!=NULL)
{
delete_dns_record(head,find_dns_record((th_cli *)(* head),(unsigned char *)&(domain_name.name),domain_name.question.qtype));
}
p->name=(unsigned char *)malloc(q_name_length+1);
//my_printf(arg,"DEBUG: DNS cache test--1 !\r\n");
if(p->name == NULL)
{
my_printf(arg,"DEBUG: malloc name-memory faile !\r\n");
goto error;
}
p->resource=(struct R_DATA *)malloc(sizeof(struct R_DATA));
if(p->resource == NULL)
{
my_printf(arg,"DEBUG: malloc resource-memory faile !\r\n");
free(p->name);
goto error;
}
p->rdata=(unsigned char *)malloc(lengths+1);
if(p->rdata == NULL)
{
my_printf(arg,"DEBUG: malloc rdata-memory faile !\r\n");
free(p->name);
free(p->resource);
goto error;
}
bzero(p->name,sizeof(q_name_length+1));
bzero(p->resource,sizeof(struct R_DATA));
bzero(p->rdata,sizeof(lengths+1));
//内存分配清零完成,下面将数据写入
memcpy(p->name,domain_name.name,q_name_length);
p->resource->type=domain_name.question.qtype;
p->resource->_class=domain_name.question.qclass;
p->resource->ttl_2=t_ttl;
p->resource->data_len=lengths;
memcpy(p->rdata,src,lengths);
//数据写入成功,调整列表指针
if((*head)!= NULL)
{
p->next=(*head);
//(*head)->next->pre=p;
//p->pre=(*head);
(*head)->pre=p;
}
(*head)=p;
return 0;
error:
free(p);
return 1;
}
//查找缓存数据
//head: 是指向th_cli *列表的指针
//name: 需要查找的问题名称
//type:需要查找的数据类型
//return :返回找到的数据的指针,否则返回NULL
th_cli * find_dns_record(th_cli * head,unsigned char * name,unsigned short type)
{
if(head==NULL || name==NULL || name[0]==0 || type==0 || head == 0)
{
return NULL;
}
while(1)
{
if(strcmp(head->name,name)==0 && (head->resource->type) == type)
{
return head;
}
if((head->next) !=0 && (head->next) !=NULL)
{
head=head->next;
}
else
{
break;
}
}
return NULL;
}
//释放指定的DNS缓存空间
//p : 是需要释放空间的地址指针
void free_DNS_cache(th_cli * p)
{
//释放数据空间
if((p->name)!= NULL)
free(p->name);
if((p->resource)!= NULL)
free(p->resource);
if((p->rdata)!= NULL)
free(p->rdata);
//释放数据结构空间
free(p);
}
//从DNS缓存列表中删除指定数据
//head:是指向th_cli *列表的首指针的地址
//p : 是需要从列表链中删除的地址指针
//return : 返回0表示成功
int delete_dns_record(th_cli ** head,th_cli * p)
{
if(p==NULL || p==0)
{
return 1;
}
if((p->pre)!=0 && (p->pre)!=NULL)
{
p->pre->next=p->next;
}
else
{
(* head)=p->next;//调整列表的首地址
//p->next->pre=0;
}
if((p->next)!=0 && (p->next)!=NULL)
p->next->pre=p->pre;
p->pre=p;
p->next=p;
//释放数据空间
free_DNS_cache(p);
#if 0
/*
if((p->name)!= NULL)
free(p->name);
if((p->resource)!= NULL)
free(p->resource);
if((p->rdata)!= NULL)
free(p->rdata);
//释放数据结构空间
free(p);
*/
#endif
//printf("delete success !\r\n");
return 0;
}
//删除全部缓存数据
//head:是指向th_cli *列表的首指针
void del_all_dns_cache(th_cli * head)
{
th_cli * p = NULL;
if(head==NULL || head==0)
{
return ;
}
do
{
p = head;
head=head->next;
p->pre=p;
p->next=p;
free_DNS_cache(p);
}while(head!=0 && head!=NULL);
}
//获取DNS缓列表中缓存数
//head :是指向th_cli *列表的指针
//max :列表最大存储数,如果大于最大存储将会删除尾部多余部分数据 最少100条数据
//return : 返回当前列表中th_cli结构的数量(包含超出部分)
int count_dns_record(th_cli * head,int max)
{
th_cli * p = 0;
if(head == 0 || head == NULL || max <100)
{
return 0;
}
int count=0;
do
{
count++;
p = head;
head=head->next;
if(count > max)//如果大于最大缓存数
{
p->pre->next=head;//调整本数据的前一个数据的下一指针指向本数据的后面数据
if(head!=0 && head!=NULL)
head->pre=p->pre;//如果后面还有数据则调整后一个数据的上指针指向本数据的前面数据
p->pre=p;
p->next=p;
//释放数据空间
free_DNS_cache(p);//清除本数据
#if 0
/*
if((p->name)!= NULL)
free(p->name);
if((p->resource)!= NULL)
free(p->resource);
if((p->rdata)!= NULL)
free(p->rdata);
//释放数据结构空间
free(p);
*/
#endif
}
}while(head!=0 && head!=NULL);
return count;
}
//将缓存数据写入缓存文件
void wirte_DNS_cache_to_file(void *arg)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
FILE *fd;
int t_len;
th_cli * p = NULL;
if((fd=fopen(cache_name,"wb"))==NULL)
{
my_printf(pthread_my,"DEBUG: open DNS cache file error !\r\n");
return ;
}
char t_buff[1024];
p=pthread_my->Cache_dns;
if(p!=0 && p!=NULL)
{
do{
bzero(&t_buff,1024);
t_buff[0]=(char)((p->resource->data_len&0xff00)>>8);
t_buff[1]=(char)(p->resource->data_len&0x00ff);
memcpy(&t_buff[2],p->rdata,p->resource->data_len);
fwrite(t_buff,p->resource->data_len+2,1,fd);
p=p->next;
}while(p!=0 && p!=NULL);
}
fclose(fd);
my_printf(pthread_my,"DEBUG: write DNS cache to file succeed !\r\n");
return ;
}
//从文件中读取缓存数据
void read_file_to_DNS_cache(void *arg)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
//int fd;
FILE *fd;
int t_len,len;
//th_cli * p = NULL;
if((fd=fopen(cache_name,"rd"))==NULL)//O_RDONLY|O_NDELAY)<0)
{
my_printf(pthread_my,"DEBUG: open DNS cache file error !\r\n");
return ;
}
char t_buff[1024];
//lseek(fd,0,SEEK_SET);
do{
bzero(&t_buff,1024);
//my_printf(arg,"DEBUG: read DNS cache file error !\r\n");
if((len=fread(t_buff,2,1,fd))<1)
{
//my_printf(arg,"DEBUG: read DNS cache file error !\r\n");
break;
}
//my_printf(arg,"DEBUG: read DNS cache file error !--d--%d\r\n",len);
t_len=(int)t_buff[0];
t_len=(int)(t_len<<8) + (int)t_buff[1];
if(len=fread(t_buff,t_len,1,fd)<1)
{
//my_printf(pthread_my,"DEBUG: read DNS cache file error !\r\n");
break;
}
insert_dns_record(pthread_my,&(pthread_my->Cache_dns),t_buff,t_len);
}while(1);
fclose(fd);
return ;
}
//获取缓存的最一条记录指针
th_cli * last_dns_record(th_cli * head)
{
if(head==NULL || head==0)
{
return NULL;
}
while(1)
{
if((head->next) !=0 && (head->next) !=NULL)
{
head=head->next;
}
else
{
return head;
}
}
}
//刷新缓存记录
void func_Refresh_cache(void *arg)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
unsigned char *qname;
msg_info infor_buf;
struct DNS_HEADER *dns = NULL;
struct QUESTION *qinfo = NULL;
bzero(&infor_buf,sizeof(msg_info));//数据区清零
dns = (struct DNS_HEADER *)&infor_buf.data_buf;//取DNS协议头指针位置
dns->id = (unsigned short) htons(getpid());
dns->qr = 0; //This is a query
dns->opcode = 0; //This is a standard query
dns->aa = 0; //Not Authoritative
dns->tc = 0; //This message is not truncated
dns->rd = 1; //Recursion Desired
dns->ra = 0; //Recursion not available! hey we dont have it (lol)
dns->z = 0;
dns->ad = 0;
dns->cd = 0;
dns->rcode = 0;
dns->q_count = htons(1); //we have only 1 question
dns->ans_count = 0;
dns->auth_count = 0;
dns->add_count = 0;
//printf("Set DNS header!\r\n");
qname =(unsigned char*)&infor_buf.data_buf[sizeof(struct DNS_HEADER)];//取DNS问题部分头位置
//pthread_mutex_lock(&ID_DNS_MUTEX);
th_cli * last_p=last_dns_record(pthread_my->Cache_dns);//取最后一个DNS缓存指针
if(last_p==NULL)
{
return;
}
ChangetoDnsNameFormat(qname , last_p->name);
//printf("Get DNS host name! %s\r\n",last_p->name);
qinfo =(struct QUESTION*)&infor_buf.data_buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)];
qinfo->qtype = last_p->resource->type; //type of the query , A , MX , CNAME , NS etc
qinfo->qclass = htons(1); //its internet (lol)
//pthread_mutex_unlock(&ID_DNS_MUTEX);
//printf("Set DNS type!\r\n");
int len=sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION);
infor_buf.flag_bit[0]=0xff;
infor_buf.flag_bit[1]=0xff;
infor_buf.comm_bit[0]=0x00;
infor_buf.comm_bit[1]=0xfe;
infor_buf.data_len[0]=(char)((len&0xff00)>>8);
infor_buf.data_len[1]=(char)(len&0x00ff);
printf("Send TCP DNS data!%d-%s\r\n",len,last_p->name);
dump_buff((char *)&infor_buf,len+6);
if(pthread_my->connected_tcp==1)
{
pthread_mutex_lock(&ID_TCP_MUTEX);
ssize_t send_d =send(pthread_my->socket_tcp,&infor_buf,len+6,0);
//printf("Send TCP DNS data!%d-%s\r\n",len,qname);
pthread_mutex_unlock(&ID_TCP_MUTEX);
if(1>send_d)
{
my_printf(pthread_my,"DEBUG: TCP send faile for UDP thread !\r\n");
pthread_my->connected_tcp=0;
}
}
else{
my_printf(pthread_my,"DEBUG: TCP Failed to connection !\r\n");
}
}
//function tcp recv thread
//监听TCP数据返回线程,中间会一直等待UDP服务器建立
//arg :线程共享数据结构体指针
void * func_tcp_recv(void *arg)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
//int socket_t=pthread_my->socket_tcp;//(int)arg;
//int socket_u=pthread_my->socket_udp;
ssize_t recv_t;
//struct MEM_PACK mem;
//th_cli * Cache_dns = NULL;
char infor_buf[2048];
//struct sockaddr_in udp_temp;
//bzero(&udp_temp,sizeof(struct sockaddr_in));
//udp_temp.sin_family=AF_INET;
//udp_temp.sin_addr.s_addr=inet_addr("255.255.255.255");
//udp_temp.sin_port=htons(8000);
my_printf(pthread_my,"DEBUG: TCP recv start !\r\n");
//printf("TCP recv start !\r\n");
int tcp_error=0;
pthread_my->connected_tcp=0;
struct timeval tv = {30, 0};//超时设置为30秒0微秒
int len;
int data_i;//数据数组索引
while(tcp_error<5)
{
my_printf(pthread_my,"DEBUG: TCP start connected!\r\n");
//printf("TCP start connected!\r\n");
pthread_my->socket_tcp=socket(AF_INET,SOCK_STREAM,0);
if(pthread_my->socket_tcp==-1)
{
my_printf(pthread_my,"DEBUG: TCP socket failed !\r\n");
//printf("TCP socket failed!\r\n");
tcp_error++;
sleep(1);
continue;//return -1;
}
if(-1 == connect(pthread_my->socket_tcp,(struct sockaddr *)(&pthread_my->s_addr),sizeof(struct sockaddr)))
{
my_printf(pthread_my,"DEBUG: TCP connect fail,Waiting to reconnect !\r\n");
//printf("TCP connect fail,Waiting to reconnect !\r\n");
sleep(1);
close(pthread_my->socket_tcp);
continue;
}
pthread_my->connected_tcp=1;
while(pthread_my->connected_udp<1)
{
sleep(1);
}
if (0 > setsockopt(pthread_my->socket_tcp, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
{
pthread_my->connected_tcp=0;
my_printf(pthread_my,"DEBUG: TCP SO_RCVTIMEO set faile !\r\n");
break;
}
while(pthread_my->connected_tcp==1)
{
bzero(&infor_buf,sizeof(infor_buf));
recv_t=recv(pthread_my->socket_tcp,&infor_buf,sizeof(infor_buf),0);
if(1 >recv_t)
{
my_printf(pthread_my,"DEBUG: TCP recv faile !\r\n");
//printf("TCP recv faile !\r\n");
pthread_my->connected_tcp=0;
break;
}
pthread_mutex_lock(&g_mutex);
pthread_my->connect_stop_restart=0;//重置网络计数
pthread_mutex_unlock(&g_mutex);
data_i=0;
while(data_i+18<recv_t)
{
if(infor_buf[data_i]!=0xff || infor_buf[data_i+1]!=0xff)
{
//printf("TCP recv flag bit error! continue..... \r\n");
data_i++;
continue;
}
len=0;
len=(int)(infor_buf[data_i+4]&0xff) <<8;
len=len + (int)(infor_buf[data_i+5]&0xff);
if (recv_t-len <6)
{
my_printf(pthread_my,"DEBUG: TCP data failed !\r\n");
//printf("TCP data failed !");
break;
}
switch(infor_buf[data_i+3])
{
case 0x00 :
{
//服务器回答的相关调试信息
pthread_mutex_lock(&g_mutex);
pthread_my->connect_wait_test++;//服务器等待数据计数
pthread_mutex_unlock(&g_mutex);
my_printf(pthread_my,"DEBUG: %s\r\n",(char *)&infor_buf[data_i+6]);
break;
}
case 0xfe :
{
int dns_id_t=(int)infor_buf[data_i+6];
dns_id_t = (dns_id_t<<8) + (int)infor_buf[data_i+7];
struct sockaddr_in client_addr_t;
bzero(&client_addr_t,sizeof(client_addr_t));
if(0==get_dns_client(dns_id_t,&client_addr_t))
{
//printf("Find DNS client ID !\r\n");
if(pthread_my->connected_udp==1)
{
if(1>sendto(pthread_my->socket_udp,&infor_buf[data_i+6],len,0,(struct sockaddr *)&client_addr_t,sizeof(struct sockaddr)))
{
my_printf(pthread_my,"DEBUG: TCP send DNS recv failed !\r\n");
}
}
}
//插入数据库
//insert_to_mysql(pthread_my,&infor_buf[data_i+6],len);
//插入缓存(内存模式)
//mem = get_memocupy();
pthread_mutex_lock(&ID_DNS_MUTEX);
insert_dns_record(pthread_my,&(pthread_my->Cache_dns),&infor_buf[data_i+6],len);
my_printf(pthread_my,"DEBUG: cpu-Temperature: %d \r\n",get_cpu_temp());
pthread_mutex_unlock(&ID_DNS_MUTEX);
break;
}
default:
{
my_printf(pthread_my,"DEBUG: TCP ERROR!command !\r\n");
}
}
data_i=data_i+len+6;
}
}
pthread_my->connected_tcp=0;
close(pthread_my->socket_tcp);
}
pthread_my->connected_tcp=-1;
my_printf(pthread_my,"DEBUG: TCP pthread ERROR,please reboot system!\r\n");
}
//UDP服务线程,监听数据传入并转发到TCP
//function udp recv thread
void * func_udp_recv(void *arg)
{
this_pth_msg *pthread_my=(this_pth_msg *)arg;
ssize_t recv_t;
msg_info infor_buf;
QUERY domain_name;
th_cli * Cache_dns_t = NULL;
struct sockaddr_in sockaddr_udp;
ssize_t src_len=sizeof(sockaddr_udp);
my_printf(pthread_my,"DEBUG: UDP recv start !\r\n");
int udp_error=0;
pthread_my->connected_udp=0;
while(udp_error<5)
{
pthread_my->socket_udp=socket(AF_INET,SOCK_DGRAM,0);
if(pthread_my->socket_udp==-1)
{
my_printf(pthread_my,"DEBUG: UDP socket failed!\r\n");
//printf("UDP socket failed!\r\n");
udp_error++;
sleep(1);
continue;//return -1;
}
/*2. 设置允许发送广播包,linux 中默认是不允许广播,需要在程序中开启*/
//int on = 1;
if(pthread_my->BROADCAST_on==1)
{
if (0 > setsockopt(pthread_my->socket_udp, SOL_SOCKET, SO_BROADCAST, &pthread_my->BROADCAST_on, sizeof(pthread_my->BROADCAST_on)))
{
pthread_my->BROADCAST_on=0;//广播允许设置失败,关闭广播!
my_printf(pthread_my,"DEBUG: setsockopt SO_BROADCAST set failed !\r\n");
}
}
if(-1 == bind(pthread_my->socket_udp,(struct sockaddr *)&pthread_my->c_addr,sizeof(struct sockaddr)))
{
my_printf(pthread_my,"DEBUG: UDP failed to bind socket on port !\r\n");
sleep(1);
udp_error++;
close(pthread_my->socket_udp);
continue;
}
pthread_my->connected_udp=1;
// while(pthread_my->connected_tcp<1)//不等待TCP连接
// {
sleep(1);
//}
udp_error=0;
while(1)
{
bzero(&infor_buf,sizeof(infor_buf));
bzero(&sockaddr_udp,src_len);
recv_t=recvfrom(pthread_my->socket_udp,infor_buf.data_buf,sizeof(infor_buf.data_buf),0,(struct sockaddr *)&sockaddr_udp,(socklen_t *)&src_len);
if(recv_t < 1||recv_t>512)
{
my_printf(pthread_my,"DEBUG: udp recv faile ! recv count:%d\r\n",recv_t);
//printf("udp recv faile ! recv count:%d\r\n",recv_t);
if(recv_t>=0)
{
continue;
}
else{
pthread_my->connected_udp=0;
if(pthread_my->socket_udp!=-1)
{
close(pthread_my->socket_udp);
}
my_printf(pthread_my,"DEBUG: udp recv ERROR ,reboot UDP ! ");
break;
}
}
if(infor_buf.data_buf[0]==0xff && infor_buf.data_buf[1]==0xff)//传入的为自定义的协议数据
{
memmove((char *)&infor_buf,(char *)&(infor_buf.data_buf),recv_t);
recv_t=recv_t-6;
}
else
{
infor_buf.flag_bit[0]=0xff;
infor_buf.flag_bit[1]=0xff;
infor_buf.comm_bit[0]=0x00;
infor_buf.comm_bit[1]=0xfe;
infor_buf.data_len[0]=(char)((recv_t&0xff00)>>8);
infor_buf.data_len[1]=(char)(recv_t&0x00ff);
int dnd_id = (int)infor_buf.data_buf[0];
dnd_id = (dnd_id<<8)+(int)infor_buf.data_buf[1];
insert_dns_client(dnd_id,&sockaddr_udp);
protocol_getname(infor_buf.data_buf,&domain_name,&(infor_buf.data_buf[12]));
//查找缓存数据 存在数据则优先发送
Cache_dns_t=NULL;
pthread_mutex_lock(&ID_DNS_MUTEX);
Cache_dns_t=find_dns_record(pthread_my->Cache_dns,(unsigned char *)&(domain_name.name),domain_name.question.qtype);
if(Cache_dns_t!=NULL)
{
my_printf(pthread_my,"DEBUG: Find DNS cache data: %s---%s--%d--%d \r\n",inet_ntoa((struct in_addr)(sockaddr_udp.sin_addr)),domain_name.name,ntohs(domain_name.question.qtype),ntohs(domain_name.question.qclass));
(Cache_dns_t->rdata)[0]=infor_buf.data_buf[0];
(Cache_dns_t->rdata)[1]=infor_buf.data_buf[1];
bzero(&sockaddr_udp,src_len);
if(0==get_dns_client(dnd_id,&sockaddr_udp))
{
if(1>sendto(pthread_my->socket_udp,Cache_dns_t->rdata,Cache_dns_t->resource->data_len,0,(struct sockaddr *)&sockaddr_udp,sizeof(struct sockaddr)))
{
my_printf(pthread_my,"DEBUG: Send DNS recv failed !\r\n");
}
}
}
pthread_mutex_unlock(&ID_DNS_MUTEX);
}
if(pthread_my->connected_tcp==1)
{
pthread_mutex_lock(&ID_TCP_MUTEX);
ssize_t send_d =send(pthread_my->socket_tcp,&infor_buf,recv_t+6,0);
pthread_mutex_unlock(&ID_TCP_MUTEX);
if(1>send_d)
{
my_printf(pthread_my,"DEBUG: TCP send faile for UDP thread !\r\n");
pthread_my->connected_tcp=0;
}
}
else{
my_printf(pthread_my,"DEBUG: TCP Failed to connection !\r\n");
}
}
}
pthread_my->connected_udp=-1;
my_printf(pthread_my,"DEBUG: UDP pthread ERROR,please reboot system!\r\n");
}
int main()
{
int count=0;
char buffer[20]={0};
//bool bNewBehavior = false;
//DWORD dwBytesReturned = 0;
this_pth_msg my_pth_msg;
bzero(&my_pth_msg,sizeof(my_pth_msg));
//配置网络参数
unsigned short tcp_portnum=0x212;// port:530
unsigned short udp_portnum=53;
my_pth_msg.s_addr.sin_family=AF_INET;
my_pth_msg.s_addr.sin_addr.s_addr=inet_addr("22.234.7.20");
my_pth_msg.s_addr.sin_port=htons(tcp_portnum);
my_pth_msg.c_addr.sin_family=AF_INET;
my_pth_msg.c_addr.sin_addr.s_addr=htonl(INADDR_ANY);
my_pth_msg.c_addr.sin_port=htons(udp_portnum);
//printf("Hello welcome to DNS Foramading!\r\n");
my_pth_msg.connected_tcp=0;
my_pth_msg.connected_udp=0;
my_pth_msg.BROADCAST_on = 1;//设置允许发送广播包
my_pth_msg.Cache_dns=NULL;
//my_pth_msg.socket_udp=udp_sock;
//printf("socket ok!\r\n");
my_printf((void *)&my_pth_msg,"\r\n --------Hello welcome to DNS Foramading!-------\r\n");
my_printf((void *)&my_pth_msg,"s_addr = %#x ,port : %#x\r\n",my_pth_msg.s_addr.sin_addr.s_addr,my_pth_msg.s_addr.sin_port);
my_printf((void *)&my_pth_msg,"c_addr = %#x ,port : %#x\r\n",my_pth_msg.c_addr.sin_addr.s_addr,my_pth_msg.c_addr.sin_port);
read_file_to_DNS_cache(&my_pth_msg);//从文件中读取缓存数据
my_printf(&my_pth_msg,"DEBUG: read file to DNS cache count : %d cpu tempe: %d \r\n",count_dns_record(my_pth_msg.Cache_dns,5000),get_cpu_temp());
//printf("connect ok !\r\n");
/* fix microsoft bug 10054 */
//WSAIoctl(my_pth_msg.socket_udp,_WSAIOW(IOC_VENDOR,12),&bNewBehavior,sizeof(bNewBehavior),NULL,0,&dwBytesReturned,NULL,NULL);
bzero(&buffer,sizeof(buffer));
char test[20];
buffer[0]=0xff;
buffer[1]=0xff;
buffer[2]=0x00;
buffer[3]=0x00;
buffer[4]=0x00;
buffer[5]=0x00;
pthread_t pid_t;
int ret_t = pthread_create(&pid_t,NULL,func_tcp_recv,(void *)&my_pth_msg);
//printf("ret_t : %d\r\n",ret_t);
pthread_t pid_u;
int ret_u = pthread_create(&pid_u,NULL,func_udp_recv,(void *)&my_pth_msg);
//printf("ret_u : %d\r\n",ret_u);
//test mysql
//insert_to_mysql((void *)&my_pth_msg);
//char buf_temp[20]="test udp send\r\n";
int write_file_count=0;
while((my_pth_msg.connected_tcp!=-1)&&(my_pth_msg.connected_udp!=-1))
{
//getchar();//scanf("%s",test);
if(my_pth_msg.connect_stop_restart>10 || my_pth_msg.connect_wait_test>10)
{
pthread_mutex_lock(&g_mutex);
my_pth_msg.connect_wait_test=0;//服务器等待数据计数,如果服务器长时间得不到客户机数据,将会断开客户机
pthread_mutex_unlock(&g_mutex);
if(my_pth_msg.connected_tcp==1)
{
//printf("TCP servers test message !");
if(1>send(my_pth_msg.socket_tcp,&buffer,6,0))
{
my_printf((void *)&my_pth_msg,"TCP send faile !\r\n");
close(my_pth_msg.socket_tcp);
my_pth_msg.connected_tcp=0;
//break;
}
}
}
// printf("TCP status : %d UDP status : %d\r\n",my_pth_msg.connected_tcp,my_pth_msg.connected_udp);
pthread_mutex_lock(&g_mutex);
my_pth_msg.connect_stop_restart++;
pthread_mutex_unlock(&g_mutex);
sleep(1);
pthread_mutex_lock(&ID_DNS_MUTEX);
if(count_dns_record(my_pth_msg.Cache_dns,5000)>50)//缓存数量大于50后进行最后一个缓存更新
func_Refresh_cache(&my_pth_msg);
pthread_mutex_unlock(&ID_DNS_MUTEX);
write_file_count++;
if(write_file_count>1000)
{
pthread_mutex_lock(&ID_DNS_MUTEX);
wirte_DNS_cache_to_file(&my_pth_msg);//将缓存数据写入文件
pthread_mutex_unlock(&ID_DNS_MUTEX);
write_file_count=0;
}
}
//getchar();
close(my_pth_msg.socket_tcp);
close(my_pth_msg.socket_udp);
del_all_dns_cache(my_pth_msg.Cache_dns);//释放缓存空间
pthread_mutex_destroy(&g_mutex);
pthread_mutex_destroy(&ID_mutex);
return 0;
}
arm linux 中用C写了一个UDP转TCP的代码
于 2023-04-07 01:05:08 首次发布