diff --git a/dns.c b/dns.c index ef6d33d..fd48c71 100644 --- a/dns.c +++ b/dns.c @@ -457,7 +457,7 @@ static inline int _dns_left_len(struct dns_context *context) return context->maxsize - (context->ptr - context->data); } -int _dns_decode_head(struct dns_context *context) +static int _dns_decode_head(struct dns_context *context) { unsigned int fields; int len = 12; @@ -484,7 +484,7 @@ int _dns_decode_head(struct dns_context *context) return 0; } -int _dns_encode_head(struct dns_context *context) +static int _dns_encode_head(struct dns_context *context) { int len = 12; struct dns_head *head = &context->packet->head; @@ -512,7 +512,7 @@ int _dns_encode_head(struct dns_context *context) return len; } -int _dns_decode_domain(struct dns_context *context, char *output, int size) +static int _dns_decode_domain(struct dns_context *context, char *output, int size) { int output_len = 0; int copy_len = 0; @@ -577,7 +577,7 @@ int _dns_decode_domain(struct dns_context *context, char *output, int size) return 0; } -int _dns_encode_domain(struct dns_context *context, char *domain) +static int _dns_encode_domain(struct dns_context *context, char *domain) { int num = 0; unsigned char *ptr_num = context->ptr++; @@ -603,7 +603,7 @@ int _dns_encode_domain(struct dns_context *context, char *domain) return 0; } -int _dns_decode_qr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass) +static int _dns_decode_qr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass) { int ret = 0; @@ -624,7 +624,7 @@ int _dns_decode_qr_head(struct dns_context *context, char *domain, int domain_si return 0; } -int _dns_encode_qr_head(struct dns_context *context, char *domain, int qtype, int qclass) +static int _dns_encode_qr_head(struct dns_context *context, char *domain, int qtype, int qclass) { int ret = 0; ret = _dns_encode_domain(context, domain); @@ -642,7 +642,7 @@ int _dns_encode_qr_head(struct dns_context *context, char *domain, int qtype, in return 0; } -int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass, int *ttl, int *rr_len) +static int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass, int *ttl, int *rr_len) { int len = 0; @@ -663,7 +663,7 @@ int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_si return 0; } -int _dns_encode_rr_head(struct dns_context *context, char *domain, int qtype, int qclass, int ttl, int rr_len) +static int _dns_encode_rr_head(struct dns_context *context, char *domain, int qtype, int qclass, int ttl, int rr_len) { int ret = 0; ret = _dns_encode_qr_head(context, domain, qtype, qclass); @@ -681,6 +681,53 @@ int _dns_encode_rr_head(struct dns_context *context, char *domain, int qtype, in return 0; } +static int _dns_encode_raw(struct dns_context *context, struct dns_rrs *rrs) +{ + int ret; + int qtype = 0; + int qclass = 0; + int ttl = 0; + char domain[DNS_MAX_CNAME_LEN]; + int rr_len; + struct dns_data_context data_context; + + data_context.data = rrs->data; + data_context.ptr = rrs->data; + data_context.maxsize = rrs->len; + + ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); + if (ret < 0) { + return -1; + } + + ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, rr_len); + if (ret < 0) { + return -1; + } + + if (_dns_left_len(context) < rr_len) { + return -1; + } + + memcpy(context->ptr, data_context.ptr, rr_len); + context->ptr += rr_len; + data_context.ptr += rr_len; + + return 0; +} + +static int _dns_decode_raw(struct dns_context *context, unsigned char *raw, int len) +{ + if (_dns_left_len(context) < len) { + return -1; + } + + memcpy(raw, context->ptr, len); + context->ptr += len; + return 0; +} + + int _dns_decode_CNAME(struct dns_context *context, char *cname, int cname_size) { int ret = 0; @@ -724,141 +771,13 @@ int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs) if (ret < 0) { return -1; } + data_context.ptr += strnlen((char*)(data_context.ptr), DNS_MAX_CNAME_LEN) + 1; return 0; } -int _dns_decode_A(struct dns_context *context, unsigned char addr[4]) -{ - if (_dns_left_len(context) < DNS_RR_A_LEN) { - return -1; - } - - memcpy(addr, context->ptr, DNS_RR_A_LEN); - context->ptr += DNS_RR_A_LEN; - return 0; -} - -int _dns_encode_A(struct dns_context *context, struct dns_rrs *rrs) -{ - int ret; - int qtype = 0; - int qclass = 0; - int ttl = 0; - char domain[DNS_MAX_CNAME_LEN]; - int rr_len; - struct dns_data_context data_context; - - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; - - ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } - - if (rr_len != DNS_RR_A_LEN) { - return -1; - } - - ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_A_LEN); - if (ret < 0) { - return -1; - } - - if (_dns_left_len(context) < DNS_RR_A_LEN) { - return -1; - } - - memcpy(context->ptr, data_context.ptr, DNS_RR_A_LEN); - context->ptr += DNS_RR_A_LEN; - data_context.ptr += DNS_RR_A_LEN; - - return 0; -} - -int _dns_decode_PTR(struct dns_context *context, char *name, int name_size) -{ - int ret; - - ret = _dns_decode_domain(context, name, name_size); - return ret; -} - -int _dns_encode_PTR(struct dns_context *context, struct dns_rrs *rrs) -{ - return _dns_encode_CNAME(context, rrs); -} - -int _dns_decode_AAAA(struct dns_context *context, unsigned char addr[DNS_RR_AAAA_LEN]) -{ - if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { - return -1; - } - - memcpy(addr, context->ptr, DNS_RR_AAAA_LEN); - context->ptr += DNS_RR_AAAA_LEN; - return 0; -} - -int _dns_encode_AAAA(struct dns_context *context, struct dns_rrs *rrs) -{ - int ret; - int qtype = 0; - int qclass = 0; - int ttl = 0; - char domain[DNS_MAX_CNAME_LEN]; - int rr_len; - struct dns_data_context data_context; - - data_context.data = rrs->data; - data_context.ptr = rrs->data; - data_context.maxsize = rrs->len; - - ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len); - if (ret < 0) { - return -1; - } - - if (rr_len != DNS_RR_AAAA_LEN) { - return -1; - } - - ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, DNS_RR_AAAA_LEN); - if (ret < 0) { - return -1; - } - - if (_dns_left_len(context) < DNS_RR_AAAA_LEN) { - return -1; - } - - memcpy(context->ptr, data_context.ptr, DNS_RR_AAAA_LEN); - context->ptr += DNS_RR_AAAA_LEN; - data_context.ptr += DNS_RR_AAAA_LEN; - - return 0; -} - -int _dns_decode_NS(struct dns_context *context, unsigned char addr[4]) -{ - if (_dns_left_len(context) < DNS_RR_A_LEN) { - return -1; - } - - memcpy(addr, context->ptr, DNS_RR_A_LEN); - context->ptr += DNS_RR_A_LEN; - return 0; -} - -int _dns_encode_NS(struct dns_context *context, struct dns_rrs *rrs) -{ - return _dns_encode_CNAME(context, rrs); -} - -int _dns_decode_qd(struct dns_context *context) +static int _dns_decode_qd(struct dns_context *context) { struct dns_packet *packet = context->packet; int len; @@ -879,7 +798,7 @@ int _dns_decode_qd(struct dns_context *context) return 0; } -int _dns_decode_an(struct dns_context *context, dns_rr_type type) +static int _dns_decode_an(struct dns_context *context, dns_rr_type type) { int ret; int qtype = 0; @@ -900,7 +819,7 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) switch (qtype) { case DNS_T_A: { unsigned char addr[DNS_RR_A_LEN]; - ret = _dns_decode_A(context, addr); + ret = _dns_decode_raw(context, addr, sizeof(addr)); if (ret < 0) { tlog(TLOG_ERROR, "decode A failed, %s", domain); return -1; @@ -942,7 +861,7 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) } break; case DNS_T_PTR: { char name[DNS_MAX_CNAME_LEN]; - ret = _dns_decode_PTR(context, name, DNS_MAX_CNAME_LEN); + ret = _dns_decode_CNAME(context, name, DNS_MAX_CNAME_LEN); if (ret < 0) { tlog(TLOG_ERROR, "decode PTR failed, %s", domain); return -1; @@ -956,7 +875,7 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) } break; case DNS_T_AAAA: { unsigned char addr[DNS_RR_AAAA_LEN]; - ret = _dns_decode_AAAA(context, addr); + ret = _dns_decode_raw(context, addr, sizeof(addr)); if (ret < 0) { tlog(TLOG_ERROR, "decode AAAA failed, %s", domain); return -1; @@ -982,7 +901,7 @@ int _dns_decode_an(struct dns_context *context, dns_rr_type type) return 0; } -int _dns_encode_qd(struct dns_context *context, struct dns_rrs *rrs) +static int _dns_encode_qd(struct dns_context *context, struct dns_rrs *rrs) { int ret; int qtype = 0; @@ -1007,24 +926,24 @@ int _dns_encode_qd(struct dns_context *context, struct dns_rrs *rrs) return 0; } -int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs) +static int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs) { int ret; switch (rrs->type) { case DNS_T_A: { - ret = _dns_encode_A(context, rrs); + ret = _dns_encode_raw(context, rrs); if (ret < 0) { return -1; } } break; case DNS_T_PTR: - ret = _dns_encode_PTR(context, rrs); + ret = _dns_encode_CNAME(context, rrs); if (ret < 0) { return -1; } break; case DNS_T_AAAA: - ret = _dns_encode_AAAA(context, rrs); + ret = _dns_encode_raw(context, rrs); if (ret < 0) { return -1; } @@ -1036,7 +955,7 @@ int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs) return 0; } -int _dns_decode_body(struct dns_context *context) +static int _dns_decode_body(struct dns_context *context) { struct dns_packet *packet = context->packet; struct dns_head *head = &packet->head; @@ -1082,7 +1001,7 @@ int _dns_decode_body(struct dns_context *context) return 0; } -int _dns_encode_body(struct dns_context *context) +static int _dns_encode_body(struct dns_context *context) { struct dns_packet *packet = context->packet; struct dns_head *head = &packet->head; diff --git a/dns_client.c b/dns_client.c index 6a729d7..8113660 100644 --- a/dns_client.c +++ b/dns_client.c @@ -315,7 +315,7 @@ void _dns_client_period_run() pthread_mutex_lock(&client.domain_map_lock); list_for_each_entry_safe(query, tmp, &client.dns_request_list, dns_request_list) { - if (now - query->send_tick >= 2000) { + if (now - query->send_tick >= 1000) { _dns_client_query_remove(query, 1); } } @@ -416,7 +416,7 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long return -1; } - tlog(TLOG_DEBUG, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len)); + tlog(TLOG_INFO, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len)); if (_dns_client_recv(inpacket, len, &from, from_len) != 0) { int fd = open("dns.bin", O_CREAT | O_TRUNC | O_RDWR); diff --git a/dns_server.c b/dns_server.c index ae98806..e662b71 100644 --- a/dns_server.c +++ b/dns_server.c @@ -27,6 +27,8 @@ #include "util.h" #include #include +#include +#include #include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +67,7 @@ struct dns_request { unsigned long send_tick; unsigned short qtype; unsigned short id; + unsigned short rcode; unsigned short ss_family; socklen_t addr_len; union { @@ -115,14 +119,14 @@ void _dns_server_period_run() len = sendto(server.fd, data, len, 0, (struct sockaddr *)&to, to_len); if (len < 0) { - printf("send failed."); + tlog(TLOG_ERROR, "send failed."); } - printf("send.\n"); + tlog(TLOG_ERROR, "send.\n"); } static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len) { - printf("forward request.\n"); + tlog(TLOG_ERROR, "forward request.\n"); return -1; } @@ -166,7 +170,7 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request) return -1; } } - + ret = dns_add_PTR(packet, DNS_RRS_AN, request->domain, 30, hostname); } break; case DNS_T_A: @@ -215,7 +219,8 @@ static int _dns_reply(struct dns_request *request) head.ra = 0; head.aa = 0; head.tc = 0; - head.rcode = DNS_RC_NOERROR; + head.rcode = request->rcode; + ret = dns_packet_init(packet, DNS_PACKSIZE, &head); if (ret != 0) { return -1; @@ -251,13 +256,13 @@ int _dns_server_request_complete(struct dns_request *request) } if (request->qtype == DNS_T_A) { - tlog(TLOG_INFO, "result: %s, %d.%d.%d.%d\n", request->domain, request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], - request->ipv4_addr[3]); + tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], + request->ipv4_addr[2], request->ipv4_addr[3]); } else if (request->qtype == DNS_T_AAAA) { - tlog(TLOG_INFO, "result :%s, %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", request->domain, request->ipv6_addr[0], request->ipv6_addr[1], - request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], - request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13], - request->ipv6_addr[14], request->ipv6_addr[15]); + tlog(TLOG_INFO, "result :%s, rcode: %d, %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", request->domain, request->rcode, request->ipv6_addr[0], + request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6], + request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12], + request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]); } _dns_reply(request); @@ -349,7 +354,7 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos static int _dns_client_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet) { int ttl; - char name[DNS_MAX_CNAME_LEN]; + char name[DNS_MAX_CNAME_LEN] = {0}; char alias[DNS_MAX_CNAME_LEN] = {0}; char ip[DNS_MAX_CNAME_LEN] = {0}; int rr_count; @@ -358,10 +363,15 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, struct dns_rrs *rrs = NULL; if (packet->head.rcode != DNS_RC_NOERROR) { - tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d\n", name, packet->head.rcode); + if (request->rcode == (unsigned short)-1) { + request->rcode = packet->head.rcode; + } + tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d, id = %d\n", domain, packet->head.rcode, packet->head.id); return -1; } + request->rcode = packet->head.rcode; + for (j = 1; j < DNS_RRS_END; j++) { rrs = dns_get_rrs_start(packet, j, &rr_count); for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) { @@ -369,12 +379,12 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, case DNS_T_A: { unsigned char addr[4]; dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); - tlog(TLOG_DEBUG, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); + tlog(TLOG_INFO, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); 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_server_request_get(request); - if (fast_ping_start(ip, 1, 500, _dns_server_ping_result, request) == NULL) { + if (fast_ping_start(ip, 1, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } } @@ -385,7 +395,7 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, sprintf(name, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); _dns_server_request_get(request); - if (fast_ping_start(name, 1, 500, _dns_server_ping_result, request) == NULL) { + if (fast_ping_start(name, 1, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } } break; @@ -435,6 +445,68 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, stru return 0; } +static int _dns_server_process_ptr(struct dns_request *request, struct dns_packet *packet) +{ + struct ifaddrs *ifaddr = NULL; + struct ifaddrs *ifa = NULL; + unsigned char *addr; + char reverse_addr[128] = {0}; + char host_name[DNS_MAX_CNAME_LEN]; + int found = 0; + + if (getifaddrs(&ifaddr) == -1) { + return -1; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) { + continue; + } + + switch (ifa->ifa_addr->sa_family) { + case AF_INET: { + struct sockaddr_in *addr_in; + addr_in = (struct sockaddr_in *)ifa->ifa_addr; + addr = (unsigned char *)&(addr_in->sin_addr.s_addr); + snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1], addr[0]); + } break; + case AF_INET6: { + struct sockaddr_in6 *addr_in6; + addr_in6 = (struct sockaddr_in6 *)ifa->ifa_addr; + if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) { + addr = addr_in6->sin6_addr.s6_addr + 12; + snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1], addr[0]); + } else { + addr = addr_in6->sin6_addr.s6_addr; + snprintf(reverse_addr, sizeof(reverse_addr), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x.in-addr.arpa", addr[15], + addr[14], addr[13], addr[12], addr[11], addr[10], addr[9], addr[8], addr[7], addr[6], addr[5], addr[4], addr[3], addr[2], addr[1], + addr[0]); + } + } break; + default: + break; + } + if (strncmp(request->domain, reverse_addr, sizeof(reverse_addr)) != 0) { + found = 1; + break; + } + } + + if (found == 0) { + goto errout; + } + + _dns_reply(request); + + freeifaddrs(ifaddr); + return 0; +errout: + if (ifaddr) { + freeifaddrs(ifaddr); + } + return -1; +} + static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len) { int decode_len; @@ -451,7 +523,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); if (decode_len < 0) { - printf("decode failed.\n"); + tlog(TLOG_ERROR, "decode failed.\n"); goto errout; } @@ -463,8 +535,9 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so memset(request, 0, sizeof(*request)); request->ttl_v4 = -1; request->ttl_v6 = -1; + request->rcode = -1; if (request == NULL) { - printf("malloc failed.\n"); + tlog(TLOG_ERROR, "malloc failed.\n"); goto errout; } @@ -491,14 +564,20 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so switch (qtype) { case DNS_T_PTR: - ret = _dns_reply(request); - free(request); - return ret; + ret = _dns_server_process_ptr(request, packet); + if (ret == 0) { + free(request); + return ret; + } else { + request->passthrough = 1; + } break; case DNS_T_A: break; + case DNS_T_AAAA: + break; default: - tlog(TLOG_INFO, "unsupport qtype: %d, domain: %s", qtype, request->domain); + tlog(TLOG_DEBUG, "unsupport qtype: %d, domain: %s", qtype, request->domain); request->passthrough = 1; break; } diff --git a/fast_ping.c b/fast_ping.c index 54067f3..db89595 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -519,7 +519,9 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int timeou } memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen); - _fast_ping_sendping(ping_host); + if (_fast_ping_sendping(ping_host) != 0) { + + } hostkey = hash_string(ping_host->host); addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);