diff --git a/dns_client.c b/dns_client.c index acf3a3d..6d706c8 100644 --- a/dns_client.c +++ b/dns_client.c @@ -174,9 +174,9 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ } memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen); - if (fast_ping_start(server_ip, 0, 60000, NULL, server_info) == NULL) { - goto errout; - } + // if (fast_ping_start(server_ip, 0, 60000, NULL, server_info) == NULL) { + // goto errout; + // } pthread_mutex_lock(&client.server_list_lock); list_add(&server_info->list, &client.dns_server_list); @@ -205,9 +205,9 @@ int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_ } list_del(&server_info->list); pthread_mutex_unlock(&client.server_list_lock); - if (fast_ping_stop(server_info->ping_host) != 0) { - tlog(TLOG_ERROR, "stop ping failed.\n"); - } + // if (fast_ping_stop(server_info->ping_host) != 0) { + // tlog(TLOG_ERROR, "stop ping failed.\n"); + // } free(server_info); return 0; } diff --git a/dns_client.h b/dns_client.h index abb227c..1864e44 100644 --- a/dns_client.h +++ b/dns_client.h @@ -10,14 +10,6 @@ typedef enum { 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]; -}; - typedef enum dns_result_type { DNS_QUERY_ERR, DNS_QUERY_RESULT = 1, diff --git a/dns_server.c b/dns_server.c index c2ca076..1e2232c 100644 --- a/dns_server.c +++ b/dns_server.c @@ -58,6 +58,16 @@ struct dns_server { DECLARE_HASHTABLE(hostmap, 6); }; +struct dns_ip_address { + struct hlist_node node; + dns_type_t addr_type; + union { + unsigned char ipv4_addr[DNS_RR_A_LEN]; + unsigned char ipv6_addr[DNS_RR_AAAA_LEN]; + unsigned char addr[0]; + }; +}; + struct dns_request { atomic_t refcnt; struct hlist_node map; @@ -94,6 +104,8 @@ struct dns_request { atomic_t notified; int passthrough; + + DECLARE_HASHTABLE(ip_map, 4); }; static struct dns_server server; @@ -255,6 +267,10 @@ int _dns_server_request_complete(struct dns_request *request) void _dns_server_request_release(struct dns_request *request) { + struct dns_ip_address *addr_map; + struct hlist_node *tmp; + int bucket = 0; + int refcnt = atomic_dec_return(&request->refcnt); if (refcnt) { if (refcnt < 0) { @@ -265,6 +281,10 @@ void _dns_server_request_release(struct dns_request *request) } _dns_server_request_complete(request); + hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node) { + hash_del(&addr_map->node); + free(addr_map); + } memset(request, 0, sizeof(*request)); free(request); } @@ -337,6 +357,47 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos } } +int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, dns_type_t addr_type) +{ + int key = 0; + struct dns_ip_address *addr_map = NULL; + int addr_len = 0; + + if (addr_type == DNS_T_A) { + addr_len = DNS_RR_A_LEN; + } else if (addr_type == DNS_T_AAAA) { + addr_len = DNS_RR_AAAA_LEN; + } else { + return -1; + } + + key = jhash(addr, addr_len, 0); + hash_for_each_possible(request->ip_map, addr_map, node, key) + { + if (addr_type == DNS_T_A) { + if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) { + return -1; + } + } else if (addr_type == DNS_T_AAAA) { + if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) { + return -1; + } + } + } + + addr_map = malloc(sizeof(*addr_map)); + if (addr_map == NULL) { + tlog(TLOG_ERROR, "malloc failed"); + return -1; + } + + addr_map->addr_type = addr_type; + memcpy(addr_map->addr, addr, addr_len); + hash_add(request->ip_map, &addr_map->node, key); + + return 0; +} + static int _dns_client_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet) { int ttl; @@ -363,12 +424,16 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, switch (rrs->type) { case DNS_T_A: { unsigned char addr[4]; + _dns_server_request_get(request); dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); + if (_dns_ip_address_check_add(request, addr, DNS_T_A) != 0) { + _dns_server_request_release(request); + break; + } tlog(TLOG_INFO, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(request->alias, name, DNS_MAX_CNAME_LEN) == 0) { - _dns_server_request_get(request); if (fast_ping_start(ip, 1, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } @@ -376,10 +441,15 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, } break; case DNS_T_AAAA: { unsigned char addr[16]; + _dns_server_request_get(request); dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr); + if (_dns_ip_address_check_add(request, addr, DNS_T_AAAA) != 0) { + _dns_server_request_release(request); + break; + } + sprintf(name, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); - _dns_server_request_get(request); if (fast_ping_start(name, 1, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } @@ -547,6 +617,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so request->id = packet->head.id; memcpy(&request->head, &packet->head, sizeof(struct dns_head)); + hash_init(request->ip_map); rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count); if (rr_count > 1) { diff --git a/fast_ping.c b/fast_ping.c index 1e39620..1c93ea2 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -298,7 +298,8 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) 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)) { - tlog(TLOG_ERROR, "sendto %s\n", strerror(errno)); + char ping_host_name[PING_MAX_HOSTLEN]; + tlog(TLOG_ERROR, "sendto %s %s\n", gethost_by_addr(ping_host_name, (struct sockaddr *)&ping_host->addr, ping_host->addr_len), strerror(errno)); goto errout; } diff --git a/include/atomic.h b/include/atomic.h index e5dbbea..a5564fe 100755 --- a/include/atomic.h +++ b/include/atomic.h @@ -1,4 +1,3 @@ -//Source: http://golubenco.org/atomic-operations.html #ifndef _GENERIC_ATOMIC_H #define _GENERIC_ATOMIC_H diff --git a/include/cache.h b/include/cache.h new file mode 100644 index 0000000..e69a0c6 --- /dev/null +++ b/include/cache.h @@ -0,0 +1,22 @@ +#ifndef _GENERIC_CACHE_H + +#include "list.h" +#include "hashtable.h" + +struct cache_node { + struct hlist_node list; +}; + +struct cache_head; + +struct cache_head *cache_new(int hashsize, void (*item_free)(struct cache_head *head, struct cache_node *node)); + +int cache_add(struct cache_head *head, struct cache_node *node, void *key, int key_len); + +struct cache_node *cache_lookup(struct cache_head *head, void *key, int key_len); + +int cache_update(struct cache_head *head, void *key, int key_len); + +void cache_free(struct cache_head *head); + +#endif // !_GENERIC_CACHE_H diff --git a/include/findbit.h b/include/findbit.h index cac0939..0a6feb9 100644 --- a/include/findbit.h +++ b/include/findbit.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ #define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ diff --git a/include/gcc_builtin.h b/include/gcc_builtin.h index 366813b..0d34b2c 100644 --- a/include/gcc_builtin.h +++ b/include/gcc_builtin.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TOOLS_LINUX_COMPILER_H_ #define _TOOLS_LINUX_COMPILER_H_ diff --git a/include/hashtable.h b/include/hashtable.h index 2823192..f21b2c1 100644 --- a/include/hashtable.h +++ b/include/hashtable.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: GPL-2.0 */ /* * Statically sized hash table implementation * (C) 2012 Sasha Levin diff --git a/lib/cache.c b/lib/cache.c new file mode 100644 index 0000000..a0b0546 --- /dev/null +++ b/lib/cache.c @@ -0,0 +1,8 @@ +#include "cache.h" +#include + +struct cache_head { + struct hlist_head hash_head; + int hash_size; + pthread_rwlock_t *rwlock; +};