diff --git a/CHANGES b/CHANGES index 9688232469..33c580c4d5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +4317. [bug] Age all unused servers on fetch timeout. [RT #41597] + 4316. [func] Add option to tools to print RRs in unknown presentation format [RT #41595]. diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 83c740a2d4..4708392b33 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -881,7 +881,8 @@ resquery_destroy(resquery_t **queryp) { static void fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, - isc_time_t *finish, isc_boolean_t no_response) + isc_time_t *finish, isc_boolean_t no_response, + isc_boolean_t age_untried) { fetchctx_t *fctx; resquery_t *query; @@ -993,14 +994,14 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, * Age RTTs of servers not tried. */ isc_stdtime_get(&now); - if (finish != NULL) + if (finish != NULL || age_untried) for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs); addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) if (UNMARKED(addrinfo)) dns_adb_agesrtt(fctx->adb, addrinfo, now); - if (finish != NULL && TRIEDFIND(fctx)) + if ((finish != NULL || age_untried) && TRIEDFIND(fctx)) for (find = ISC_LIST_HEAD(fctx->finds); find != NULL; find = ISC_LIST_NEXT(find, publink)) @@ -1011,7 +1012,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, dns_adb_agesrtt(fctx->adb, addrinfo, now); - if (finish != NULL && TRIEDALT(fctx)) { + if ((finish != NULL || age_untried) && TRIEDALT(fctx)) { for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs); addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) @@ -1082,7 +1083,9 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, } static void -fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) { +fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response, + isc_boolean_t age_untried) +{ resquery_t *query, *next_query; FCTXTRACE("cancelqueries"); @@ -1091,7 +1094,8 @@ fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) { query != NULL; query = next_query) { next_query = ISC_LIST_NEXT(query, link); - fctx_cancelquery(&query, NULL, NULL, no_response); + fctx_cancelquery(&query, NULL, NULL, no_response, + age_untried); } } @@ -1158,9 +1162,11 @@ fctx_cleanupaltaddrs(fetchctx_t *fctx) { } static inline void -fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) { +fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response, + isc_boolean_t age_untried) +{ FCTXTRACE("stopeverything"); - fctx_cancelqueries(fctx, no_response); + fctx_cancelqueries(fctx, no_response, age_untried); fctx_cleanupfinds(fctx); fctx_cleanupaltfinds(fctx); fctx_cleanupforwaddrs(fctx); @@ -1398,6 +1404,7 @@ static void fctx_done(fetchctx_t *fctx, isc_result_t result, int line) { dns_resolver_t *res; isc_boolean_t no_response = ISC_FALSE; + isc_boolean_t age_untried = ISC_FALSE; REQUIRE(line >= 0); @@ -1411,10 +1418,11 @@ fctx_done(fetchctx_t *fctx, isc_result_t result, int line) { */ log_edns(fctx); no_response = ISC_TRUE; - } + } else if (result == ISC_R_TIMEDOUT) + age_untried = ISC_TRUE; fctx->reason = NULL; - fctx_stopeverything(fctx, no_response); + fctx_stopeverything(fctx, no_response, age_untried); LOCK(&res->buckets[fctx->bucketnum].lock); @@ -1464,7 +1472,8 @@ process_sendevent(resquery_t *query, isc_event_t *event) { */ add_bad(fctx, query->addrinfo, sevent->result, badns_unreachable); - fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); + fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, + ISC_FALSE); retry = ISC_TRUE; break; @@ -1473,7 +1482,8 @@ process_sendevent(resquery_t *query, isc_event_t *event) { "unexpected event result; responding", sevent->result); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, + ISC_FALSE); break; } } @@ -2636,7 +2646,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { FCTXTRACE("query canceled: idle timer failed; " "responding"); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, + ISC_FALSE); fctx_done(fctx, result, __LINE__); break; } @@ -2675,7 +2686,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { FCTXTRACE("query canceled: " "resquery_send() failed; responding"); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE); fctx_done(fctx, result, __LINE__); } break; @@ -2694,7 +2705,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { * No route to remote. */ isc_socket_detach(&query->tcpsocket); - fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); + fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE); retry = ISC_TRUE; break; @@ -2704,7 +2715,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { sevent->result); isc_socket_detach(&query->tcpsocket); - fctx_cancelquery(&query, NULL, NULL, ISC_FALSE); + fctx_cancelquery(&query, NULL, NULL, ISC_FALSE, ISC_FALSE); break; } } @@ -3680,7 +3691,7 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) { if (addrinfo == NULL) { /* We have no more addresses. Start over. */ - fctx_cancelqueries(fctx, ISC_TRUE); + fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE); fctx_cleanupfinds(fctx); fctx_cleanupaltfinds(fctx); fctx_cleanupforwaddrs(fctx); @@ -3890,7 +3901,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) { isc_time_compare(&tevent->due, &query->start) >= 0) { FCTXTRACE("query timed out; no response"); - fctx_cancelquery(&query, NULL, NULL, ISC_TRUE); + fctx_cancelquery(&query, NULL, NULL, ISC_TRUE, ISC_FALSE); } fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; @@ -3984,7 +3995,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) { * fetch. To avoid deadlock with the ADB, we must do this * before we lock the bucket lock. */ - fctx_stopeverything(fctx, ISC_FALSE); + fctx_stopeverything(fctx, ISC_FALSE, ISC_FALSE); LOCK(&res->buckets[bucketnum].lock); @@ -8444,7 +8455,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * * XXXRTH Don't cancel the query if waiting for validation? */ - fctx_cancelquery(&query, &devent, finish, no_response); + fctx_cancelquery(&query, &devent, finish, no_response, ISC_FALSE); if (keep_trying) { if (result == DNS_R_FORMERR) @@ -8508,7 +8519,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } fctx->ns_ttl = fctx->nameservers.ttl; fctx->ns_ttl_ok = ISC_TRUE; - fctx_cancelqueries(fctx, ISC_TRUE); + fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE); fctx_cleanupfinds(fctx); fctx_cleanupaltfinds(fctx); fctx_cleanupforwaddrs(fctx); @@ -8541,7 +8552,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * DNSSEC validator to validate the answer. */ FCTXTRACE("wait for validator"); - fctx_cancelqueries(fctx, ISC_TRUE); + fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE); /* * We must not retransmit while the validator is working; * it has references to the current rmessage. @@ -8552,7 +8563,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { } else if (result == DNS_R_CHASEDSSERVERS) { unsigned int n; add_bad(fctx, addrinfo, result, broken_type); - fctx_cancelqueries(fctx, ISC_TRUE); + fctx_cancelqueries(fctx, ISC_TRUE, ISC_FALSE); fctx_cleanupfinds(fctx); fctx_cleanupforwaddrs(fctx);