diff --git a/src/dns_cache.c b/src/dns_cache.c index 04b9cfe..08b6506 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -66,7 +66,7 @@ static void _dns_cache_remove(struct dns_cache *dns_cache) dns_cache_release(dns_cache); } -int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len) +int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed) { struct dns_cache *dns_cache = NULL; @@ -90,6 +90,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ dns_cache->qtype = qtype; dns_cache->ttl = ttl; dns_cache->del_pending = 0; + dns_cache->speed = speed; time(&dns_cache->insert_time); pthread_mutex_unlock(&dns_cache_head.lock); if (qtype == DNS_T_A) { @@ -121,7 +122,7 @@ errout: return -1; } -int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len) +int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed) { uint32_t key = 0; struct dns_cache *dns_cache = NULL; @@ -155,6 +156,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type dns_cache->ttl = ttl; dns_cache->hitnum = 2; dns_cache->del_pending = 0; + dns_cache->speed = speed; atomic_set(&dns_cache->ref, 1); time(&dns_cache->insert_time); if (qtype == DNS_T_A) { diff --git a/src/dns_cache.h b/src/dns_cache.h index dad5a39..efbbf4b 100644 --- a/src/dns_cache.h +++ b/src/dns_cache.h @@ -19,7 +19,8 @@ struct dns_cache { char domain[DNS_MAX_CNAME_LEN]; char cname[DNS_MAX_CNAME_LEN]; unsigned int cname_ttl; - unsigned int ttl; + unsigned int ttl;; + unsigned int speed; int hitnum; int del_pending; time_t insert_time; @@ -33,9 +34,9 @@ struct dns_cache { int dns_cache_init(int size); -int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len); +int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed); -int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len); +int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed); struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype); diff --git a/src/dns_server.c b/src/dns_server.c index 5bfa745..dd63034 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -550,33 +550,16 @@ static int _dns_server_request_complete(struct dns_request *request) /* if doing prefetch, update cache only */ if (request->prefetch) { - dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); + dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4); } else { /* insert result to cache */ - dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); + dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4); } request->has_soa = 0; } } else if (request->qtype == DNS_T_AAAA) { - if (request->has_ipv4 && request->ping_ttl_v4 > 0) { - 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]); - - /* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */ - if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) { - tlog(TLOG_DEBUG, "Force IPV4 perfered."); - if (request->prefetch) { - dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); - } else { - dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN); - } - - return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL); - } - } - if (request->has_ipv6) { 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[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], @@ -589,15 +572,32 @@ static int _dns_server_request_complete(struct dns_request *request) /* if doing prefetch, update cache only */ if (request->prefetch) { - dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN); + dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6); } else { /* insert result to cache */ - dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN); + dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6); } - - request->has_ipv4 = 0; - request->has_soa = 0; } + + if (request->has_ipv4 && request->ping_ttl_v4 > 0) { + 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]); + + /* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */ + if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) { + tlog(TLOG_DEBUG, "Force IPV4 perfered."); + if (request->prefetch) { + dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4); + } else { + dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4); + } + + return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL); + } + request->has_ipv4 = 0; + } + + request->has_soa = 0; } if (request->has_soa) { @@ -1445,6 +1445,16 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac goto errout; } + if (dns_conf_dualstack_ip_selection && request->qtype == DNS_T_AAAA) { + struct dns_cache *dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A); + if (dns_cache_A) { + if ((dns_cache_A->speed + (dns_conf_dualstack_ip_selection_threshold * 10)) < dns_cache->speed || dns_cache->speed < 0) { + tlog(TLOG_DEBUG, "Force IPV4 perfered."); + return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL); + } + } + } + /* Cache hits, returning results in the cache */ switch (request->qtype) { case DNS_T_A: