Fix DiG UDP query retry and fail-over bug

When the `udp_ready()` callback function gets called with a failure
result code, DiG erroneously cancels the lookup.

Copy the logic behind `tcp_connected()` callback function into
`udp_ready()` so that DiG will now retry the failed query (if retries
are enabled) and then, if it fails again, it will fail-over to the next
server in the list, which synchronizes the behavior between TCP and UDP
modes.

Also, `udp_ready()` was calling `lookup_detach()` without calling
`lookup_attach()` first, but the issue was masked behind the fact
that `clear_current_lookup()` wasn't being called when needed, and
`lookup_detach()` was compensating for that. This also has been fixed.

(cherry picked from commit 3f3108552577c326b4dab6c3b631c51cf0040144)
This commit is contained in:
Aram Sargsyan 2022-06-15 12:57:14 +00:00
parent c003127717
commit be8ec6ef18

View file

@ -3112,6 +3112,9 @@ send_udp(dig_query_t *query) {
static void
udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
dig_query_t *query = (dig_query_t *)arg;
dig_query_t *next = NULL;
char sockstr[ISC_SOCKADDR_FORMATSIZE];
dig_lookup_t *l = NULL;
dig_query_t *readquery = NULL;
int local_timeout = timeout * 1000;
@ -3132,30 +3135,63 @@ udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
debug("udp_ready(%p, %s, %p)", handle, isc_result_totext(eresult),
query);
if (eresult == ISC_R_CANCELED || query->canceled) {
dig_lookup_t *l = query->lookup;
LOCK_LOOKUP;
lookup_attach(query->lookup, &l);
if (eresult == ISC_R_CANCELED || query->canceled) {
debug("in cancel handler");
if (!query->canceled) {
cancel_lookup(l);
}
query_detach(&query);
lookup_detach(&l);
clear_current_lookup();
UNLOCK_LOOKUP;
return;
} else if (eresult != ISC_R_SUCCESS) {
dig_lookup_t *l = query->lookup;
debug("udp setup failed: %s", isc_result_totext(eresult));
isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
dighost_warning("UDP setup with %s(%s) for %s failed: %s.",
sockstr, query->servname, l->textname,
isc_result_totext(eresult));
if (exitcode < 9) {
exitcode = 9;
}
if (l->retries > 1) {
l->retries--;
debug("making new UDP request, %d tries left",
l->retries);
requeue_lookup(l, true);
next = NULL;
} else if ((l->current_query != NULL) &&
(ISC_LINK_LINKED(l->current_query, link)))
{
next = ISC_LIST_NEXT(l->current_query, link);
} else {
next = NULL;
}
query_detach(&query);
cancel_lookup(l);
if (next == NULL) {
cancel_lookup(l);
}
lookup_detach(&l);
if (next != NULL) {
start_udp(next);
} else {
clear_current_lookup();
}
check_if_done();
UNLOCK_LOOKUP;
return;
}
exitcode = 0;
query_attach(query, &readquery);
debug("recving with lookup=%p, query=%p, handle=%p", query->lookup,
@ -3177,6 +3213,8 @@ udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
send_udp(readquery);
query_detach(&query);
lookup_detach(&l);
UNLOCK_LOOKUP;
}
/*%