From 6c271f63281ca2263ebbd7ad7f6788bc4449d279 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 12 Mar 2025 10:02:05 +1100 Subject: [PATCH] Add "+showbadvers" to dig and reset EDNS version Add "+showbadvers" to display the BADVERS response similarly to "+showbadcookie". Additionally reset the EDNS version to the requested version in "dig +trace" so that EDNS version negotiation can be tested at all levels of the trace rather that just when requesting the root nameservers. --- bin/dig/dig.c | 18 ++++++++++++++++-- bin/dig/dig.rst | 6 ++++++ bin/dig/dighost.c | 12 +++++++++++- bin/dig/dighost.h | 7 ++++--- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 23f5b57130..ff3148eacf 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -289,6 +289,7 @@ help(void) { " form of answers - global " "option)\n" " +[no]showbadcookie (Show BADCOOKIE message)\n" + " +[no]showbadvers (Show BADVERS message)\n" " +[no]showsearch (Search with intermediate " "results)\n" " +[no]split=## (Split hex/base64 fields " @@ -1772,6 +1773,8 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, FULLCHECK("edns"); if (!state) { lookup->edns = -1; + lookup->original_edns = + -1; break; } if (value == NULL) { @@ -1788,6 +1791,7 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, goto exit_or_usage; } lookup->edns = num; + lookup->original_edns = num; break; case 'f': FULLCHECK("ednsflags"); @@ -2306,8 +2310,18 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, case 'w': /* showsearch */ switch (cmd[4]) { case 'b': - FULLCHECK("showbadcookie"); - lookup->showbadcookie = state; + switch (cmd[7]) { + case 'c': + FULLCHECK("showbadcookie"); + lookup->showbadcookie = state; + break; + case 'v': + FULLCHECK("showbadvers"); + lookup->showbadvers = state; + break; + default: + goto invalid_option; + } break; case 's': FULLCHECK("showsearch"); diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index fa436fefac..3b961f8fee 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -614,6 +614,12 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to BADCOOKIE rcode before retrying the request or not. The default is to not show the messages. +.. option:: +showbadvers, +noshowbadvers + + This option toggles whether to show the message containing the + BADVERS rcode before retrying the request or not. The default + is to not show the messages. + .. option:: +showsearch, +noshowsearch This option performs [or does not perform] a search showing intermediate results. diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 69a310d2f3..5069af6b4f 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -605,6 +605,7 @@ make_empty_lookup(void) { .idnout = idnout, .udpsize = -1, .edns = -1, + .original_edns = -1, .recurse = true, .retries = tries, .comments = true, @@ -738,6 +739,7 @@ clone_lookup(dig_lookup_t *lookold, bool servers) { } looknew->showbadcookie = lookold->showbadcookie; + looknew->showbadvers = lookold->showbadvers; looknew->sendcookie = lookold->sendcookie; looknew->seenbadcookie = lookold->seenbadcookie; looknew->badcookie = lookold->badcookie; @@ -764,6 +766,7 @@ clone_lookup(dig_lookup_t *lookold, bool servers) { looknew->idnout = lookold->idnout; looknew->udpsize = lookold->udpsize; looknew->edns = lookold->edns; + looknew->original_edns = lookold->original_edns; looknew->recurse = lookold->recurse; looknew->aaonly = lookold->aaonly; looknew->adflag = lookold->adflag; @@ -1938,6 +1941,7 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { } domain = dns_fixedname_name(&lookup->fdomain); dns_name_copy(name, domain); + lookup->edns = lookup->original_edns; } debug("adding server %s", namestr); num = getaddresses(lookup, namestr, &lresult); @@ -2456,7 +2460,8 @@ setup_lookup(dig_lookup_t *lookup) { lookup->udpsize = DEFAULT_EDNS_BUFSIZE; } if (lookup->edns < 0) { - lookup->edns = DEFAULT_EDNS_VERSION; + lookup->original_edns = lookup->edns = + DEFAULT_EDNS_VERSION; } if (lookup->nsid) { @@ -4300,6 +4305,11 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, if (msg->rcode == dns_rcode_badvers && msg->opt != NULL && (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) { + if (l->showbadvers) { + dighost_printmessage(query, &b, msg, true); + dighost_received(isc_buffer_usedlength(&b), &peer, + query); + } /* * Add minimum EDNS version required checks here if needed. */ diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h index 8c404d115d..db8c842f75 100644 --- a/bin/dig/dighost.h +++ b/bin/dig/dighost.h @@ -117,9 +117,9 @@ struct dig_lookup { section_answer, section_authority, section_question, seenbadcookie, sendcookie, servfail_stops, setqid, /*% use a speciied query ID */ - showbadcookie, stats, tcflag, tcp_keepalive, tcp_mode, - tcp_mode_set, tls_mode, /*% connect using TLS */ - trace, /*% dig +trace */ + showbadcookie, showbadvers, stats, tcflag, tcp_keepalive, + tcp_mode, tcp_mode_set, tls_mode, /*% connect using TLS */ + trace, /*% dig +trace */ trace_root, /*% initial query for either +trace or +nssearch */ ttlunits, use_usec, waiting_connect, zflag; char textname[MXNAME]; /*% Name we're going to be looking up */ @@ -148,6 +148,7 @@ struct dig_lookup { int nsfound; int16_t udpsize; int16_t edns; + int16_t original_edns; int16_t padding; uint32_t ixfr_serial; isc_buffer_t rdatabuf;