Fix dig hanging issue in cases when the lookup's next query can't start

In recv_done(), when dig decides to start the lookup's next query in
the line using `start_udp()` or `start_tcp()`, and for some reason,
no queries get started, dig doesn't cancel the lookup.

This can occur, for example, when there are two queries in the lookup,
one with a regular IP address, and another with a IPv4 mapped IPv6
address. When the regular IP address fails to serve the query, its
`recv_done()` callback starts the next query in the line (in this
case the one with a mapped IP address), but because `dig` doesn't
connect to such IP addresses, and there are no other queries in the
list, no new queries are being started, and the lookup keeps hanging.

After calling `start_udp()` or `start_tcp()` in `recv_done()`, check
if there are no pending/working queries then cancel the lookup instead
of only detaching from the current query.

(cherry picked from commit 7e2f50c369)
This commit is contained in:
Aram Sargsyan 2022-04-01 13:12:40 +00:00
parent 2c4e7c1702
commit 1294de8e36
2 changed files with 25 additions and 0 deletions

View file

@ -3691,6 +3691,9 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
l->retries);
start_udp(newq);
}
if (check_if_queries_done(l, query)) {
goto cancel_lookup;
}
goto detach_query;
} else if (l->retries > 1 && l->tcp_mode) {
@ -3727,6 +3730,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
start_udp(next);
}
}
if (check_if_queries_done(l, query)) {
goto cancel_lookup;
}
goto detach_query;
}
@ -3768,6 +3775,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
start_udp(next);
}
}
if (check_if_queries_done(l, query)) {
goto cancel_lookup;
}
goto detach_query;
}
@ -4044,6 +4055,10 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
? "SERVFAIL reply"
: "recursion not available",
query->servname);
if (check_if_queries_done(l, query)) {
goto cancel_lookup;
}
goto detach_query;
}
}

View file

@ -1071,6 +1071,16 @@ if [ -x "$DIG" ] ; then
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
# See [GL #3248] for more information
n=$((n+1))
echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)"
ret=0
dig_with_opts @10.53.0.8 @::ffff:10.53.0.8 a.example > dig.out.test$n 2>&1 || ret=1
grep -F ";; Skipping mapped address" dig.out.test$n > /dev/null || ret=1
grep -F ";; No acceptable nameservers" dig.out.test$n > /dev/null || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
else
echo_i "$DIG is needed, so skipping these dig tests"
fi