]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
When resending a UDP request, insert the query to the lookup's list
authorAram Sargsyan <aram@isc.org>
Wed, 9 Mar 2022 19:45:54 +0000 (19:45 +0000)
committerAram Sargsyan <aram@isc.org>
Fri, 18 Mar 2022 08:23:53 +0000 (08:23 +0000)
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.

bin/dig/dighost.c

index bd0818d4f4bb3ceee5946ef7efb21804856a55ee..360e8a3b974563e8c47ce41c8f82f82d85c091d4 100644 (file)
@@ -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;
        }