dns_server: fix dualstack select issue.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
107
src/dns_server.c
107
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user