From 58685cd573e8de1fd023232dc5b3118c78ec6f52 Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Wed, 9 Mar 2022 19:45:54 +0000 Subject: [PATCH] When resending a UDP request, insert the query to the lookup's list When a query times out, and `dig` (or `host`) creates a new query to resend the request, it is being prepended to the lookup's queries list, which can cause a confusion later, making `dig` (or `host`) believe that there is another new query in the list, but that is actually the old one, which was timed out. That mistake will result in an assertion failure. That can happen, in particular, when after a timed out request, the retried request returns a SERVFAIL result, and the recursion is enabled, and `+nofail` option was used with `dig` (that is the default behavior in `host`, unless the `-s` option is provided). Fix the problem by inserting the query just after the current, timed-out query, instead of prepending to the list. Before calling start_udp() detach `l->current_query`, like it is done in another place in the function. Slightly update a couple of debug messages to make them more consistent. (cherry picked from commit a96247594816e892bdf9fd2ca4025ad078e52995) --- bin/dig/dighost.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index bd0818d4f4..360e8a3b97 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -3061,7 +3061,8 @@ force_next(dig_query_t *query) { if (l->retries > 1) { l->retries--; - debug("making new TCP request, %d tries left", l->retries); + debug("making new %s request, %d tries left", + l->tcp_mode ? "TCP" : "UDP", l->retries); requeue_lookup(l, true); lookup_detach(&l); isc_refcount_decrement0(&recvcount); @@ -3625,13 +3626,14 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, dig_query_t *newq = NULL; l->retries--; - debug("resending UDP request to first server, %d tries left", - l->retries); + debug("making new UDP request, %d tries left", l->retries); newq = new_query(l, query->servname, query->userarg); - ISC_LIST_PREPEND(l->q, newq, link); - - start_udp(ISC_LIST_HEAD(l->q)); + ISC_LIST_INSERTAFTER(l->q, query, newq, link); + if (l->current_query == query) { + query_detach(&l->current_query); + } + start_udp(newq); goto detach_query; }