From 7e985e7d113405030f5ee59fed9d709fb784a685 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Wed, 8 Jun 2022 23:28:46 +0800 Subject: [PATCH] dns_server: fix dualstack select issue. --- etc/smartdns/smartdns.conf | 2 +- src/dns_cache.c | 2 +- src/dns_conf.c | 2 +- src/dns_server.c | 107 +++++++++++++++++++++++++------------ 4 files changed, 75 insertions(+), 38 deletions(-) diff --git a/etc/smartdns/smartdns.conf b/etc/smartdns/smartdns.conf index 808e67c..b332d55 100644 --- a/etc/smartdns/smartdns.conf +++ b/etc/smartdns/smartdns.conf @@ -38,7 +38,7 @@ bind [::]:53 # dns cache size # cache-size [number] # 0: for no cache -cache-size 4096 +cache-size 16384 # enable persist cache when restart # cache-persist yes diff --git a/src/dns_cache.c b/src/dns_cache.c index 6ecff77..81c6e40 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -551,7 +551,7 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre) } if (ttl < 0) { - if (dns_cache_head.enable_inactive && (dns_cache_is_soa(dns_cache) == 0)) { + if (dns_cache_head.enable_inactive) { _dns_cache_move_inactive(dns_cache); } else { _dns_cache_remove(dns_cache); diff --git a/src/dns_conf.c b/src/dns_conf.c index 062bd84..513b8d2 100644 --- a/src/dns_conf.c +++ b/src/dns_conf.c @@ -64,7 +64,7 @@ int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE; int dns_conf_prefetch = 0; int dns_conf_serve_expired = 1; int dns_conf_serve_expired_ttl = 0; -int dns_conf_serve_expired_reply_ttl = 5; +int dns_conf_serve_expired_reply_ttl = 3; /* upstream servers */ struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; diff --git a/src/dns_server.c b/src/dns_server.c index 018c2a3..0df566c 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -219,7 +219,7 @@ struct dns_request { int dualstack_selection; int dualstack_selection_force_soa; - int dualstack_selection_force_disable; + int dualstack_selection_query; int dualstack_selection_ping_time; int dualstack_selection_has_ip; struct dns_request *dualstack_request; @@ -314,7 +314,7 @@ static void _dns_server_set_dualstack_selection(struct dns_request *request) { struct dns_rule_flags *rule_flag = NULL; - if (request->dualstack_selection_force_disable) { + if (request->dualstack_selection_query) { request->dualstack_selection = 0; return; } @@ -1425,7 +1425,7 @@ int _dns_server_reply_all_pending_list(struct dns_request *request, struct dns_s context->inpacket_len); _dns_server_get_answer(&context_pending); req->dualstack_selection = request->dualstack_selection; - req->dualstack_selection_force_disable = request->dualstack_selection_force_disable; + req->dualstack_selection_query = request->dualstack_selection_query; req->dualstack_selection_force_soa = request->dualstack_selection_force_soa; req->dualstack_selection_has_ip = request->dualstack_selection_has_ip; req->dualstack_selection_ping_time = request->dualstack_selection_ping_time; @@ -1449,6 +1449,44 @@ int _dns_server_reply_all_pending_list(struct dns_request *request, struct dns_s return ret; } +static int _dns_server_force_dualstack(struct dns_request *request) +{ + /* for dualstack request as first pending request, check if need to choose another request*/ + if (request->dualstack_request) { + struct dns_request *dualstack_request = request->dualstack_request; + request->dualstack_selection_has_ip = dualstack_request->has_ip; + request->dualstack_selection_ping_time = dualstack_request->ping_time; + request->dualstack_selection = 1; + } + + if (request->dualstack_selection_ping_time < 0 || request->dualstack_selection == 0) { + return -1; + } + + if (request->has_soa || request->rcode != DNS_RC_NOERROR) { + return -1; + } + + if (request->dualstack_selection_has_ip == 0) { + return -1; + } + + if (request->ping_time > 0) { + if (request->dualstack_selection_ping_time + (dns_conf_dualstack_ip_selection_threshold * 10) > + request->ping_time) { + return -1; + } + } + + /* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */ + tlog(TLOG_INFO, "result: %s, qtype: %d, force %s perfered, id: %d, time1: %d, time2: %d", request->domain, + request->qtype, request->qtype == DNS_T_AAAA ? "IPv4" : "IPv6", request->id, request->ping_time, + request->dualstack_selection_ping_time); + request->dualstack_selection_force_soa = 1; + + return 0; +} + static int _dns_server_request_complete(struct dns_request *request) { int ttl = DNS_SERVER_TMOUT_TTL; @@ -1465,14 +1503,6 @@ static int _dns_server_request_complete(struct dns_request *request) return 0; } - /* for dualstack request as first pending request, check if need to choose another request*/ - if (request->dualstack_request) { - struct dns_request *dualstack_request = request->dualstack_request; - request->dualstack_selection_has_ip = dualstack_request->has_ip; - request->dualstack_selection_ping_time = dualstack_request->ping_time; - request->dualstack_selection = 1; - } - if (request->has_ip != 0) { request->has_soa = 0; if (request->has_ping_result == 0 && request->ip_ttl > DNS_SERVER_TMOUT_TTL) { @@ -1481,18 +1511,8 @@ static int _dns_server_request_complete(struct dns_request *request) ttl = request->ip_ttl; } - if (request->dualstack_selection_ping_time > 0 && request->dualstack_selection && - request->dualstack_selection_has_ip) { - if ((request->dualstack_selection_ping_time + (dns_conf_dualstack_ip_selection_threshold * 10)) < - request->ping_time || - request->ping_time < 0) { - /* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */ - tlog(TLOG_INFO, "result: %s, qtype: %d, force %s perfered, id: %d, time1: %d, time2: %d", request->domain, - request->qtype, request->qtype == DNS_T_AAAA ? "IPv4" : "IPv6", request->id, request->ping_time, - request->dualstack_selection_ping_time); - request->dualstack_selection_force_soa = 1; - goto out; - } + if (_dns_server_force_dualstack(request) == 0) { + goto out; } if (request->has_soa) { @@ -1707,8 +1727,13 @@ static void _dns_server_complete_with_multi_ipaddress(struct dns_request *reques { struct dns_server_post_context context; int do_reply = 0; + if (request->ip_map_num > 0) { + request->has_soa = 0; + } + if (atomic_inc_return(&request->notified) == 1) { do_reply = 1; + _dns_server_force_dualstack(request); } _dns_server_post_context_init(&context, request); @@ -2347,7 +2372,9 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain, } break; case DNS_T_SOA: { request->has_soa = 1; - request->rcode = packet->head.rcode; + if (request->rcode != DNS_RC_NOERROR) { + request->rcode = packet->head.rcode; + } dns_get_SOA(rrs, name, 128, &ttl, &request->soa); tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: " @@ -2355,7 +2382,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain, domain, request->qtype, request->soa.mname, request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum); int soa_num = atomic_inc_return(&request->soa_num); - if (soa_num >= (dns_server_num() / 3) + 1 || soa_num > 4) { + if ((soa_num >= (dns_server_num() / 3) + 1 || soa_num > 4) && request->ip_map_num <= 0) { _dns_server_request_complete(request); } } break; @@ -2534,7 +2561,9 @@ static int _dns_server_get_answer(struct dns_server_post_context *context) } break; case DNS_T_SOA: { request->has_soa = 1; - request->rcode = packet->head.rcode; + if (request->rcode != DNS_RC_NOERROR) { + request->rcode = packet->head.rcode; + } dns_get_SOA(rrs, name, 128, &ttl, &request->soa); tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: " @@ -3400,12 +3429,7 @@ static int _dns_server_process_cache(struct dns_request *request) goto out; } - if (dns_cache_is_soa(dns_cache)) { - ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request); - goto out; - } - - if (request->dualstack_selection && request->qtype == DNS_T_AAAA) { + if (request->dualstack_selection) { int dualstack_qtype; if (request->qtype == DNS_T_A) { dualstack_qtype = DNS_T_AAAA; @@ -3418,18 +3442,31 @@ static int _dns_server_process_cache(struct dns_request *request) dualstack_dns_cache = dns_cache_lookup(request->domain, dualstack_qtype); if (dualstack_dns_cache && dns_cache_is_soa(dualstack_dns_cache) == 0 && (dualstack_dns_cache->info.speed > 0)) { + + if (dns_cache_is_soa(dns_cache)) { + ret = _dns_server_process_cache_packet(request, dns_cache); + goto out_update_cache; + } + if ((dualstack_dns_cache->info.speed + (dns_conf_dualstack_ip_selection_threshold * 10)) < dns_cache->info.speed || dns_cache->info.speed < 0) { tlog(TLOG_DEBUG, "cache result: %s, qtype: %d, force %s perfered, id: %d, time1: %d, time2: %d", request->domain, request->qtype, request->qtype == DNS_T_AAAA ? "IPv4" : "IPv6", request->id, - request->ping_time, request->dualstack_selection_ping_time); + dns_cache->info.speed, dualstack_dns_cache->info.speed); ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request); goto out_update_cache; } } } + if (dns_cache_is_soa(dns_cache)) { + if (dns_cache_get_ttl(dns_cache) > 0) { + ret = _dns_server_process_cache_packet(request, dns_cache); + } + goto out; + } + ret = _dns_server_process_cache_data(request, dns_cache); if (ret != 0) { goto out; @@ -3760,7 +3797,7 @@ int _dns_server_query_dualstack(struct dns_request *request) request_dualstack->server_flags = request->server_flags; safe_strncpy(request_dualstack->domain, request->domain, sizeof(request->domain)); request_dualstack->qtype = qtype; - request_dualstack->dualstack_selection_force_disable = 1; + request_dualstack->dualstack_selection_query = 1; request_dualstack->prefetch = request->prefetch; _dns_server_request_get(request); request_dualstack->dualstack_request = request; @@ -3838,7 +3875,7 @@ static int _dns_server_do_query(struct dns_request *request) _dns_server_check_set_passthrough(request); /* process cache */ - if (request->prefetch == 0) { + if (request->prefetch == 0 && request->dualstack_selection_query == 0) { if (_dns_server_process_cache(request) == 0) { goto clean_exit; }