diff --git a/dns.c b/dns.c index 8d40ee6..8c24391 100644 --- a/dns.c +++ b/dns.c @@ -17,6 +17,7 @@ */ #include "dns.h" +#include "tlog.h" #include #include @@ -515,6 +516,9 @@ int _dns_decode_domain(struct dns_context *context, char *output, int size) int is_compressed = 0; while (1) { + if (ptr > context->data + context->maxsize || ptr < context->data) { + return -1; + } len = *ptr; if (len == 0) { *(output - 1) = 0; @@ -528,21 +532,27 @@ int _dns_decode_domain(struct dns_context *context, char *output, int size) context->ptr = ptr; } ptr = context->data + len; - if (context->maxsize - (ptr - context->data) < 1) { + if (context->maxsize - (ptr - context->data) < 0) { + tlog(TLOG_ERROR, "length is not enouth %d:%d, %p, %p", context->maxsize, ptr-context->data, + context->ptr, context->data); return -1; } is_compressed = 1; continue; } - if (context->maxsize - (ptr - context->data) < 1) { + if (context->maxsize - (ptr - context->data) < 0) { + tlog(TLOG_ERROR, "length is not enouth %d:%d, %p, %p", context->maxsize, ptr-context->data, + context->ptr, context->data); return -1; } ptr++; if (output_len < size - 1) { copy_len = (len < size - output_len) ? len : size - 1 - output_len; - if (context->maxsize - (ptr - context->data) < 1) { + if (context->maxsize - (ptr - context->data) < 0) { + tlog(TLOG_ERROR, "length is not enouth %d:%d, %p, %p", context->maxsize, ptr-context->data, + context->ptr, context->data); return -1; } memcpy(output, ptr, copy_len); @@ -594,10 +604,12 @@ int _dns_decode_qr_head(struct dns_context *context, char *domain, int domain_si ret = _dns_decode_domain(context, domain, domain_size); if (ret < 0) { + tlog(TLOG_ERROR, "decode domain failed."); return -1; } if (_dns_left_len(context) < 4) { + tlog(TLOG_ERROR, "left length is not enough, %s.", domain); return -1; } @@ -631,10 +643,12 @@ int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_si len = _dns_decode_qr_head(context, domain, domain_size, qtype, qclass); if (len < 0) { + tlog(TLOG_ERROR, "decode qr head failed."); return -1; } if (_dns_left_len(context) < 6) { + tlog(TLOG_ERROR, "left length is not enough."); return -1; } @@ -873,6 +887,7 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) ret = _dns_decode_rr_head(context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); if (ret < 0) { + tlog(TLOG_ERROR, "decode head failed."); return -1; } start = context->ptr; @@ -882,11 +897,13 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) unsigned char addr[DNS_RR_A_LEN]; ret = _dns_decode_A(context, addr); if (ret < 0) { + tlog(TLOG_ERROR, "decode A failed, %s", domain); return -1; } ret = dns_add_A(packet, type, domain, ttl, addr); if (ret < 0) { + tlog(TLOG_ERROR, "add A failed, %s", domain); return -1; } } break; @@ -894,11 +911,13 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) char cname[DNS_MAX_CNAME_LEN]; ret = _dns_decode_CNAME(context, cname, DNS_MAX_CNAME_LEN); if (ret < 0) { + tlog(TLOG_ERROR, "decode CNAME failed, %s", domain); return -1; } ret = dns_add_CNAME(packet, type, domain, ttl, cname); if (ret < 0) { + tlog(TLOG_ERROR, "add CNAME failed, %s", domain); return -1; } } break; @@ -906,11 +925,13 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) char ns[DNS_MAX_CNAME_LEN]; ret = _dns_decode_CNAME(context, ns, DNS_MAX_CNAME_LEN); if (ret < 0) { + tlog(TLOG_ERROR, "decode NS failed, %s", domain); return -1; } ret = dns_add_NS(packet, type, domain, ttl, ns); if (ret < 0) { + tlog(TLOG_ERROR, "add NS failed, %s", domain); return -1; } } break; @@ -918,11 +939,13 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) char name[DNS_MAX_CNAME_LEN]; ret = _dns_decode_PTR(context, name, DNS_MAX_CNAME_LEN); if (ret < 0) { + tlog(TLOG_ERROR, "decode PTR failed, %s", domain); return -1; } ret = dns_add_PTR(packet, type, domain, ttl, name); if (ret < 0) { + tlog(TLOG_ERROR, "add PTR failed, %s", domain); return -1; } } break; @@ -930,11 +953,13 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) unsigned char addr[DNS_RR_AAAA_LEN]; ret = _dns_decode_AAAA(context, addr); if (ret < 0) { + tlog(TLOG_ERROR, "decode AAAA failed, %s", domain); return -1; } ret = dns_add_AAAA(packet, type, domain, ttl, addr); if (ret < 0) { + tlog(TLOG_ERROR, "add AAAA failed, %s", domain); return -1; } } break; @@ -944,6 +969,8 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) } if (context->ptr - start != rr_len) { + tlog(TLOG_ERROR, "length mitchmatch , %s, %d:%d", domain, + context->ptr - start, rr_len); return -1; } @@ -1014,6 +1041,7 @@ int _dns_decode_body(struct dns_context *context) for (i = 0; i < head->qdcount; i++) { ret = _dns_decode_qd(context); if (ret < 0) { + tlog(TLOG_ERROR, "decode qd failed."); return -1; } head->qdcount--; @@ -1022,6 +1050,7 @@ int _dns_decode_body(struct dns_context *context) for (i = 0; i < head->ancount; i++) { ret = _dns_decode_an(context, DNS_RRS_AN); if (ret < 0) { + tlog(TLOG_ERROR, "decode an failed."); return -1; } head->ancount--; @@ -1030,6 +1059,7 @@ int _dns_decode_body(struct dns_context *context) for (i = 0; i < head->nscount; i++) { ret = _dns_decode_an(context, DNS_RRS_NS); if (ret < 0) { + tlog(TLOG_ERROR, "decode ns failed."); return -1; } head->nscount--; @@ -1038,6 +1068,7 @@ int _dns_decode_body(struct dns_context *context) for (i = 0; i < head->nrcount; i++) { ret = _dns_decode_an(context, DNS_RRS_NR); if (ret < 0) { + tlog(TLOG_ERROR, "decode nr failed."); return -1; } head->nrcount--; @@ -1119,6 +1150,7 @@ int dns_decode(struct dns_packet *packet, int maxsize, unsigned char *data, int ret = _dns_decode_body(&context); if (ret < 0) { + tlog(TLOG_ERROR, "decode body failed.\n"); return -1; } diff --git a/dns.h b/dns.h index b5c62ab..23adf9a 100644 --- a/dns.h +++ b/dns.h @@ -9,7 +9,7 @@ #define DNS_RR_A_LEN 4 #define DNS_RR_AAAA_LEN 16 #define DNS_MAX_CNAME_LEN 256 -#define DNS_IN_PACKSIZE 512 +#define DNS_IN_PACKSIZE (512 * 2) #define DNS_PACKSIZE (512 * 4) typedef enum dns_rr_type { diff --git a/dns_client.c b/dns_client.c index 2be9c8b..446f209 100644 --- a/dns_client.c +++ b/dns_client.c @@ -40,6 +40,11 @@ #include #include #include +#include + #include + #include + + #define DNS_MAX_HOSTNAME 256 @@ -378,12 +383,13 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet) struct dns_query_struct *query; int ttl; char name[DNS_MAX_CNAME_LEN]; + char alias[DNS_MAX_CNAME_LEN] = {0}; + char ip[DNS_MAX_CNAME_LEN] = {0}; int rr_count; int i = 0; int j = 0; struct dns_rrs *rrs = NULL; int ret = -1; - int A_num = 0; query = _dns_client_get_request(packet->head.id, domain); if (query == NULL) { @@ -398,12 +404,14 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet) unsigned char addr[4]; dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); printf("%s %d : %d.%d.%d.%d\n", name, ttl, addr[0], addr[1], addr[2], addr[3]); - sprintf(name, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); - _dns_client_query_get(query); - if (fast_ping_start(name, 1, 700, dns_client_ping_result, query) == NULL) { - _dns_client_query_release(query); + sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); + + if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(alias, name, DNS_MAX_CNAME_LEN) == 0) { + _dns_client_query_get(query); + if (fast_ping_start(ip, 1, 700, dns_client_ping_result, query) == NULL) { + _dns_client_query_release(query); + } } - A_num++; } break; case DNS_T_AAAA: { unsigned char addr[16]; @@ -424,6 +432,7 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet) char cname[128]; dns_get_CNAME(rrs, name, 128, &ttl, cname, 128); printf("%s %d : %s\n", name, ttl, cname); + strncpy(alias, cname, DNS_MAX_CNAME_LEN); } break; default: break; @@ -431,10 +440,12 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet) } } + pthread_mutex_lock(&client.server_list_lock); query->dns_request_sent--; - if (query->dns_request_sent <= 0) { + if (query->dns_request_sent < 0) { _dns_client_query_release(query); } + pthread_mutex_unlock(&client.server_list_lock); return ret; } @@ -451,9 +462,14 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so unsigned char packet_buff[DNS_PACKSIZE]; struct dns_packet *packet = (struct dns_packet *)packet_buff; + packet->head.tc = 0; len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); if (len != 0) { - printf("decode failed, packet len = %d\n", inpacket_len); + tlog(TLOG_ERROR, "decode failed, packet len = %d, tc=%d, %d\n", inpacket_len, + packet->head.tc, packet->head.id); + int fd = open("dns.bin", O_CREAT | O_TRUNC | O_RDWR); + write(fd, inpacket, inpacket_len); + close(fd); return -1; } @@ -462,8 +478,9 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so return -1; } - printf("qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d\n", packet->head.qdcount, packet->head.ancount, packet->head.nscount, - packet->head.nrcount, inpacket_len, packet->head.id); + printf("qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, rd = %d, ra = %d, rcode = %d\n", packet->head.qdcount, packet->head.ancount, packet->head.nscount, + packet->head.nrcount, inpacket_len, packet->head.id, packet->head.rd, packet->head.ra, + packet->head.rcode); rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count); for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { @@ -471,6 +488,12 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so printf("domain: %s qtype: %d qclass: %d\n", name, qtype, qclass); } + if (packet->head.rcode != DNS_RC_NOERROR) { + tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d\n", name, packet->head.rcode); + //TODO set response to dns_server.c + return -1; + } + return _dns_client_process_answer(name, packet); } @@ -480,6 +503,7 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long unsigned char inpacket[DNS_IN_PACKSIZE]; struct sockaddr_storage from; socklen_t from_len = sizeof(from); + char from_host[DNS_MAX_CNAME_LEN]; len = recvfrom(client.udp, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len); if (len < 0) { @@ -487,6 +511,8 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long return -1; } + tlog(TLOG_INFO, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len)); + return _dns_client_recv(inpacket, len, &from, from_len); } @@ -625,6 +651,8 @@ int dns_client_query(char *domain, dns_client_callback callback, void *user_ptr) goto errout_del_list; } + tlog(TLOG_ERROR, "send request %s, id %d\n", domain, query->sid); + key = hash_string(domain); key = jhash(&query->sid, sizeof(query->sid), key); pthread_mutex_lock(&client.domain_map_lock); @@ -719,6 +747,28 @@ errout: return -1; } +void dns_debug(void) +{ + char data[1024]; + int len; + char buff[4096]; + + int fd = open("dns.bin", O_RDWR); + if (fd < 0) { + return; + } + len = read(fd, data, 1024); + close(fd); + if (len < 0) { + return; + } + + struct dns_packet *packet = buff; + if (dns_decode(packet, 4096, data, len) != 0) { + printf("decode failed.\n"); + } +} + int dns_client_init() { pthread_attr_t attr; @@ -726,7 +776,10 @@ int dns_client_init() int ret; int fd = 1; - if (client.epoll_fd > 0) { + //dns_debug(); + + if (client.epoll_fd > 0) + { return -1; } diff --git a/dns_server.c b/dns_server.c index 422bd23..90c0383 100644 --- a/dns_server.c +++ b/dns_server.c @@ -58,6 +58,7 @@ struct dns_request { atomic_t refcnt; struct hlist_node map; char domain[DNS_MAX_CNAME_LEN]; + char alias[DNS_MAX_CNAME_LEN]; unsigned short qtype; unsigned short id; unsigned short ss_family; @@ -169,6 +170,7 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request) default: break; } + return ret; } @@ -226,7 +228,8 @@ static int dns_server_resolve_callback(char *domain, struct dns_result *result, } memcpy(request->ipv4_addr, result->addr_ipv4, 4); - //memcpy(request->ipv6_addr, result->addr_ipv6, 16); + strncpy(request->alias, result->alias, DNS_MAX_CNAME_LEN); + // memcpy(request->ipv6_addr, result->addr_ipv6, 16); request->qtype = DNS_T_A; printf("----------------%s--%d.%d.%d.%d-\n", domain, diff --git a/fast_ping.c b/fast_ping.c index e813bec..42d1ff4 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -559,15 +559,18 @@ static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct struct icmp6_hdr *icmp6 = &packet->icmp6; if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { + tlog(TLOG_ERROR, "icmp6 type faild, %d:%d", icmp6->icmp6_type, ICMP6_ECHO_REPLY); return NULL; } icmp_len = data_len; if (icmp_len < 16) { + tlog(TLOG_ERROR, "length is invalid, %d", icmp_len); return NULL; } if (icmp6->icmp6_id != ping.ident) { + tlog(TLOG_ERROR, "ident failed, %d:%d", icmp6->icmp6_id, ping.ident); return NULL; } @@ -583,6 +586,7 @@ static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct * int icmp_len; if (ip->ip_p != IPPROTO_ICMP) { + tlog(TLOG_ERROR, "ip type faild, %d:%d", ip->ip_p, IPPROTO_ICMP); return NULL; } @@ -592,14 +596,17 @@ static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct * icmp_len = data_len - hlen; if (icmp_len < 16) { + tlog(TLOG_ERROR, "length is invalid, %d", icmp_len); return NULL; } if (icmp->icmp_type != ICMP_ECHOREPLY) { + tlog(TLOG_ERROR, "icmp type faild, %d:%d", icmp->icmp_type, ICMP_ECHOREPLY); return NULL; } if (icmp->icmp_id != ping.ident) { + tlog(TLOG_ERROR, "ident failed, %d:%d", icmp->icmp_id, ping.ident); return NULL; } @@ -621,6 +628,7 @@ struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_ho goto errout; } } else { + tlog(TLOG_ERROR, "ping host type is invalid, %d", ping_host->type); goto errout; } diff --git a/smartdns.c b/smartdns.c index cb2c199..f2363e2 100755 --- a/smartdns.c +++ b/smartdns.c @@ -35,6 +35,8 @@ int smartdns_init() goto errout; } + tlog_setlogscreen(1); + ret = fast_ping_init(); if (ret != 0) { fprintf(stderr, "start ping failed.\n"); @@ -53,10 +55,11 @@ int smartdns_init() goto errout; } - dns_add_server("192.168.1.1", 53, DNS_SERVER_UDP); + //dns_add_server("192.168.1.1", 53, DNS_SERVER_UDP); dns_add_server("114.114.114.114", 53, DNS_SERVER_UDP); dns_add_server("123.207.137.88", 53, DNS_SERVER_UDP); - fast_ping_start("192.168.1.1", 10, 1000, 0, 0); + dns_add_server("193.112.15.186", 53, DNS_SERVER_UDP); + //dns_add_server("202.141.178.13", 5353, DNS_SERVER_UDP); return 0; errout: