diff --git a/Makefile b/Makefile index a8aec48..79ae261 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BIN=smartdns -OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o +OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o dns.o util.o CFLAGS=-g -O0 -Wall CFLAGS +=-Iinclude CXXFLAGS=-g -O0 -Wall -std=c++11 diff --git a/dns.h b/dns.h index bf9fa3f..b5c62ab 100644 --- a/dns.h +++ b/dns.h @@ -10,7 +10,7 @@ #define DNS_RR_AAAA_LEN 16 #define DNS_MAX_CNAME_LEN 256 #define DNS_IN_PACKSIZE 512 -#define DNS_PACKSIZE (512 * 2) +#define DNS_PACKSIZE (512 * 4) typedef enum dns_rr_type { DNS_RRS_QD = 0, diff --git a/dns_client.c b/dns_client.c index 73fa503..a49bafc 100644 --- a/dns_client.c +++ b/dns_client.c @@ -21,6 +21,8 @@ #include "dns.h" #include "fast_ping.h" #include "hashtable.h" +#include "list.h" +#include "util.h" #include #include #include @@ -56,78 +58,357 @@ struct dns_client { int run; int epoll_fd; + pthread_mutex_t server_list_lock; struct list_head dns_server_list; - pthread_mutex_t map_lock; - DECLARE_HASHTABLE(hostmap, 6); + pthread_mutex_t dns_request_lock; + struct list_head dns_request_list; + struct list_head dns_request_wait_list; + + pthread_mutex_t domain_map_lock; + DECLARE_HASHTABLE(domain_map, 6); int udp; - int tcp; }; + +struct dns_server_info { + struct list_head list; + dns_server_type_t type; + unsigned short ss_family; + socklen_t addr_len; + union { + struct sockaddr_in in; + struct sockaddr_in6 in6; + struct sockaddr addr; + }; +}; + struct dns_query_struct { - char domain[DNS_MAX_HOSTNAME]; - struct hlist_node host_node; + atomic_t refcnt; + struct list_head dns_request_list; + struct hlist_node domain_node; + char domain[DNS_MAX_CNAME_LEN]; + int dns_request_sent; void *user_ptr; + unsigned long send_tick; + dns_client_callback callback; + struct dns_result result; }; static struct dns_client client; -static dns_client_callback dns_callback; - -static void tv_sub(struct timeval *out, struct timeval *in) +static struct addrinfo *_dns_client_getaddr(const char *host, char *port, int type, int protocol) { - if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ - --out->tv_sec; - out->tv_usec += 1000000; + struct addrinfo hints; + struct addrinfo *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = type; + hints.ai_protocol = protocol; + if (getaddrinfo(host, port, &hints, &result) != 0) { + fprintf(stderr, "get addr info failed. %s\n", strerror(errno)); + goto errout; } - out->tv_sec -= in->tv_sec; + + return result; +errout: + if (result) { + freeaddrinfo(result); + } + return NULL; +} + +int _dns_client_server_exist(struct addrinfo *gai, dns_server_type_t server_type) +{ + struct dns_server_info *server_info, *tmp; + pthread_mutex_lock(&client.server_list_lock); + list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list) + { + if (server_info->addr_len != gai->ai_addrlen || server_info->ss_family != gai->ai_family) { + continue; + } + + if (server_info->type != server_type) { + continue; + } + + if (memcmp(&server_info->addr, gai->ai_addr, gai->ai_addrlen) != 0) { + continue; + } + pthread_mutex_lock(&client.server_list_lock); + return 0; + } + pthread_mutex_unlock(&client.server_list_lock); + return -1; +} + +int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type) +{ + struct dns_server_info *server_info = NULL; + + if (_dns_client_server_exist(gai, server_type) == 0) { + goto errout; + } + + server_info = malloc(sizeof(*server_info)); + if (server_info == NULL) { + goto errout; + } + memset(server_info, 0, sizeof(*server_info)); + server_info->ss_family = gai->ai_family; + server_info->addr_len = gai->ai_addrlen; + server_info->type = server_type; + if (gai->ai_addrlen > sizeof(server_info->addr)) { + goto errout; + } + memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen); + pthread_mutex_lock(&client.server_list_lock); + list_add(&server_info->list, &client.dns_server_list); + pthread_mutex_unlock(&client.server_list_lock); + + if (fast_ping_start(server_ip, 0, 60000, NULL, server_info) != 0) { + goto errout; + } + return 0; +errout: + if (server_info) { + free(server_info); + } + + return -1; +} + +int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_type_t server_type) +{ + struct dns_server_info *server_info, *tmp; + pthread_mutex_lock(&client.server_list_lock); + list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list) + { + if (server_info->addr_len != gai->ai_addrlen || server_info->ss_family != gai->ai_family) { + continue; + } + + if (memcmp(&server_info->addr, gai->ai_addr, gai->ai_addrlen) != 0) { + continue; + } + list_del(&server_info->list); + pthread_mutex_unlock(&client.server_list_lock); + if (fast_ping_stop(server_ip) != 0) { + printf("stop ping failed.\n"); + } + free(server_info); + return 0; + } + pthread_mutex_unlock(&client.server_list_lock); + return -1; +} + +int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t server_type, int operate) +{ + char port_s[8]; + int sock_type; + int ret; + struct addrinfo *gai = NULL; + + if (server_type >= DNS_SERVER_TYPE_END) { + return -1; + } + + if (server_type == DNS_SERVER_UDP) { + sock_type = SOCK_DGRAM; + } else { + sock_type = SOCK_STREAM; + } + + snprintf(port_s, 8, "%d", port); + gai = _dns_client_getaddr(server_ip, port_s, sock_type, 0); + if (gai == NULL) { + goto errout; + } + + if (operate == 0) { + ret = _dns_client_server_add(server_ip, gai, server_type); + if (ret != 0) { + goto errout; + } + } else { + ret = _dns_client_server_remove(server_ip, gai, server_type); + if (ret != 0) { + goto errout; + } + } + freeaddrinfo(gai); + return 0; +errout: + if (gai) { + freeaddrinfo(gai); + } + return -1; +} + +int dns_add_server(char *server_ip, int port, dns_server_type_t server_type) +{ + return _dns_client_server_operate(server_ip, port, server_type, 0); +} + +int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type) +{ + return _dns_client_server_operate(server_ip, port, server_type, 1); +} + + +int _dns_client_query_complete(struct dns_query_struct *query) +{ + int ret = -1; + if (query->callback) { + ret = query->callback(query->domain, &query->result, query->user_ptr); + } + + return ret; +} + + +void _dns_client_query_release(struct dns_query_struct *query) +{ + if (!atomic_dec_and_test(&query->refcnt)) { + return; + } + + pthread_mutex_lock(&client.domain_map_lock); + list_del(&query->dns_request_list); + hash_del(&query->domain_node); + pthread_mutex_unlock(&client.domain_map_lock); + _dns_client_query_complete(query); + free(query); +} + +void _dns_client_query_get(struct dns_query_struct *query) +{ + atomic_inc(&query->refcnt); +} + +void dns_client_ping_result(const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, struct timeval *tv, void *userptr) +{ + struct dns_query_struct *query = userptr; + + if (query == NULL) { + return; + } + + unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100; + + switch (addr->sa_family) { + case AF_INET: { + struct sockaddr_in *addr_in; + addr_in = (struct sockaddr_in *)addr; + if (query->result.ttl_v4 > rtt) { + query->result.ttl_v4 = rtt; + memcpy(query->result.addr_ipv4, &addr_in->sin_addr.s_addr, 4); + } + } break; + case AF_INET6: { + struct sockaddr_in6 *addr_in6; + addr_in6 = (struct sockaddr_in6 *)addr; + if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) { + if (query->result.ttl_v4 > rtt) { + query->result.ttl_v4 = rtt; + memcpy(query->result.addr_ipv4, addr_in6->sin6_addr.s6_addr + 12, 4); + } + } else { + if (query->result.ttl_v6 > rtt) { + query->result.ttl_v6 = rtt; + memcpy(query->result.addr_ipv6, addr_in6->sin6_addr.s6_addr, 16); + } + } + } break; + default: + break; + } + printf("from %15s: seq=%d time=%d\n", host, seqno, rtt); + _dns_client_query_release(query); } void _dns_client_period_run() { + struct dns_query_struct *query, *tmp; + unsigned long now = get_tick_count(); + 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 > 500) { + } + } + pthread_mutex_unlock(&client.domain_map_lock); + return; } -static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len) +static struct dns_query_struct *_dns_client_get_request(char *domain) { - int len; - int i; - int j; - int qtype; - int qclass; + struct dns_query_struct *query = NULL; + struct hlist_node *tmp = NULL; + + pthread_mutex_lock(&client.domain_map_lock); + hash_for_each_possible_safe(client.domain_map, query, tmp, domain_node, hash_string(domain)) + { + if (strncmp(query->domain, domain, DNS_MAX_CNAME_LEN) != 0) { + continue; + } + break; + } + pthread_mutex_unlock(&client.domain_map_lock); + + return query; +} + +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]; int rr_count; + int i = 0; + int j = 0; struct dns_rrs *rrs = NULL; - unsigned char packet_buff[DNS_PACKSIZE]; - struct dns_packet *packet = (struct dns_packet *)packet_buff; + int ret = -1; + int A_num = 0; - len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); - if (len != 0) { - printf("decode failed.\n"); + query = _dns_client_get_request(domain); + if (query == NULL) { return -1; } - printf("qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d\n", packet->head.qdcount, packet->head.ancount, packet->head.nscount, - packet->head.nrcount, inpacket_len); - - 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)) { - dns_get_domain(rrs, name, 128, &qtype, &qclass); - printf("domain: %s qtype: %d qclass: %d\n", name, qtype, qclass); - } - 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)) { switch (rrs->type) { case DNS_T_A: { unsigned char addr[4]; - dns_get_A(rrs, name, 128, &ttl, addr); + 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]); - dns_callback(name, addr, DNS_T_A, 0); + 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, 900, dns_client_ping_result, query) != 0) { + _dns_client_query_release(query); + } + A_num++; + } break; + case DNS_T_AAAA: { + unsigned char addr[16]; + dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); + 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_client_query_get(query); + if (fast_ping_start(name, 1, 900, dns_client_ping_result, query) != 0) { + _dns_client_query_release(query); + } + } break; + case DNS_T_NS: { + char cname[128]; + dns_get_CNAME(rrs, name, 128, &ttl, cname, 128); + printf("NS: %s %d : %s\n", name, ttl, cname); } break; - case DNS_T_NS: case DNS_T_CNAME: { char cname[128]; dns_get_CNAME(rrs, name, 128, &ttl, cname, 128); @@ -139,12 +420,50 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so } } - printf("\n"); + query->dns_request_sent--; + if (query->dns_request_sent <= 0) { + _dns_client_query_release(query); + } - return 0; + return ret; } -static int _dns_client_process(struct dns_query_struct *dns_query, struct timeval *now) +static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len) +{ + int len; + int i; + int qtype; + int qclass; + char name[DNS_MAX_CNAME_LEN]; + int rr_count; + struct dns_rrs *rrs = NULL; + unsigned char packet_buff[DNS_PACKSIZE]; + struct dns_packet *packet = (struct dns_packet *)packet_buff; + + len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); + if (len != 0) { + printf("decode failed, packet len = %d\n", inpacket_len); + return -1; + } + + if (packet->head.qr != DNS_OP_IQUERY) { + printf("message type error.\n"); + return -1; + } + + printf("qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d\n", packet->head.qdcount, packet->head.ancount, packet->head.nscount, + packet->head.nrcount, inpacket_len); + + 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)) { + dns_get_domain(rrs, name, DNS_MAX_CNAME_LEN, &qtype, &qclass); + printf("domain: %s qtype: %d qclass: %d\n", name, qtype, qclass); + } + + return _dns_client_process_answer(name, packet); +} + +static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long now) { int len; unsigned char inpacket[DNS_IN_PACKSIZE]; @@ -165,37 +484,35 @@ static void *_dns_client_work(void *arg) struct epoll_event events[DNS_MAX_EVENTS + 1]; int num; int i; - struct timeval last = {0}; - struct timeval now = {0}; - struct timeval diff = {0}; - uint millisec = 0; + unsigned long now = {0}; + unsigned int sleep = 100; + int sleep_time; + unsigned int expect_time = 0; + now = get_tick_count() - sleep; + expect_time = now + sleep; while (client.run) { - diff = now; - tv_sub(&diff, &last); - millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; - if (millisec >= 1000) { + now = get_tick_count(); + if (now - expect_time >= 0) { _dns_client_period_run(); - last = now; + sleep_time = sleep - (now - expect_time); + if (sleep_time < 0) { + sleep_time = 0; + expect_time = now; + } + expect_time += sleep; } - num = epoll_wait(client.epoll_fd, events, DNS_MAX_EVENTS, 1000); + num = epoll_wait(client.epoll_fd, events, DNS_MAX_EVENTS, sleep_time); if (num < 0) { - gettimeofday(&now, 0); usleep(100000); continue; } - if (num == 0) { - gettimeofday(&now, 0); - continue; - } - - gettimeofday(&now, 0); for (i = 0; i < num; i++) { struct epoll_event *event = &events[i]; struct dns_query_struct *dns_query = (struct dns_query_struct *)event->data.ptr; - _dns_client_process(dns_query, &now); + _dns_client_process(dns_query, now); } } @@ -205,17 +522,10 @@ static void *_dns_client_work(void *arg) return NULL; } -static int _dns_client_send_packet(void *packet, int len) +static int _dns_client_send_udp(struct dns_server_info *server_info, void *packet, int len) { - struct sockaddr_in to; int send_len = 0; - socklen_t to_len = sizeof(to); - - memset(&to, 0, sizeof(to)); - to.sin_addr.s_addr = inet_addr("192.168.1.1"); - to.sin_port = htons(53); - - send_len = sendto(client.udp, packet, len, 0, (struct sockaddr *)&to, to_len); + send_len = sendto(client.udp, packet, len, 0, (struct sockaddr *)&server_info->addr, server_info->addr_len); if (send_len != len) { printf("send to server failed."); return -1; @@ -224,7 +534,34 @@ static int _dns_client_send_packet(void *packet, int len) return 0; } -static int _dns_client_send_request(struct dns_query_struct *request, char *doamin) +static int _dns_client_send_packet(struct dns_query_struct *query, void *packet, int len) +{ + struct dns_server_info *server_info, *tmp; + int ret = 0; + + query->send_tick = get_tick_count(); + pthread_mutex_lock(&client.server_list_lock); + list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list) + { + switch (server_info->type) { + case DNS_SERVER_UDP: + ret = _dns_client_send_udp(server_info, packet, len); + default: + ret = -1; + break; + } + + if (ret != 0) { + continue; + } + + query->dns_request_sent++; + } + pthread_mutex_unlock(&client.server_list_lock); + return 0; +} + +static int _dns_client_send_query(struct dns_query_struct *query, char *doamin) { unsigned char packet_buff[DNS_PACKSIZE]; unsigned char inpacket[DNS_IN_PACKSIZE]; @@ -235,7 +572,7 @@ static int _dns_client_send_request(struct dns_query_struct *request, char *doam memset(&head, 0, sizeof(head)); head.rcode = 0; head.qr = DNS_OP_QUERY; - head.rd = 1; + head.rd = 0; head.ra = 0; head.id = 1; @@ -243,42 +580,60 @@ static int _dns_client_send_request(struct dns_query_struct *request, char *doam dns_add_domain(packet, doamin, DNS_T_A, DNS_C_IN); encode_len = dns_encode(inpacket, DNS_IN_PACKSIZE, packet); if (encode_len <= 0) { - printf("encode request failed.\n"); + printf("encode query failed.\n"); return -1; } - return _dns_client_send_packet(inpacket, encode_len); + return _dns_client_send_packet(query, inpacket, encode_len); } -int dns_client_query(char *domain, void *user_ptr) +int dns_client_query(char *domain, dns_client_callback callback, void *user_ptr) { - struct dns_query_struct *request = NULL; + struct dns_query_struct *query = NULL; int ret = 0; - request = malloc(sizeof(*request)); - if (request == NULL) { - return -1; - } - INIT_HLIST_NODE(&request->host_node); - strncpy(request->domain, domain, DNS_MAX_CNAME_LEN); - request->user_ptr = user_ptr; - ret =_dns_client_send_request(request, domain); - if (ret != 0) { + query = malloc(sizeof(*query)); + if (query == NULL) { goto errout; } - free(request); + memset(query, 0, sizeof(*query)); + INIT_HLIST_NODE(&query->domain_node); + INIT_LIST_HEAD(&query->dns_request_list); + atomic_set(&query->refcnt, 0); + strncpy(query->domain, domain, DNS_MAX_CNAME_LEN); + query->user_ptr = user_ptr; + query->callback = callback; + query->result.ttl_v4 = -1; + query->result.ttl_v6 = -1; + + _dns_client_query_get(query); + ret = _dns_client_send_query(query, domain); + if (ret != 0) { + goto errout_del_list; + } + + pthread_mutex_lock(&client.domain_map_lock); + list_add_tail(&query->dns_request_list, &client.dns_request_list); + hash_add(client.domain_map, &query->domain_node, hash_string(domain)); + pthread_mutex_unlock(&client.domain_map_lock); + return 0; +errout_del_list: + atomic_dec(&query->refcnt); + pthread_mutex_lock(&client.domain_map_lock); + list_del(&query->dns_request_list); + hash_del(&query->domain_node); + pthread_mutex_unlock(&client.domain_map_lock); errout: - if (request) { - free(request); + if (query) { + free(query); } return -1; } -int dns_register_callback(dns_client_callback callback) +int dns_client_query_raw(char *domain, unsigned char *raw, int raw_len, void *user_ptr) { - dns_callback = callback; - return 0; + return -1; } static struct addrinfo *_dns_server_getaddr(const char *host, const char *port, int type, int protocol) @@ -322,7 +677,7 @@ int dns_client_socket(void) int fd = -1; struct addrinfo *gai = NULL; - gai = _dns_server_getaddr(NULL, "54", SOCK_DGRAM, 0); + gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0); if (gai == NULL) { fprintf(stderr, "get address failed.\n"); goto errout; @@ -383,11 +738,17 @@ int dns_client_init() goto errout; } - pthread_mutex_init(&client.map_lock, 0); - hash_init(client.hostmap); + pthread_mutex_init(&client.server_list_lock, 0); + INIT_LIST_HEAD(&client.dns_server_list); + + pthread_mutex_init(&client.domain_map_lock, 0); + hash_init(client.domain_map); + INIT_LIST_HEAD(&client.dns_request_wait_list); + INIT_LIST_HEAD(&client.dns_request_list); + client.epoll_fd = epollfd; - if (dns_client_start()) { + if (dns_client_start()) { fprintf(stderr, "start client failed.\n"); goto errout; } @@ -400,15 +761,17 @@ errout: pthread_join(client.tid, &retval); } - if (fd > 0) { - close(fd); + if (client.udp > 0) { + close(client.udp); + client.udp = -1; } if (epollfd) { close(epollfd); } - pthread_mutex_destroy(&client.map_lock); + pthread_mutex_destroy(&client.server_list_lock); + pthread_mutex_destroy(&client.domain_map_lock); return -1; } @@ -425,5 +788,6 @@ void dns_client_exit() close(client.udp); } - pthread_mutex_destroy(&client.map_lock); + pthread_mutex_destroy(&client.server_list_lock); + pthread_mutex_destroy(&client.domain_map_lock); } \ No newline at end of file diff --git a/dns_client.h b/dns_client.h index cb876ab..c40bf51 100644 --- a/dns_client.h +++ b/dns_client.h @@ -1,13 +1,35 @@ #ifndef _SMART_DNS_CLIENT_H #define _SMART_DNS_CLIENT_H +#include "dns.h" + +typedef enum { + DNS_SERVER_UDP, + DNS_SERVER_TCP, + DNS_SERVER_HTTP, + DNS_SERVER_TYPE_END, +} dns_server_type_t; + +struct dns_result { + char alias[DNS_MAX_CNAME_LEN]; + unsigned long ttl_v4; + unsigned char addr_ipv4[4]; + unsigned long ttl_v6; + unsigned char addr_ipv6[16]; +}; + int dns_client_init(void); -typedef int (*dns_client_callback)(char *domain, unsigned char *addr, int addr_type, void *user_ptr); -int dns_register_callback(dns_client_callback callback); +typedef int (*dns_client_callback)(char *domain, struct dns_result *result, void *user_ptr); -int dns_client_query(char *domain, void *user_ptr); +int dns_client_query(char *domain, dns_client_callback callback, void *user_ptr); + +int dns_client_query_raw(char *domain, unsigned char *raw, int raw_len, void *user_ptr); void dns_client_exit(void); +int dns_add_server(char *server_ip, int port, dns_server_type_t server_type); + +int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type); + #endif diff --git a/dns_server.c b/dns_server.c index ee93ca2..cca2a5b 100644 --- a/dns_server.c +++ b/dns_server.c @@ -18,6 +18,8 @@ #include "dns_server.h" #include "dns.h" +#include "util.h" +#include "atomic.h" #include "hashtable.h" #include "list.h" #include "dns_client.h" @@ -52,6 +54,7 @@ struct dns_server { }; struct dns_request { + atomic_t refcnt; struct hlist_node map; char domain[DNS_MAX_CNAME_LEN]; unsigned short qtype; @@ -72,15 +75,6 @@ struct dns_request { static struct dns_server server; -static void tv_sub(struct timeval *out, struct timeval *in) -{ - if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ - --out->tv_sec; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; -} - void _dns_server_period_run() { return; @@ -177,6 +171,7 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request) return ret; } + static int _dns_reply(struct dns_request *request) { unsigned char inpacket[DNS_IN_PACKSIZE]; @@ -220,6 +215,40 @@ static int _dns_reply(struct dns_request *request) return 0; } + +static int dns_server_resolve_callback(char *domain, struct dns_result *result, void *user_ptr) +{ + struct dns_request *request = user_ptr; + + if (user_ptr == NULL) { + return -1; + } + + + memcpy(request->ipv4_addr, result->addr_ipv4, 4); + //memcpy(request->ipv6_addr, result->addr_ipv6, 16); + request->qtype = DNS_T_A; + + printf("----------------%s--%d.%d.%d.%d-\n", domain, + request->ipv4_addr[0], + request->ipv4_addr[1], + request->ipv4_addr[2], + request->ipv4_addr[3]); + _dns_reply(request); + + if (!atomic_dec_and_test(&request->refcnt)) { + return 0; + + } + + printf("free query server %p\n", request); + memset(request, 0, sizeof(*request)); + free(request); + + return 0; +} + + static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len) { int decode_len; @@ -279,9 +308,10 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so break; } - dns_client_query(request->domain, request); + printf("query server %p\n", request); + atomic_set(&request->refcnt, 1); + dns_client_query(request->domain, dns_server_resolve_callback, request); - free(request); return 0; errout: if (request) { @@ -291,7 +321,7 @@ errout: return ret; } -static int _dns_server_process(struct timeval *now) +static int _dns_server_process(unsigned long now) { int len; unsigned char inpacket[DNS_IN_PACKSIZE]; @@ -312,33 +342,34 @@ int dns_server_run(void) struct epoll_event events[DNS_MAX_EVENTS + 1]; int num; int i; - struct timeval last = {0}; - struct timeval now = {0}; - struct timeval diff = {0}; - uint millisec = 0; + unsigned long now = {0}; + int sleep = 1000; + int sleep_time = 0; + unsigned long expect_time = 0; - while (server.run) { - diff = now; - tv_sub(&diff, &last); - millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; - if (millisec >= 1000) { - _dns_server_period_run(); - last = now; - } + now = get_tick_count() - sleep; + expect_time = now + sleep; + while (server.run) { + now = get_tick_count(); + if (now - expect_time >= 0) { + _dns_server_period_run(); + sleep_time = sleep - (now - expect_time); + if (sleep_time < 0) { + sleep_time = 0; + + } + expect_time += sleep; + } - num = epoll_wait(server.epoll_fd, events, DNS_MAX_EVENTS, 1000); + num = epoll_wait(server.epoll_fd, events, DNS_MAX_EVENTS, sleep_time); if (num < 0) { - gettimeofday(&now, 0); usleep(100000); continue; } if (num == 0) { - gettimeofday(&now, 0); continue; } - - gettimeofday(&now, 0); for (i = 0; i < num; i++) { struct epoll_event *event = &events[i]; if (event->data.fd != server.fd) { @@ -346,7 +377,7 @@ int dns_server_run(void) continue; } - _dns_server_process(&now); + _dns_server_process(now); } } @@ -429,11 +460,6 @@ errout: return -1; } -static int dns_server_resolve_callback(char *domain, unsigned char *addr, int addr_type, void *user_ptr) -{ - return 0; -} - int dns_server_init(void) { pthread_attr_t attr; @@ -465,8 +491,6 @@ int dns_server_init(void) server.fd = fd; server.run = 1; - dns_register_callback(dns_server_resolve_callback); - if (dns_server_start() != 0) { fprintf(stderr, "start service failed.\n"); goto errout; diff --git a/fast_ping.c b/fast_ping.c index f8d3e0c..8a53dbe 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -1,7 +1,7 @@ /************************************************************************* -* -* Copyright (C) 2018 Ruilin Peng (Nick) . -* + * + * Copyright (C) 2018 Ruilin Peng (Nick) . + * * smartdns is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -19,8 +19,8 @@ #include "fast_ping.h" #include "atomic.h" #include "hashtable.h" -#include #include +#include #include #include #include @@ -42,770 +42,820 @@ #define ICMP_INPACKET_SIZE 1024 struct fast_ping_packet_msg { - struct timeval tv; + struct timeval tv; }; struct fast_ping_packet { - union { - struct icmp icmp; - struct icmp6_hdr icmp6; - }; - struct fast_ping_packet_msg msg; + union { + struct icmp icmp; + struct icmp6_hdr icmp6; + }; + struct fast_ping_packet_msg msg; }; struct ping_host_struct { - atomic_t ref; - struct hlist_node host_node; - struct hlist_node addr_node; - int type; + atomic_t ref; + struct hlist_node host_node; + struct hlist_node addr_node; + int type; - void *userptr; - char host[PING_MAX_HOSTLEN]; + void *userptr; + fast_ping_result ping_callback; + char host[PING_MAX_HOSTLEN]; - int fd; - unsigned int seq; - struct timeval last; - int interval; - int timeout; - int send; - struct sockaddr_storage addr; - socklen_t addr_len; - struct fast_ping_packet packet; + int fd; + unsigned int seq; + struct timeval last; + int interval; + int timeout; + int count; + int send; + struct sockaddr addr; + socklen_t addr_len; + struct fast_ping_packet packet; }; struct fast_ping_struct { - int run; - pthread_t tid; - pthread_mutex_t lock; - unsigned short ident; + int run; + pthread_t tid; + pthread_mutex_t lock; + unsigned short ident; - int epoll_fd; - int fd_icmp; - struct ping_host_struct icmp_host; - int fd_icmp6; - struct ping_host_struct icmp6_host; + int epoll_fd; + int fd_icmp; + struct ping_host_struct icmp_host; + int fd_icmp6; + struct ping_host_struct icmp6_host; - pthread_mutex_t map_lock; - DECLARE_HASHTABLE(hostmap, 6); - DECLARE_HASHTABLE(addrmap, 6); + pthread_mutex_t map_lock; + DECLARE_HASHTABLE(hostmap, 6); + DECLARE_HASHTABLE(addrmap, 6); }; static struct fast_ping_struct ping; -static fast_ping_result ping_callback; uint16_t _fast_ping_checksum(uint16_t *header, size_t len) { - uint32_t sum = 0; - int i; + uint32_t sum = 0; + int i; - for (i = 0; i < len / sizeof(uint16_t); i++) { - sum += ntohs(header[i]); - } + for (i = 0; i < len / sizeof(uint16_t); i++) { + sum += ntohs(header[i]); + } - return htons(~((sum >> 16) + (sum & 0xffff))); -} - -void fast_ping_result_callback(fast_ping_result result) -{ - ping_callback = result; + return htons(~((sum >> 16) + (sum & 0xffff))); } void _fast_ping_install_filter_v6(int sock) { - struct icmp6_filter icmp6_filter; - ICMP6_FILTER_SETBLOCKALL(&icmp6_filter); - ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &icmp6_filter); - setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &icmp6_filter, sizeof(struct icmp6_filter)); + struct icmp6_filter icmp6_filter; + ICMP6_FILTER_SETBLOCKALL(&icmp6_filter); + ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &icmp6_filter); + setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &icmp6_filter, sizeof(struct icmp6_filter)); - static int once; - static struct sock_filter insns[] = { - BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 4), /* Load icmp echo ident */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA, 0, 1), /* Ours? */ - BPF_STMT(BPF_RET | BPF_K, ~0U), /* Yes, it passes. */ - BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 0), /* Load icmp type */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ICMP6_ECHO_REPLY, 1, 0), /* Echo? */ - BPF_STMT(BPF_RET | BPF_K, ~0U), /* No. It passes. This must not happen. */ - BPF_STMT(BPF_RET | BPF_K, 0), /* Echo with wrong ident. Reject. */ - }; - static struct sock_fprog filter = { sizeof insns / sizeof(insns[0]), insns }; + static int once; + static struct sock_filter insns[] = { + BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 4), /* Load icmp echo ident */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA, 0, 1), /* Ours? */ + BPF_STMT(BPF_RET | BPF_K, ~0U), /* Yes, it passes. */ + BPF_STMT(BPF_LD | BPF_B | BPF_ABS, 0), /* Load icmp type */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ICMP6_ECHO_REPLY, 1, 0), /* Echo? */ + BPF_STMT(BPF_RET | BPF_K, ~0U), /* No. It passes. This must not happen. */ + BPF_STMT(BPF_RET | BPF_K, 0), /* Echo with wrong ident. Reject. */ + }; + static struct sock_fprog filter = {sizeof insns / sizeof(insns[0]), insns}; - if (once) { - return; - } - once = 1; + if (once) { + return; + } + once = 1; - /* Patch bpflet for current identifier. */ - insns[1] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(getpid()), 0, 1); + /* Patch bpflet for current identifier. */ + insns[1] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(getpid()), 0, 1); - if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) { - perror("WARNING: failed to install socket filter\n"); - } + if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) { + perror("WARNING: failed to install socket filter\n"); + } } void _fast_ping_install_filter_v4(int sock) { - static int once; - static struct sock_filter insns[] = { - BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, 0), /* Skip IP header. F..g BSD... Look into ping6. */ - BPF_STMT(BPF_LD | BPF_H | BPF_IND, 4), /* Load icmp echo ident */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA, 0, 1), /* Ours? */ - BPF_STMT(BPF_RET | BPF_K, ~0U), /* Yes, it passes. */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), /* Load icmp type */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ICMP_ECHOREPLY, 1, 0), /* Echo? */ - BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFF), /* No. It passes. */ - BPF_STMT(BPF_RET | BPF_K, 0) /* Echo with wrong ident. Reject. */ - }; + static int once; + static struct sock_filter insns[] = { + BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, 0), /* Skip IP header. F..g BSD... Look into ping6. */ + BPF_STMT(BPF_LD | BPF_H | BPF_IND, 4), /* Load icmp echo ident */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xAAAA, 0, 1), /* Ours? */ + BPF_STMT(BPF_RET | BPF_K, ~0U), /* Yes, it passes. */ + BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), /* Load icmp type */ + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ICMP_ECHOREPLY, 1, 0), /* Echo? */ + BPF_STMT(BPF_RET | BPF_K, 0xFFFFFFF), /* No. It passes. */ + BPF_STMT(BPF_RET | BPF_K, 0) /* Echo with wrong ident. Reject. */ + }; - static struct sock_fprog filter = { sizeof insns / sizeof(insns[0]), insns }; + static struct sock_fprog filter = {sizeof insns / sizeof(insns[0]), insns}; - if (once) { - return; - } - once = 1; + if (once) { + return; + } + once = 1; - /* Patch bpflet for current identifier. */ - insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(getpid()), 0, 1); + /* Patch bpflet for current identifier. */ + insns[2] = (struct sock_filter)BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htons(getpid()), 0, 1); - if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) { - perror("WARNING: failed to install socket filter\n"); - } + if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) { + perror("WARNING: failed to install socket filter\n"); + } } static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int protocol) { - struct addrinfo hints; - struct addrinfo *result = NULL; + struct addrinfo hints; + struct addrinfo *result = NULL; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = type; - hints.ai_protocol = protocol; - if (getaddrinfo(host, NULL, &hints, &result) != 0) { - fprintf(stderr, "get addr info failed. %s\n", strerror(errno)); - goto errout; - } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = type; + hints.ai_protocol = protocol; + if (getaddrinfo(host, NULL, &hints, &result) != 0) { + fprintf(stderr, "get addr info failed. %s\n", strerror(errno)); + goto errout; + } - return result; + return result; errout: - if (result) { - freeaddrinfo(result); - } - return NULL; + if (result) { + freeaddrinfo(result); + } + return NULL; } static int _fast_ping_getdomain(const char *host) { - struct addrinfo hints; - struct addrinfo *result = NULL; - int domain = -1; + struct addrinfo hints; + struct addrinfo *result = NULL; + int domain = -1; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - if (getaddrinfo(host, NULL, &hints, &result) != 0) { - fprintf(stderr, "get addr info failed. %s\n", strerror(errno)); - goto errout; - } + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + if (getaddrinfo(host, NULL, &hints, &result) != 0) { + fprintf(stderr, "get addr info failed. %s\n", strerror(errno)); + goto errout; + } - domain = result->ai_family; + domain = result->ai_family; - freeaddrinfo(result); + freeaddrinfo(result); - return domain; + return domain; errout: - if (result) { - freeaddrinfo(result); - } - return -1; + if (result) { + freeaddrinfo(result); + } + return -1; } 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) { - pthread_mutex_lock(&ping.map_lock); - if (atomic_dec_and_test(&ping_host->ref)) { - hlist_del(&ping_host->host_node); - hlist_del(&ping_host->addr_node); - } else { - ping_host = NULL; - } - pthread_mutex_unlock(&ping.map_lock); + pthread_mutex_lock(&ping.map_lock); + if (atomic_dec_and_test(&ping_host->ref)) { + hlist_del(&ping_host->host_node); + hlist_del(&ping_host->addr_node); + } else { + ping_host = NULL; + } + pthread_mutex_unlock(&ping.map_lock); - if (ping_host == NULL) { - return ; - } + if (ping_host == NULL) { + return; + } - free(ping_host); + free(ping_host); +} + +static void _fast_ping_host_put_locked(struct ping_host_struct *ping_host) +{ + if (atomic_dec_and_test(&ping_host->ref)) { + hlist_del(&ping_host->host_node); + hlist_del(&ping_host->addr_node); + } else { + ping_host = NULL; + } + + if (ping_host == NULL) { + return; + } + + free(ping_host); } static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) { - struct fast_ping_packet *packet = &ping_host->packet; - struct icmp6_hdr *icmp6 = &packet->icmp6; - int len = 0; + struct fast_ping_packet *packet = &ping_host->packet; + struct icmp6_hdr *icmp6 = &packet->icmp6; + int len = 0; - ping_host->seq++; - memset(icmp6, 0, sizeof(*icmp6)); - icmp6->icmp6_type = ICMP6_ECHO_REQUEST; - icmp6->icmp6_code = 0; - icmp6->icmp6_cksum = 0; - icmp6->icmp6_id = getpid(); - icmp6->icmp6_seq = htons(ping_host->seq); + ping_host->seq++; + memset(icmp6, 0, sizeof(*icmp6)); + icmp6->icmp6_type = ICMP6_ECHO_REQUEST; + icmp6->icmp6_code = 0; + icmp6->icmp6_cksum = 0; + icmp6->icmp6_id = getpid(); + icmp6->icmp6_seq = htons(ping_host->seq); - gettimeofday(&packet->msg.tv, 0); - icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); + gettimeofday(&packet->msg.tv, 0); + 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); - if (len < 0 || len != sizeof(struct fast_ping_packet)) { - fprintf(stderr, "sendto %s\n", strerror(errno)); - goto errout; - } + len = sendto(ping_host->fd, &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)) { + fprintf(stderr, "sendto %s\n", strerror(errno)); + goto errout; + } - return 0; + return 0; errout: - return -1; + return -1; } static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host) { - struct fast_ping_packet *packet = &ping_host->packet; - struct icmp *icmp = &packet->icmp; - int len; + struct fast_ping_packet *packet = &ping_host->packet; + struct icmp *icmp = &packet->icmp; + int len; - ping_host->seq++; - memset(icmp, 0, sizeof(*icmp)); - icmp->icmp_type = ICMP_ECHO; - icmp->icmp_code = 0; - icmp->icmp_cksum = 0; - icmp->icmp_id = ping.ident; - icmp->icmp_seq = htons(ping_host->seq); + ping_host->seq++; + memset(icmp, 0, sizeof(*icmp)); + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_code = 0; + icmp->icmp_cksum = 0; + icmp->icmp_id = ping.ident; + icmp->icmp_seq = htons(ping_host->seq); - gettimeofday(&packet->msg.tv, 0); - icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet)); + gettimeofday(&packet->msg.tv, 0); + 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); - if (len < 0 || len != sizeof(struct fast_ping_packet)) { - fprintf(stderr, "sendto %s\n", strerror(errno)); - goto errout; - } + len = sendto(ping_host->fd, 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)) { + fprintf(stderr, "sendto %s\n", strerror(errno)); + goto errout; + } - return 0; + return 0; errout: - return -1; + return -1; } static int _fast_ping_sendping(struct ping_host_struct *ping_host) { - int ret = -1; + int ret = -1; - if (ping_host->type == AF_INET) { - ret = _fast_ping_sendping_v4(ping_host); - } else if (ping_host->type == AF_INET6) { - ret = _fast_ping_sendping_v6(ping_host); - } + if (ping_host->type == AF_INET) { + ret = _fast_ping_sendping_v4(ping_host); + } else if (ping_host->type == AF_INET6) { + ret = _fast_ping_sendping_v6(ping_host); + } - if (ret != 0) { - return ret; - } + if (ret != 0) { + return ret; + } - ping_host->send = 1; - gettimeofday(&ping_host->last, 0); + ping_host->send = 1; + gettimeofday(&ping_host->last, 0); - return 0; + return 0; } static int _fast_ping_create_sock(int protocol) { - int fd = -1; - struct ping_host_struct *icmp_host = NULL; - struct epoll_event event; + int fd = -1; + struct ping_host_struct *icmp_host = NULL; + struct epoll_event event; - switch (protocol) { - case IPPROTO_ICMP: - fd = socket(AF_INET, SOCK_RAW, protocol); - if (fd < 0) { - fprintf(stderr, "create icmp socket failed.\n"); - goto errout; - } - _fast_ping_install_filter_v4(fd); - icmp_host = &ping.icmp_host; - break; - case IPPROTO_ICMPV6: - fd = socket(AF_INET6, SOCK_RAW, protocol); - if (fd < 0) { - fprintf(stderr, "create icmp socket failed.\n"); - goto errout; - } - _fast_ping_install_filter_v6(fd); - icmp_host = &ping.icmp6_host; - break; - } + switch (protocol) { + case IPPROTO_ICMP: + fd = socket(AF_INET, SOCK_RAW, protocol); + if (fd < 0) { + fprintf(stderr, "create icmp socket failed.\n"); + goto errout; + } + _fast_ping_install_filter_v4(fd); + icmp_host = &ping.icmp_host; + break; + case IPPROTO_ICMPV6: + fd = socket(AF_INET6, SOCK_RAW, protocol); + if (fd < 0) { + fprintf(stderr, "create icmp socket failed.\n"); + goto errout; + } + _fast_ping_install_filter_v6(fd); + icmp_host = &ping.icmp6_host; + break; + } - event.events = EPOLLIN; - event.data.ptr = icmp_host; - if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) { - goto errout; - } + event.events = EPOLLIN; + event.data.ptr = icmp_host; + if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) { + goto errout; + } - icmp_host->fd = fd; - icmp_host->type = AF_PACKET; - return fd; + icmp_host->fd = fd; + icmp_host->type = AF_PACKET; + return fd; errout: - close(fd); - return -1; + close(fd); + return -1; } static int _fast_ping_create_icmp(int protocol) { - int fd = 0; - int *set_fd = NULL; + int fd = 0; + int *set_fd = NULL; - pthread_mutex_lock(&ping.lock); - switch (protocol) { - case IPPROTO_ICMP: - set_fd = &ping.fd_icmp; - break; - case IPPROTO_ICMPV6: - set_fd = &ping.fd_icmp6; - break; - default: - goto errout; - break; - } + pthread_mutex_lock(&ping.lock); + switch (protocol) { + case IPPROTO_ICMP: + set_fd = &ping.fd_icmp; + break; + case IPPROTO_ICMPV6: + set_fd = &ping.fd_icmp6; + break; + default: + goto errout; + break; + } - if (*set_fd > 0) { - goto out; - } + if (*set_fd > 0) { + goto out; + } - fd = _fast_ping_create_sock(protocol); - if (fd < 0) { - goto errout; - } + fd = _fast_ping_create_sock(protocol); + if (fd < 0) { + goto errout; + } - *set_fd = fd; + *set_fd = fd; out: - pthread_mutex_unlock(&ping.lock); - return *set_fd; + pthread_mutex_unlock(&ping.lock); + return *set_fd; errout: - if (fd > 0) { - close(fd); - } - pthread_mutex_unlock(&ping.lock); - return -1; -} - -int fast_ping_start(const char *host, int timeout, void *userptr) -{ - struct ping_host_struct *ping_host = NULL; - struct addrinfo *gai = NULL; - int domain = -1; - int icmp_proto = 0; - uint32_t hostkey; - uint32_t addrkey; - int fd = -1; - - domain = _fast_ping_getdomain(host); - if (domain < 0) { - return -1; - } - - switch (domain) { - case AF_INET: - icmp_proto = IPPROTO_ICMP; - break; - case AF_INET6: - icmp_proto = IPPROTO_ICMPV6; - break; - default: - return -1; - break; - } - - fd = _fast_ping_create_icmp(icmp_proto); - if (fd < 0) { - goto errout; - } - - gai = _fast_ping_getaddr(host, SOCK_RAW, icmp_proto); - if (gai == NULL) { - goto errout; - } - - ping_host = malloc(sizeof(*ping_host)); - if (ping_host == NULL) { - goto errout; - } - - int interval = 1000; - memset(ping_host, 0, sizeof(*ping_host)); - strncpy(ping_host->host, host, PING_MAX_HOSTLEN); - ping_host->type = domain; - ping_host->fd = fd; - ping_host->timeout = timeout; - ping_host->interval = (timeout > interval) ? timeout : interval; - memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen); - ping_host->addr_len = gai->ai_addrlen; - - atomic_set(&ping_host->ref, 0); - - hostkey = hash_string(ping_host->host); - addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0); - pthread_mutex_lock(&ping.map_lock); - _fast_ping_host_get(ping_host); - hash_add(ping.hostmap, &ping_host->host_node, hostkey); - hash_add(ping.addrmap, &ping_host->addr_node, addrkey); - pthread_mutex_unlock(&ping.map_lock); - - freeaddrinfo(gai); - - _fast_ping_sendping(ping_host); - return 0; -errout: - if (fd > 0) { + if (fd > 0) { close(fd); } - - if (gai) { - freeaddrinfo(gai); - } + pthread_mutex_unlock(&ping.lock); + return -1; +} - if (ping_host) { - free(ping_host); - } +void fast_ping_print_result(const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, struct timeval *tv, void *userptr) +{ + if (result == PING_RESULT_RESPONSE) { + double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; + printf("from %15s: seq=%d time=%.3f\n", host, seqno, rtt); + } else if (result == PING_RESULT_TIMEOUT) { + printf("from %15s: seq=%d timeout\n", host, seqno); + } +} - return -1; +int fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr) +{ + struct ping_host_struct *ping_host = NULL; + struct addrinfo *gai = NULL; + int domain = -1; + int icmp_proto = 0; + uint32_t hostkey; + uint32_t addrkey; + int fd = -1; + + domain = _fast_ping_getdomain(host); + if (domain < 0) { + return -1; + } + + switch (domain) { + case AF_INET: + icmp_proto = IPPROTO_ICMP; + break; + case AF_INET6: + icmp_proto = IPPROTO_ICMPV6; + break; + default: + return -1; + break; + } + + fd = _fast_ping_create_icmp(icmp_proto); + if (fd < 0) { + goto errout; + } + + gai = _fast_ping_getaddr(host, SOCK_RAW, icmp_proto); + if (gai == NULL) { + goto errout; + } + + ping_host = malloc(sizeof(*ping_host)); + if (ping_host == NULL) { + goto errout; + } + + int interval = 1000; + memset(ping_host, 0, sizeof(*ping_host)); + strncpy(ping_host->host, host, PING_MAX_HOSTLEN); + ping_host->type = domain; + ping_host->fd = fd; + ping_host->timeout = timeout; + ping_host->count = count; + ping_host->userptr = userptr; + if (ping_callback) { + ping_host->ping_callback = ping_callback; + } else { + ping_host->ping_callback = fast_ping_print_result; + } + ping_host->interval = (timeout > interval) ? timeout : interval; + memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen); + ping_host->addr_len = gai->ai_addrlen; + + atomic_set(&ping_host->ref, 0); + + hostkey = hash_string(ping_host->host); + addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0); + pthread_mutex_lock(&ping.map_lock); + _fast_ping_host_get(ping_host); + hash_add(ping.hostmap, &ping_host->host_node, hostkey); + hash_add(ping.addrmap, &ping_host->addr_node, addrkey); + pthread_mutex_unlock(&ping.map_lock); + + freeaddrinfo(gai); + + _fast_ping_sendping(ping_host); + return 0; +errout: + if (fd > 0) { + close(fd); + } + + if (gai) { + freeaddrinfo(gai); + } + + if (ping_host) { + free(ping_host); + } + + return -1; } int fast_ping_stop(const char *host) { - struct ping_host_struct *ping_host; - uint32_t key; - key = hash_string(host); - pthread_mutex_lock(&ping.map_lock); - hash_for_each_possible(ping.hostmap, ping_host, host_node, key) - { - if (strncmp(host, ping_host->host, PING_MAX_HOSTLEN) == 0) { - break; - } - } - if (ping_host == NULL) { - pthread_mutex_unlock(&ping.map_lock); - return -1; - } - pthread_mutex_unlock(&ping.map_lock); - _fast_ping_host_put(ping_host); - return 0; + struct ping_host_struct *ping_host; + uint32_t key; + key = hash_string(host); + pthread_mutex_lock(&ping.map_lock); + hash_for_each_possible(ping.hostmap, ping_host, host_node, key) + { + if (strncmp(host, ping_host->host, PING_MAX_HOSTLEN) == 0) { + break; + } + } + if (ping_host == NULL) { + pthread_mutex_unlock(&ping.map_lock); + return -1; + } + pthread_mutex_unlock(&ping.map_lock); + _fast_ping_host_put(ping_host); + return 0; } static void tv_sub(struct timeval *out, struct timeval *in) { - if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ - --out->tv_sec; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; + if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; } static int _fast_ping_icmp6_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv) { - int icmp_len; - struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data; - struct icmp6_hdr *icmp6 = &packet->icmp6; - struct timeval tvresult = *tvrecv; + int icmp_len; + struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data; + struct icmp6_hdr *icmp6 = &packet->icmp6; + struct timeval tvresult = *tvrecv; - if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { - return -1; - } + if (icmp6->icmp6_type != ICMP6_ECHO_REPLY) { + return -1; + } - icmp_len = data_len; - if (icmp_len < 16) { - return -1; - } + icmp_len = data_len; + if (icmp_len < 16) { + return -1; + } - if (icmp6->icmp6_id != ping.ident) { - return -1; - } + if (icmp6->icmp6_id != ping.ident) { + return -1; + } - struct timeval *tvsend = &packet->msg.tv; - tv_sub(&tvresult, tvsend); - ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr); + struct timeval *tvsend = &packet->msg.tv; + tv_sub(&tvresult, tvsend); - return 0; + if (ping_host->ping_callback) { + ping_host->ping_callback(ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tvresult, ping_host->userptr); + } + return 0; } static int _fast_ping_icmp_packet(struct ping_host_struct *ping_host, u_char *packet_data, int data_len, struct timeval *tvrecv) { - struct ip *ip = (struct ip *)packet_data; - struct fast_ping_packet *packet; - struct icmp *icmp; - struct timeval tvresult = *tvrecv; - int hlen; - int icmp_len; + struct ip *ip = (struct ip *)packet_data; + struct fast_ping_packet *packet; + struct icmp *icmp; + struct timeval tvresult = *tvrecv; + int hlen; + int icmp_len; - if (ip->ip_p != IPPROTO_ICMP) { - return -1; - } + if (ip->ip_p != IPPROTO_ICMP) { + return -1; + } - hlen = ip->ip_hl << 2; - packet = (struct fast_ping_packet *)(packet_data + hlen); - icmp = &packet->icmp; - icmp_len = data_len - hlen; + hlen = ip->ip_hl << 2; + packet = (struct fast_ping_packet *)(packet_data + hlen); + icmp = &packet->icmp; + icmp_len = data_len - hlen; - if (icmp_len < 16) { - return -1; - } + if (icmp_len < 16) { + return -1; + } - if (icmp->icmp_type != ICMP_ECHOREPLY) { - return -1; - } + if (icmp->icmp_type != ICMP_ECHOREPLY) { + return -1; + } - if (icmp->icmp_id != ping.ident) { - return -1; - } + if (icmp->icmp_id != ping.ident) { + return -1; + } - struct timeval *tvsend = &packet->msg.tv; - tv_sub(&tvresult, tvsend); + struct timeval *tvsend = &packet->msg.tv; + tv_sub(&tvresult, tvsend); + if (ping_host->ping_callback) { + ping_host->ping_callback(ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tvresult, ping_host->userptr); + } - ping_callback(ping_host->host, PING_RESULT_RESPONSE, ping_host->seq, &tvresult, ping_host->userptr); - - return 0; + return 0; } static int _fast_ping_recvping(struct ping_host_struct *ping_host, u_char *inpacket, int len, struct timeval *tvrecv) { - if (ping_host->type == AF_INET6) { - if (_fast_ping_icmp6_packet(ping_host, inpacket, len, tvrecv)) { - goto errout; - } - } else if (ping_host->type == AF_INET) { + if (ping_host->type == AF_INET6) { + if (_fast_ping_icmp6_packet(ping_host, inpacket, len, tvrecv)) { + goto errout; + } + } else if (ping_host->type == AF_INET) { + if (_fast_ping_icmp_packet(ping_host, inpacket, len, tvrecv)) { + goto errout; + } + } - if (_fast_ping_icmp_packet(ping_host, inpacket, len, tvrecv)) { - goto errout; - } - } - - return 0; + return 0; errout: - return -1; + return -1; } +#if 0 static int _fast_ping_gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len) { - struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr; - host[0] = 0; - switch (addr_store->ss_family) { - case AF_INET: { - struct sockaddr_in *addr_in; - addr_in = (struct sockaddr_in *)addr; - inet_ntop(AF_INET, &addr_in->sin_addr, host, addr_len); - } break; - case AF_INET6: { - struct sockaddr_in6 *addr_in6; - addr_in6 = (struct sockaddr_in6 *)addr; - if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) { - struct sockaddr_in addr_in4; - memset(&addr_in4, 0, sizeof(addr_in4)); - memcpy(&addr_in4.sin_addr.s_addr, addr_in6->sin6_addr.s6_addr + 12, sizeof(addr_in4.sin_addr.s_addr)); - } else { - inet_ntop(AF_INET6, &addr_in6->sin6_addr, host, addr_len); - } - } break; - default: - goto errout; - break; - } - return 0; + struct sockaddr_storage *addr_store = (struct sockaddr_storage *)addr; + host[0] = 0; + switch (addr_store->ss_family) { + case AF_INET: { + struct sockaddr_in *addr_in; + addr_in = (struct sockaddr_in *)addr; + inet_ntop(AF_INET, &addr_in->sin_addr, host, addr_len); + } break; + case AF_INET6: { + struct sockaddr_in6 *addr_in6; + addr_in6 = (struct sockaddr_in6 *)addr; + if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) { + struct sockaddr_in addr_in4; + memset(&addr_in4, 0, sizeof(addr_in4)); + memcpy(&addr_in4.sin_addr.s_addr, addr_in6->sin6_addr.s6_addr + 12, sizeof(addr_in4.sin_addr.s_addr)); + } else { + inet_ntop(AF_INET6, &addr_in6->sin6_addr, host, addr_len); + } + } break; + default: + goto errout; + break; + } + return 0; errout: - return -1; + return -1; } +#endif static int _fast_ping_process(struct ping_host_struct *ping_host, struct timeval *now) { - int len; - u_char inpacket[ICMP_INPACKET_SIZE]; - struct sockaddr_storage from; - struct ping_host_struct *recv_ping_host; - socklen_t from_len = sizeof(from); - uint32_t addrkey; + int len; + u_char inpacket[ICMP_INPACKET_SIZE]; + struct sockaddr_storage from; + struct ping_host_struct *recv_ping_host; + socklen_t from_len = sizeof(from); + uint32_t addrkey; - len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len); - if (len < 0) { - fprintf(stderr, "recvfrom failed, %s\n", strerror(errno)); - goto errout; - } + len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len); + if (len < 0) { + fprintf(stderr, "recvfrom failed, %s\n", strerror(errno)); + goto errout; + } - addrkey = jhash(&from, from_len, 0); - pthread_mutex_lock(&ping.map_lock); - hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey) - { - if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0) { - break; - } - } - pthread_mutex_unlock(&ping.map_lock); + addrkey = jhash(&from, from_len, 0); + pthread_mutex_lock(&ping.map_lock); + hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey) + { + if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0) { + break; + } + } + pthread_mutex_unlock(&ping.map_lock); - if (recv_ping_host == NULL) { - return -1; - } + if (recv_ping_host == NULL) { + return -1; + } - recv_ping_host->send = 0; + recv_ping_host->send = 0; - _fast_ping_recvping(recv_ping_host, inpacket, len, now); - return 0; + _fast_ping_recvping(recv_ping_host, inpacket, len, now); + + if (recv_ping_host->count >= 0) { + recv_ping_host->count--; + } + if (recv_ping_host->count == 0) { + _fast_ping_host_put(recv_ping_host); + } + return 0; errout: - return -1; + return -1; } static void _fast_ping_period_run() { - struct ping_host_struct *ping_host; - struct hlist_node *tmp; - int i = 0; - struct timeval now; - struct timeval interval; - uint64_t millisecond; - gettimeofday(&now, 0); + struct ping_host_struct *ping_host; + struct hlist_node *tmp; + int i = 0; + struct timeval now; + struct timeval interval; + uint64_t millisecond; + gettimeofday(&now, 0); - pthread_mutex_lock(&ping.map_lock); - hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node) - { - interval = now; - tv_sub(&interval, &ping_host->last); - millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000; - if (millisecond > ping_host->timeout && ping_host->send == 1) { - ping_callback(ping_host->host, PING_RESULT_TIMEOUT, ping_host->seq, &interval, ping_host->userptr); - ping_host->send = 0; - } - if (millisecond >= ping_host->interval) { - _fast_ping_sendping(ping_host); - } - } - pthread_mutex_unlock(&ping.map_lock); + pthread_mutex_lock(&ping.map_lock); + hash_for_each_safe(ping.addrmap, i, tmp, ping_host, addr_node) + { + interval = now; + tv_sub(&interval, &ping_host->last); + millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000; + if (millisecond > ping_host->timeout && ping_host->send == 1) { + ping_host->ping_callback(ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr, ping_host->addr_len, ping_host->seq, &interval, ping_host->userptr); + ping_host->send = 0; + } + + if (millisecond < ping_host->interval) { + continue; + } + if (ping_host->count >= 0) { + ping_host->count--; + } + if (ping_host->count == 0) { + _fast_ping_host_put_locked(ping_host); + continue; + } + + _fast_ping_sendping(ping_host); + } + pthread_mutex_unlock(&ping.map_lock); } static void *_fast_ping_work(void *arg) { - struct epoll_event events[PING_MAX_EVENTS + 1]; - int num; - int i; - struct timeval last = { 0 }; - struct timeval now = { 0 }; - struct timeval diff = {0}; - uint millisec = 0; + struct epoll_event events[PING_MAX_EVENTS + 1]; + int num; + int i; + struct timeval last = {0}; + struct timeval now = {0}; + struct timeval diff = {0}; + uint millisec = 0; - while (ping.run) { - diff = now; - tv_sub(&diff, &last); - millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; - if (millisec >= 100) { - _fast_ping_period_run(); - last = now; - } + while (ping.run) { + diff = now; + tv_sub(&diff, &last); + millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; + if (millisec >= 100) { + _fast_ping_period_run(); + last = now; + } - num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 100); - if (num < 0) { - gettimeofday(&now, 0); - usleep(100000); - continue; - } + num = epoll_wait(ping.epoll_fd, events, PING_MAX_EVENTS, 100); + if (num < 0) { + gettimeofday(&now, 0); + usleep(100000); + continue; + } - if (num == 0) { - gettimeofday(&now, 0); - continue; - } + if (num == 0) { + gettimeofday(&now, 0); + continue; + } - gettimeofday(&now, 0); - for (i = 0; i < num; i++) { - struct epoll_event *event = &events[i]; - struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr; - _fast_ping_process(ping_host, &now); - } - } + gettimeofday(&now, 0); + for (i = 0; i < num; i++) { + struct epoll_event *event = &events[i]; + struct ping_host_struct *ping_host = (struct ping_host_struct *)event->data.ptr; + _fast_ping_process(ping_host, &now); + } + } - close(ping.epoll_fd); - ping.epoll_fd = -1; + close(ping.epoll_fd); + ping.epoll_fd = -1; - return NULL; + return NULL; } int fast_ping_init() { - pthread_attr_t attr; - int epollfd = -1; - int ret; + pthread_attr_t attr; + int epollfd = -1; + int ret; - if (ping.epoll_fd > 0) { - return -1; - } + if (ping.epoll_fd > 0) { + return -1; + } - memset(&ping, 0, sizeof(ping)); - pthread_attr_init(&attr); + memset(&ping, 0, sizeof(ping)); + pthread_attr_init(&attr); - epollfd = epoll_create1(EPOLL_CLOEXEC); - if (epollfd < 0) { - fprintf(stderr, "create epoll failed, %s\n", strerror(errno)); - goto errout; - } + epollfd = epoll_create1(EPOLL_CLOEXEC); + if (epollfd < 0) { + fprintf(stderr, "create epoll failed, %s\n", strerror(errno)); + goto errout; + } - ping.run = 1; - ret = pthread_create(&ping.tid, &attr, _fast_ping_work, NULL); - if (ret != 0) { - fprintf(stderr, "create ping work thread failed, %s\n", strerror(errno)); - goto errout; - } + ping.run = 1; + ret = pthread_create(&ping.tid, &attr, _fast_ping_work, NULL); + if (ret != 0) { + fprintf(stderr, "create ping work thread failed, %s\n", strerror(errno)); + goto errout; + } - pthread_mutex_init(&ping.map_lock, 0); - pthread_mutex_init(&ping.lock, 0); - hash_init(ping.hostmap); - hash_init(ping.addrmap); - ping.epoll_fd = epollfd; - ping.ident = getpid(); + pthread_mutex_init(&ping.map_lock, 0); + pthread_mutex_init(&ping.lock, 0); + hash_init(ping.hostmap); + hash_init(ping.addrmap); + ping.epoll_fd = epollfd; + ping.ident = getpid(); - return 0; + return 0; errout: - if (ping.tid > 0) { - void *retval = NULL; - ping.run = 0; - pthread_join(ping.tid, &retval); - } + if (ping.tid > 0) { + void *retval = NULL; + ping.run = 0; + pthread_join(ping.tid, &retval); + } - if (epollfd) { - close(epollfd); - } + if (epollfd) { + close(epollfd); + } - pthread_mutex_destroy(&ping.lock); - pthread_mutex_destroy(&ping.map_lock); + pthread_mutex_destroy(&ping.lock); + pthread_mutex_destroy(&ping.map_lock); - return -1; + return -1; } void fast_ping_exit() { - if (ping.tid > 0) { - void *ret = NULL; - ping.run = 0; - pthread_join(ping.tid, &ret); - } + if (ping.tid > 0) { + void *ret = NULL; + ping.run = 0; + pthread_join(ping.tid, &ret); + } - if (ping.fd_icmp > 0) { - close(ping.fd_icmp); - ping.fd_icmp = -1; - } + if (ping.fd_icmp > 0) { + close(ping.fd_icmp); + ping.fd_icmp = -1; + } - if (ping.fd_icmp6 > 0) { - close(ping.fd_icmp6); - ping.fd_icmp6 = -1; - } + if (ping.fd_icmp6 > 0) { + close(ping.fd_icmp6); + ping.fd_icmp6 = -1; + } - pthread_mutex_destroy(&ping.lock); - pthread_mutex_destroy(&ping.map_lock); + pthread_mutex_destroy(&ping.lock); + pthread_mutex_destroy(&ping.map_lock); } \ No newline at end of file diff --git a/fast_ping.h b/fast_ping.h index ac9a41c..22dc4ae 100755 --- a/fast_ping.h +++ b/fast_ping.h @@ -2,7 +2,7 @@ #define FAST_PING_H #include - +#include #ifdef __cpluscplus extern "C" { #endif @@ -18,10 +18,9 @@ typedef enum { PING_RESULT_TIMEOUT = 2, } FAST_PING_RESULT; -typedef void (*fast_ping_result)(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr); -void fast_ping_result_callback(fast_ping_result result); +typedef void (*fast_ping_result)(const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, struct timeval *tv, void *userptr); -int fast_ping_start(const char *host, int timeout, void *userptr); +int fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr); int fast_ping_stop(const char *host); diff --git a/smartdns b/smartdns deleted file mode 100644 index afbfbeb..0000000 Binary files a/smartdns and /dev/null differ diff --git a/smartdns.c b/smartdns.c index 08d9aab..cffcd67 100755 --- a/smartdns.c +++ b/smartdns.c @@ -21,18 +21,10 @@ #include "dns_server.h" #include "hashtable.h" #include "list.h" +#include "tlog.h" #include #include -void smartdns_ping_result(const char *host, FAST_PING_RESULT result, int seqno, struct timeval *tv, void *userptr) -{ - if (result == PING_RESULT_RESPONSE) { - double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; - printf("%16s: seq=%d time=%.3f\n", host, seqno, rtt); - } else if (result == PING_RESULT_TIMEOUT) { - printf("%16s: seq=%d timeout\n", host, seqno); - } -} int smartdns_init() { @@ -44,8 +36,6 @@ int smartdns_init() goto errout; } - fast_ping_result_callback(smartdns_ping_result); - ret = dns_server_init(); if (ret != 0) { fprintf(stderr, "start dns server failed.\n"); @@ -58,7 +48,10 @@ int smartdns_init() goto errout; } - return 0; + //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); + return 0; errout: return -1; diff --git a/util.c b/util.c new file mode 100644 index 0000000..dcfa9e0 --- /dev/null +++ b/util.c @@ -0,0 +1,11 @@ +#include "util.h" +#include + +unsigned long get_tick_count() +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); +} \ No newline at end of file diff --git a/util.h b/util.h new file mode 100644 index 0000000..7700d4d --- /dev/null +++ b/util.h @@ -0,0 +1,8 @@ + + +#ifndef SMART_DNS_UTIL_H +#define SMART_DNS_UTIL_H + +unsigned long get_tick_count(); + +#endif \ No newline at end of file