Fix a crash in dig NS search mode

In special NS search mode, after the initial lookup, dig starts the
followup lookup with discovered NS servers in the queries list. If one
of those queries then fail, dig, as usual, tries to start the next query
in the list, which results in a crash, because the NS search mode is
special in a way that the queries are running in parallel, so the next
query is usually already started.

Apply some special logic in `recv_done()` function to deal with the
described situation when handling the query result for the NS search
mode. Particularly, print a warning message for the failed query,
and do not try to start the next query in the list. Also, set a non-zero
exit code if all the queries in the followup lookup fail.
This commit is contained in:
Aram Sargsyan
2022-05-19 20:44:32 +00:00
parent 99baab6268
commit 1290863c22
2 changed files with 47 additions and 2 deletions

View File

@@ -3879,6 +3879,51 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
goto next_lookup;
}
/*
* NSSEARCH mode is special, because the queries in the followup lookup
* are independent and they are being started in parallel, so if one of
* them fails there is no need to start the next query in the lookup,
* and this failure can be treated as a soft error (with a warning
* message), because there are usually more than one NS servers in the
* lookup's queries list. However, if there was not a single successful
* query in the followup lookup, then print an error message and exit
* with a non-zero exit code.
*/
if (l->ns_search_only && !l->trace_root) {
if (eresult == ISC_R_SUCCESS) {
l->ns_search_success = true;
} else {
char sockstr[ISC_SOCKADDR_FORMATSIZE];
isc_sockaddr_format(&query->sockaddr, sockstr,
sizeof(sockstr));
dighost_warning("communications error to %s: %s",
sockstr, isc_result_totext(eresult));
/*
* If this is not the last query, then we detach the
* query, but keep the lookup running.
*/
if (!check_if_queries_done(l, query)) {
goto detach_query;
}
/*
* This is the last query, and if there was not a
* single successful query in the whole lookup, then
* treat the situation as an error.
*/
if (!l->ns_search_success) {
dighost_error("no NS servers could be reached");
if (exitcode < 9) {
exitcode = 9;
}
}
goto cancel_lookup;
}
}
if (eresult == ISC_R_TIMEDOUT) {
if (l->retries > 1 && !l->tcp_mode) {
dig_query_t *newq = NULL;

View File

@@ -114,8 +114,8 @@ struct dig_lookup {
idnin, idnout, ignore, multiline, need_search, new_search,
noclass, nocrypto, nottl, ns_search_only, /*%< dig +nssearch,
host -C */
nsid, /*% Name Server ID (RFC 5001) */
onesoa, pending, /*%< Pending a successful answer */
ns_search_success, nsid, /*% Name Server ID (RFC 5001) */
onesoa, pending, /*%< Pending a successful answer */
print_unknown_format, qr, raflag, recurse, section_additional,
section_answer, section_authority, section_question,
seenbadcookie, sendcookie, servfail_stops,