Add TCP ping

This commit is contained in:
Nick Peng
2018-06-10 00:29:07 +08:00
parent b05dd784bc
commit ec83f75582
9 changed files with 898 additions and 686 deletions

13
conf.c
View File

@@ -11,19 +11,14 @@
#define DEFAULT_DNS_CACHE_SIZE 512 #define DEFAULT_DNS_CACHE_SIZE 512
int dns_conf_port = DEFAULT_DNS_PORT; char dns_conf_server_ip[DNS_MAX_IPLEN];
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE; int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
int dns_conf_server_num; int dns_conf_server_num;
int config_port(char *value) int config_bind(char *value)
{ {
int port = atoi(value); strncpy(dns_conf_server_ip, value, DNS_MAX_IPLEN);
if (port <= 0 || port >= 65535) {
return -1;
}
dns_conf_port = port;
return 0; return 0;
} }
@@ -88,7 +83,7 @@ struct config_item {
}; };
struct config_item config_item[] = { struct config_item config_item[] = {
{"port", config_port}, {"bind", config_bind},
{"server", config_server_udp}, {"server", config_server_udp},
{"server-tcp", config_server_tcp}, {"server-tcp", config_server_tcp},
{"server-http", config_server_http}, {"server-http", config_server_http},

2
conf.h
View File

@@ -17,7 +17,7 @@ struct dns_servers {
dns_conf_server_type_t type; dns_conf_server_type_t type;
}; };
extern int dns_conf_port; extern char dns_conf_server_ip[DNS_MAX_IPLEN];
extern int dns_conf_cachesize; extern int dns_conf_cachesize;
extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
extern int dns_conf_server_num; extern int dns_conf_server_num;

View File

@@ -55,8 +55,8 @@ struct dns_server {
int fd; int fd;
pthread_mutex_t map_lock; pthread_mutex_t request_list_lock;
DECLARE_HASHTABLE(hostmap, 6); struct list_head request_list;
}; };
struct dns_ip_address { struct dns_ip_address {
@@ -71,7 +71,7 @@ struct dns_ip_address {
struct dns_request { struct dns_request {
atomic_t refcnt; atomic_t refcnt;
struct hlist_node map; struct list_head list;
char domain[DNS_MAX_CNAME_LEN]; char domain[DNS_MAX_CNAME_LEN];
struct dns_head head; struct dns_head head;
unsigned long send_tick; unsigned long send_tick;
@@ -86,6 +86,9 @@ struct dns_request {
struct sockaddr addr; struct sockaddr addr;
}; };
int has_ping_result;
int has_ping_tcp;
int has_ptr; int has_ptr;
int has_cname; int has_cname;
@@ -106,13 +109,12 @@ struct dns_request {
int passthrough; int passthrough;
pthread_mutex_t ip_map_lock;
DECLARE_HASHTABLE(ip_map, 4); DECLARE_HASHTABLE(ip_map, 4);
}; };
static struct dns_server server; static struct dns_server server;
void _dns_server_period_run() {}
static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len) static int _dns_server_forward_request(unsigned char *inpacket, int inpacket_len)
{ {
tlog(TLOG_ERROR, "forward request.\n"); tlog(TLOG_ERROR, "forward request.\n");
@@ -255,10 +257,10 @@ int _dns_server_request_complete(struct dns_request *request)
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1], 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]); request->ipv4_addr[2], request->ipv4_addr[3]);
} else if (request->qtype == DNS_T_AAAA) { } else if (request->qtype == DNS_T_AAAA) {
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], tlog(TLOG_INFO, "result :%s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
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[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
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[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]); request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
} }
_dns_reply(request); _dns_reply(request);
@@ -266,7 +268,7 @@ int _dns_server_request_complete(struct dns_request *request)
return ret; return ret;
} }
void _dns_server_request_release(struct dns_request *request) void _dns_server_request_release_lock(struct dns_request *request, int locked)
{ {
struct dns_ip_address *addr_map; struct dns_ip_address *addr_map;
struct hlist_node *tmp; struct hlist_node *tmp;
@@ -281,16 +283,30 @@ void _dns_server_request_release(struct dns_request *request)
return; return;
} }
if (locked == 0) {
pthread_mutex_lock(&server.request_list_lock);
list_del(&request->list);
pthread_mutex_unlock(&server.request_list_lock);
} else {
list_del(&request->list);
}
_dns_server_request_complete(request); _dns_server_request_complete(request);
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node) hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
{ {
hash_del(&addr_map->node); hash_del(&addr_map->node);
free(addr_map); free(addr_map);
} }
pthread_mutex_destroy(&request->ip_map_lock);
memset(request, 0, sizeof(*request)); memset(request, 0, sizeof(*request));
free(request); free(request);
} }
void _dns_server_request_release(struct dns_request *request)
{
_dns_server_request_release_lock(request, 0);
}
void _dns_server_request_get(struct dns_request *request) void _dns_server_request_get(struct dns_request *request)
{ {
atomic_inc(&request->refcnt); atomic_inc(&request->refcnt);
@@ -343,6 +359,7 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
break; break;
} }
if (result == PING_RESULT_RESPONSE) { if (result == PING_RESULT_RESPONSE) {
request->has_ping_result = 1;
tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt); tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
} else { } else {
tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno); tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno);
@@ -374,18 +391,22 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
} }
key = jhash(addr, addr_len, 0); key = jhash(addr, addr_len, 0);
pthread_mutex_lock(&request->ip_map_lock);
hash_for_each_possible(request->ip_map, addr_map, node, key) hash_for_each_possible(request->ip_map, addr_map, node, key)
{ {
if (addr_type == DNS_T_A) { if (addr_type == DNS_T_A) {
if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) { if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) {
pthread_mutex_unlock(&request->ip_map_lock);
return -1; return -1;
} }
} else if (addr_type == DNS_T_AAAA) { } else if (addr_type == DNS_T_AAAA) {
if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) { if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) {
pthread_mutex_unlock(&request->ip_map_lock);
return -1; return -1;
} }
} }
} }
pthread_mutex_unlock(&request->ip_map_lock);
addr_map = malloc(sizeof(*addr_map)); addr_map = malloc(sizeof(*addr_map));
if (addr_map == NULL) { if (addr_map == NULL) {
@@ -418,7 +439,6 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
return -1; return -1;
} }
request->rcode = packet->head.rcode; request->rcode = packet->head.rcode;
for (j = 1; j < DNS_RRS_END; j++) { for (j = 1; j < DNS_RRS_END; j++) {
@@ -467,11 +487,12 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
break; break;
} }
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", name, ttl, addr[0], addr[1], addr[2], addr[3], addr[4], tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); 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]);
sprintf(name, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", 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]);
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]);
if (fast_ping_start(name, 1, 0, 1000, _dns_server_ping_result, request) == NULL) { if (fast_ping_start(name, 1, 0, 1000, _dns_server_ping_result, request) == NULL) {
_dns_server_request_release(request); _dns_server_request_release(request);
} }
@@ -625,6 +646,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
request = malloc(sizeof(*request)); request = malloc(sizeof(*request));
memset(request, 0, sizeof(*request)); memset(request, 0, sizeof(*request));
pthread_mutex_init(&request->ip_map_lock, 0);
request->ttl_v4 = -1; request->ttl_v4 = -1;
request->ttl_v6 = -1; request->ttl_v6 = -1;
request->rcode = DNS_RC_SERVFAIL; request->rcode = DNS_RC_SERVFAIL;
@@ -676,6 +698,11 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
} }
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype); tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype);
pthread_mutex_lock(&server.request_list_lock);
list_add_tail(&request->list, &server.request_list);
pthread_mutex_unlock(&server.request_list_lock);
_dns_server_request_get(request); _dns_server_request_get(request);
request->send_tick = get_tick_count(); request->send_tick = get_tick_count();
dns_client_query(request->domain, qtype, dns_server_resolve_callback, request); dns_client_query(request->domain, qtype, dns_server_resolve_callback, request);
@@ -705,13 +732,74 @@ static int _dns_server_process(unsigned long now)
return _dns_server_recv(inpacket, len, &from, from_len); return _dns_server_recv(inpacket, len, &from, from_len);
} }
void _dns_server_tcp_ping_check(struct dns_request *request)
{
struct dns_ip_address *addr_map;
int bucket = 0;
char name[DNS_MAX_CNAME_LEN] = {0};
char ip[DNS_MAX_CNAME_LEN] = {0};
if (request->has_ping_result) {
return;
}
if (request->has_ping_tcp) {
return;
}
pthread_mutex_lock(&request->ip_map_lock);
hash_for_each(request->ip_map, bucket, addr_map, node)
{
switch (addr_map->addr_type) {
case DNS_T_A: {
_dns_server_request_get(request);
sprintf(ip, "%d.%d.%d.%d:80", addr_map->ipv4_addr[0], addr_map->ipv4_addr[1], addr_map->ipv4_addr[2], addr_map->ipv4_addr[3]);
if (fast_ping_start(ip, 1, 0, 1000, _dns_server_ping_result, request) == NULL) {
_dns_server_request_release_lock(request, 1);
}
} break;
case DNS_T_AAAA: {
_dns_server_request_get(request);
sprintf(name, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]:80", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
addr_map->ipv6_addr[2], addr_map->ipv6_addr[3], addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6],
addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);
if (fast_ping_start(name, 1, 0, 1000, _dns_server_ping_result, request) == NULL) {
_dns_server_request_release_lock(request, 1);
}
} break;
default:
break;
}
}
pthread_mutex_unlock(&request->ip_map_lock);
request->has_ping_tcp = 1;
}
void _dns_server_period_run()
{
struct dns_request *request, *tmp;
unsigned long now = get_tick_count();
pthread_mutex_lock(&server.request_list_lock);
list_for_each_entry_safe(request, tmp, &server.request_list, list)
{
if (request->send_tick < now - 500 && request->has_ping_tcp == 0) {
_dns_server_tcp_ping_check(request);
}
}
pthread_mutex_unlock(&server.request_list_lock);
}
int dns_server_run(void) int dns_server_run(void)
{ {
struct epoll_event events[DNS_MAX_EVENTS + 1]; struct epoll_event events[DNS_MAX_EVENTS + 1];
int num; int num;
int i; int i;
unsigned long now = {0}; unsigned long now = {0};
int sleep = 1000; int sleep = 100;
int sleep_time = 0; int sleep_time = 0;
unsigned long expect_time = 0; unsigned long expect_time = 0;
@@ -798,9 +886,20 @@ int dns_server_socket(void)
int fd = -1; int fd = -1;
struct addrinfo *gai = NULL; struct addrinfo *gai = NULL;
char port_str[8]; char port_str[8];
char ip[MAX_IP_LEN];
int port;
char *host = NULL;
snprintf(port_str, sizeof(port_str), "%d", dns_conf_port); if (parse_ip(dns_conf_server_ip, ip, &port) == 0) {
gai = _dns_server_getaddr(NULL, port_str, SOCK_DGRAM, 0); host = ip;
}
if (port <= 0) {
port = DEFAULT_DNS_PORT;
}
snprintf(port_str, sizeof(port_str), "%d", port);
gai = _dns_server_getaddr(host, port_str, SOCK_DGRAM, 0);
if (gai == NULL) { if (gai == NULL) {
tlog(TLOG_ERROR, "get address failed.\n"); tlog(TLOG_ERROR, "get address failed.\n");
goto errout; goto errout;
@@ -857,8 +956,8 @@ int dns_server_init(void)
goto errout; goto errout;
} }
pthread_mutex_init(&server.map_lock, 0); pthread_mutex_init(&server.request_list_lock, 0);
hash_init(server.hostmap); INIT_LIST_HEAD(&server.request_list);
server.epoll_fd = epollfd; server.epoll_fd = epollfd;
server.fd = fd; server.fd = fd;
server.run = 1; server.run = 1;
@@ -880,7 +979,7 @@ errout:
close(epollfd); close(epollfd);
} }
pthread_mutex_destroy(&server.map_lock); pthread_mutex_destroy(&server.request_list_lock);
return -1; return -1;
} }
@@ -894,5 +993,5 @@ void dns_server_exit(void)
server.fd = -1; server.fd = -1;
} }
pthread_mutex_destroy(&server.map_lock); pthread_mutex_destroy(&server.request_list_lock);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -116,7 +116,7 @@ int smartdns_init()
} }
tlog_setlogscreen(1); tlog_setlogscreen(1);
tlog_setlevel(TLOG_INFO); tlog_setlevel(TLOG_ERROR);
if (dns_conf_server_num <= 0) { if (dns_conf_server_num <= 0) {
if (smartdns_load_from_resolv() != 0) { if (smartdns_load_from_resolv() != 0) {
@@ -142,7 +142,6 @@ int smartdns_init()
tlog(TLOG_ERROR, "start dns client failed.\n"); tlog(TLOG_ERROR, "start dns client failed.\n");
goto errout; goto errout;
} }
ret = smartdns_add_servers(); ret = smartdns_add_servers();
if (ret != 0) { if (ret != 0) {
tlog(TLOG_ERROR, "add servers failed."); tlog(TLOG_ERROR, "add servers failed.");

View File

@@ -1,6 +1,6 @@
# port # bind
port 53 bind [::]:53
cache-size 1024 cache-size 1024
loglevel info loglevel info
@@ -11,7 +11,7 @@ server 123.207.137.88
server 119.29.29.29 server 119.29.29.29
server 223.5.5.5 server 223.5.5.5
server 208.67.222.222:5353 server 208.67.222.222:5353
#server 202.141.178.13:5353 server 202.141.178.13:5353
#server 77.88.8.8:53 #server 77.88.8.8:53
#server 202.141.162.123:53 #server 202.141.162.123:53
#server 101.132.183.99:53 #server 101.132.183.99:53

17
util.c
View File

@@ -44,11 +44,13 @@ errout:
return NULL; return NULL;
} }
int parse_ip(char *value, char *ip, int *port) int parse_ip(const char *value, char *ip, int *port)
{ {
int offset = 0; int offset = 0;
char *colon = NULL; char *colon = NULL;
colon = strstr(value, ":");
if (strstr(value, "[")) { if (strstr(value, "[")) {
/* ipv6 with port */ /* ipv6 with port */
char *bracket_end = strstr(value, "]"); char *bracket_end = strstr(value, "]");
@@ -60,9 +62,11 @@ int parse_ip(char *value, char *ip, int *port)
memcpy(ip, value + 1, offset); memcpy(ip, value + 1, offset);
ip[offset] = 0; ip[offset] = 0;
colon = bracket_end + 1; colon = strstr(bracket_end, ":");
if (colon) {
} else if (strstr(value, "::")) { colon++;
}
} else if (colon && strstr(colon + 1, ":")) {
/* ipv6 without port */ /* ipv6 without port */
strncpy(ip, value, MAX_IP_LEN); strncpy(ip, value, MAX_IP_LEN);
colon = NULL; colon = NULL;
@@ -77,6 +81,7 @@ int parse_ip(char *value, char *ip, int *port)
offset = colon - value; offset = colon - value;
colon++; colon++;
memcpy(ip, value, offset); memcpy(ip, value, offset);
ip[offset] = 0;
} }
} }
@@ -87,5 +92,9 @@ int parse_ip(char *value, char *ip, int *port)
*port = PORT_NOT_DEFINED; *port = PORT_NOT_DEFINED;
} }
if (ip[0] == 0) {
return -1;
}
return 0; return 0;
} }

2
util.h
View File

@@ -12,6 +12,6 @@ unsigned long get_tick_count();
char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len); char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len);
int parse_ip(char *value, char *ip, int *port); int parse_ip(const char *value, char *ip, int *port);
#endif #endif