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);
} }

View File

@@ -23,6 +23,7 @@
#include "util.h" #include "util.h"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
@@ -75,6 +76,8 @@ struct ping_host_struct {
int count; int count;
int send; int send;
unsigned int sid; unsigned int sid;
unsigned short port;
unsigned short ss_family;
union { union {
struct sockaddr addr; struct sockaddr addr;
struct sockaddr_in6 in6; struct sockaddr_in6 in6;
@@ -177,7 +180,7 @@ void _fast_ping_install_filter_v4(int sock)
} }
} }
static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int protocol) static struct addrinfo *_fast_ping_getaddr(const char *host, const char *port, int type, int protocol)
{ {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *result = NULL; struct addrinfo *result = NULL;
@@ -186,7 +189,7 @@ static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int proto
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = type; hints.ai_socktype = type;
hints.ai_protocol = protocol; hints.ai_protocol = protocol;
if (getaddrinfo(host, NULL, &hints, &result) != 0) { if (getaddrinfo(host, port, &hints, &result) != 0) {
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno)); tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
goto errout; goto errout;
} }
@@ -231,8 +234,16 @@ static void _fast_ping_host_get(struct ping_host_struct *ping_host)
atomic_inc(&ping_host->ref); atomic_inc(&ping_host->ref);
} }
static void _fast_ping_host_put(struct ping_host_struct *ping_host) static void _fast_ping_host_put_locked(struct ping_host_struct *ping_host, int locked)
{ {
if (locked) {
if (atomic_dec_and_test(&ping_host->ref)) {
hash_del(&ping_host->host_node);
hash_del(&ping_host->addr_node);
} else {
ping_host = NULL;
}
} else {
pthread_mutex_lock(&ping.map_lock); pthread_mutex_lock(&ping.map_lock);
if (atomic_dec_and_test(&ping_host->ref)) { if (atomic_dec_and_test(&ping_host->ref)) {
hash_del(&ping_host->host_node); hash_del(&ping_host->host_node);
@@ -241,6 +252,7 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
ping_host = NULL; ping_host = NULL;
} }
pthread_mutex_unlock(&ping.map_lock); pthread_mutex_unlock(&ping.map_lock);
}
if (ping_host == NULL) { if (ping_host == NULL) {
return; return;
@@ -252,29 +264,17 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tv, ping_host->userptr); ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tv, ping_host->userptr);
if (ping_host->fd > 0) {
close(ping_host->fd);
ping_host->fd = -1;
}
free(ping_host); free(ping_host);
} }
static void _fast_ping_host_put_locked(struct ping_host_struct *ping_host) static void _fast_ping_host_put(struct ping_host_struct *ping_host)
{ {
if (atomic_dec_and_test(&ping_host->ref)) { _fast_ping_host_put_locked(ping_host, 0);
hash_del(&ping_host->host_node);
hash_del(&ping_host->addr_node);
} else {
ping_host = NULL;
}
if (ping_host == NULL) {
return;
}
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tv, ping_host->userptr);
free(ping_host);
} }
static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
@@ -296,7 +296,7 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
packet->msg.seq = ping_host->seq; packet->msg.seq = ping_host->seq;
icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
len = sendto(ping_host->fd, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len); len = sendto(ping.fd_icmp6, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
if (len < 0 || len != sizeof(struct fast_ping_packet)) { if (len < 0 || len != sizeof(struct fast_ping_packet)) {
if (errno == ENETUNREACH) { if (errno == ENETUNREACH) {
goto errout; goto errout;
@@ -332,7 +332,7 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
packet->msg.seq = ping_host->seq; packet->msg.seq = ping_host->seq;
icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
len = sendto(ping_host->fd, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len); len = sendto(ping.fd_icmp, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
if (len < 0 || len != sizeof(struct fast_ping_packet)) { if (len < 0 || len != sizeof(struct fast_ping_packet)) {
if (errno == ENETUNREACH) { if (errno == ENETUNREACH) {
goto errout; goto errout;
@@ -349,6 +349,53 @@ errout:
return -1; return -1;
} }
static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
{
struct epoll_event event;
int flags;
int fd = 0;
fd = socket(ping_host->ss_family, SOCK_STREAM, 0);
if (fd < 0) {
goto errout;
}
flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
ping_host->seq++;
if (connect(fd, (struct sockaddr *)&ping_host->addr, ping_host->addr_len) != 0) {
if (errno != EINPROGRESS) {
char ping_host_name[PING_MAX_HOSTLEN];
if (errno == ENETUNREACH) {
goto errout;
}
tlog(TLOG_ERROR, "connect %s, id %d, %s", gethost_by_addr(ping_host_name, (struct sockaddr *)&ping_host->addr, ping_host->addr_len), ping_host->sid,
strerror(errno));
goto errout;
}
}
event.events = EPOLLIN | EPOLLOUT;
event.data.ptr = ping_host;
if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
goto errout;
}
if (ping_host->fd > 0) {
close(ping_host->fd);
}
ping_host->fd = fd;
return 0;
errout:
if (fd > 0) {
close(fd);
}
return -1;
}
static int _fast_ping_sendping(struct ping_host_struct *ping_host) static int _fast_ping_sendping(struct ping_host_struct *ping_host)
{ {
int ret = -1; int ret = -1;
@@ -357,6 +404,8 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
ret = _fast_ping_sendping_v4(ping_host); ret = _fast_ping_sendping_v4(ping_host);
} else if (ping_host->type == FAST_PING_ICMP6) { } else if (ping_host->type == FAST_PING_ICMP6) {
ret = _fast_ping_sendping_v6(ping_host); ret = _fast_ping_sendping_v6(ping_host);
} else if (ping_host->type == FAST_PING_TCP) {
ret = _fast_ping_sendping_tcp(ping_host);
} }
ping_host->send = 1; ping_host->send = 1;
@@ -369,7 +418,7 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
return 0; return 0;
} }
static int _fast_ping_create_sock(FAST_PING_TYPE type) static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
{ {
int fd = -1; int fd = -1;
struct ping_host_struct *icmp_host = NULL; struct ping_host_struct *icmp_host = NULL;
@@ -440,7 +489,7 @@ static int _fast_ping_create_icmp(FAST_PING_TYPE type)
goto out; goto out;
} }
fd = _fast_ping_create_sock(type); fd = _fast_ping_create_icmp_sock(type);
if (fd < 0) { if (fd < 0) {
goto errout; goto errout;
} }
@@ -476,10 +525,31 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
int icmp_proto = 0; int icmp_proto = 0;
uint32_t hostkey; uint32_t hostkey;
uint32_t addrkey; uint32_t addrkey;
int fd = -1; char ip_str[PING_MAX_HOSTLEN];
char port_str[MAX_IP_LEN];
char *service = NULL;
int port = -1;
FAST_PING_TYPE type; FAST_PING_TYPE type;
int socktype = 0;
domain = _fast_ping_getdomain(host); if (parse_ip(host, ip_str, &port) != 0) {
goto errout;
}
if (port > 0) {
icmp_proto = 0;
socktype = SOCK_STREAM;
snprintf(port_str, MAX_IP_LEN, "%d", port);
service = port_str;
type = FAST_PING_TCP;
gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
if (gai == NULL) {
goto errout;
}
} else {
socktype = SOCK_RAW;
domain = _fast_ping_getdomain(ip_str);
if (domain < 0) { if (domain < 0) {
return NULL; return NULL;
} }
@@ -498,15 +568,15 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
break; break;
} }
fd = _fast_ping_create_icmp(type); if (_fast_ping_create_icmp(type) < 0) {
if (fd < 0) {
goto errout; goto errout;
} }
gai = _fast_ping_getaddr(host, SOCK_RAW, icmp_proto); gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
if (gai == NULL) { if (gai == NULL) {
goto errout; goto errout;
} }
}
ping_host = malloc(sizeof(*ping_host)); ping_host = malloc(sizeof(*ping_host));
if (ping_host == NULL) { if (ping_host == NULL) {
@@ -515,7 +585,7 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
memset(ping_host, 0, sizeof(*ping_host)); memset(ping_host, 0, sizeof(*ping_host));
strncpy(ping_host->host, host, PING_MAX_HOSTLEN); strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
ping_host->fd = fd; ping_host->fd = -1;
ping_host->timeout = timeout; ping_host->timeout = timeout;
ping_host->count = count; ping_host->count = count;
ping_host->type = type; ping_host->type = type;
@@ -529,6 +599,8 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
} }
ping_host->interval = (timeout > interval) ? timeout : interval; ping_host->interval = (timeout > interval) ? timeout : interval;
ping_host->addr_len = gai->ai_addrlen; ping_host->addr_len = gai->ai_addrlen;
ping_host->port = port;
ping_host->ss_family = gai->ai_family;
if (gai->ai_addrlen > sizeof(struct sockaddr_in6)) { if (gai->ai_addrlen > sizeof(struct sockaddr_in6)) {
goto errout; goto errout;
} }
@@ -536,7 +608,7 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
tlog(TLOG_DEBUG, "ping %s, id = %d", host, ping_host->sid); tlog(TLOG_DEBUG, "ping %s, id = %d", host, ping_host->sid);
if (_fast_ping_sendping(ping_host) != 0) { if (_fast_ping_sendping(ping_host) != 0) {
goto errout1; goto errout;
} }
hostkey = hash_string(ping_host->host); hostkey = hash_string(ping_host->host);
@@ -550,13 +622,8 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int interv
freeaddrinfo(gai); freeaddrinfo(gai);
return ping_host; return ping_host;
errout: errout:
if (fd > 0) {
close(fd);
}
errout1:
if (gai) { if (gai) {
freeaddrinfo(gai); freeaddrinfo(gai);
} }
@@ -736,7 +803,48 @@ errout:
return -1; return -1;
} }
static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval *now) static int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct epoll_event *event, struct timeval *now)
{
struct timeval tvresult = *now;
struct timeval *tvsend = &ping_host->last;
int connect_error = 0;
socklen_t len = sizeof(connect_error);
if (event->events & EPOLLIN || event->events & EPOLLERR) {
if (getsockopt(ping_host->fd, SOL_SOCKET, SO_ERROR, (char *)&connect_error, &len) != 0) {
goto errout;
}
if (connect_error != 0 && connect_error != ECONNREFUSED) {
goto errout;
}
}
tv_sub(&tvresult, tvsend);
if (ping_host->ping_callback) {
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len,
ping_host->seq, &tvresult, ping_host->userptr);
}
ping_host->send = 0;
if (ping_host->fd > 0) {
close(ping_host->fd);
ping_host->fd = -1;
}
if (ping_host->count == 1) {
_fast_ping_host_put(ping_host);
}
return 0;
errout:
if (ping_host->fd > 0) {
close(ping_host->fd);
ping_host->fd = -1;
}
return -1;
}
static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_event *event, struct timeval *now)
{ {
int ret = -1; int ret = -1;
@@ -745,6 +853,8 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval
case FAST_PING_ICMP: case FAST_PING_ICMP:
ret = _fast_ping_process_icmp(ping_host, now); ret = _fast_ping_process_icmp(ping_host, now);
break; break;
case FAST_PING_TCP:
ret = _fast_ping_process_tcp(ping_host, event, now);
default: default:
break; break;
} }
@@ -782,7 +892,7 @@ static void _fast_ping_period_run()
if (ping_host->count == 1) { if (ping_host->count == 1) {
hash_del(&ping_host->host_node); hash_del(&ping_host->host_node);
hash_del(&ping_host->addr_node); hash_del(&ping_host->addr_node);
_fast_ping_host_put_locked(ping_host); _fast_ping_host_put_locked(ping_host, 1);
continue; continue;
} }
ping_host->count--; ping_host->count--;
@@ -828,7 +938,7 @@ static void *_fast_ping_work(void *arg)
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
struct epoll_event *event = &events[i]; struct epoll_event *event = &events[i];
struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr; struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr;
_fast_ping_process(ping_host, &now); _fast_ping_process(ping_host, event, &now);
} }
} }

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