From 4ff67b18896de4f772d9d10c52cba5b7078fc184 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 27 May 2025 14:41:24 +1000 Subject: [PATCH 1/3] Add CO support to dig Dig now support setting the EDNS CO as flag using "+coflag" / "+nocoflag" rather than as part of +ednsflags. (cherry picked from commit 6c28411c55d595e3c9ce3f8d1754b24875eb5306) --- bin/dig/dig.c | 8 ++++++++ bin/dig/dig.rst | 9 ++++++++- bin/dig/dighost.c | 6 +++++- bin/dig/dighost.h | 9 ++++----- lib/dns/include/dns/message.h | 3 ++- lib/dns/message.c | 12 ++++++++++-- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index d31a0b664a..1e724c6185 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -196,6 +196,9 @@ help(void) { " +[no]cmd (Control display of " "command line -\n" " global option)\n" + " +[no]coflag (Set compact denial of " + "existence ok flag)\n" + " in query)\n" " +[no]comments (Control display of " "packet " "header\n" @@ -1285,6 +1288,11 @@ plus_option(char *option, bool is_batchfile, bool *need_clone, break; case 'o': /* comments */ switch (cmd[2]) { + case 'f': + case '\0': /* +co is a synonym for +coflag */ + FULLCHECK("coflag"); + lookup->coflag = state; + break; case 'm': FULLCHECK("comments"); lookup->comments = state; diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst index 59ac9f15dd..88b0a40307 100644 --- a/bin/dig/dig.rst +++ b/bin/dig/dig.rst @@ -298,6 +298,13 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to always has a global effect; it cannot be set globally and then overridden on a per-lookup basis. The default is to print this comment. +.. option:: +coflag, +co, +nocoflag, +noco + + This option sets [or does not set] the CO (Compact denial of + existence Ok) EDNS bit in the query. If set, it tells servers + that Compact Denial of Existence responses are acceptable when + replying to queries. The default is ``+nocoflag``. + .. option:: +comments, +nocomments This option toggles the display of some comment lines in the output, with @@ -363,7 +370,7 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to This option sets the must-be-zero EDNS flags bits (Z bits) to the specified value. Decimal, hex, and octal encodings are accepted. Setting a named flag - (e.g., DO) is silently ignored. By default, no Z bits are set. + (e.g. DO, CO) is silently ignored. By default, no Z bits are set. .. option:: +ednsnegotiation, +noednsnegotiation diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 87fbb41e1c..0f8ac1335c 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -789,6 +789,7 @@ clone_lookup(dig_lookup_t *lookold, bool servers) { looknew->aaonly = lookold->aaonly; looknew->adflag = lookold->adflag; looknew->cdflag = lookold->cdflag; + looknew->coflag = lookold->coflag; looknew->raflag = lookold->raflag; looknew->tcflag = lookold->tcflag; looknew->print_unknown_format = lookold->print_unknown_format; @@ -2655,10 +2656,13 @@ setup_lookup(dig_lookup_t *lookup) { } flags = lookup->ednsflags; - flags &= ~DNS_MESSAGEEXTFLAG_DO; + flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO); if (lookup->dnssec) { flags |= DNS_MESSAGEEXTFLAG_DO; } + if (lookup->coflag) { + flags |= DNS_MESSAGEEXTFLAG_CO; + } add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags, opts, i); } diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h index 227c315f51..09d136363d 100644 --- a/bin/dig/dighost.h +++ b/bin/dig/dighost.h @@ -105,11 +105,10 @@ typedef struct dig_searchlist dig_searchlist_t; struct dig_lookup { unsigned int magic; isc_refcount_t references; - bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, comments, - dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, expandaaaa, - expire, fuzzing, header_only, identify, /*%< Append an "on - server " message - */ + bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, coflag, + comments, dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg, + expandaaaa, expire, fuzzing, header_only, + identify, /*%< Append an "on server " message */ identify_previous_line, /*% Prepend a "Nameserver :" message, with newline and tab */ idnin, idnout, ignore, multiline, need_search, new_search, diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index f15884a183..b4c2c8ee9c 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -97,7 +97,8 @@ #define DNS_MESSAGEFLAG_CD 0x0010U /*%< EDNS0 extended message flags */ -#define DNS_MESSAGEEXTFLAG_DO 0x8000U +#define DNS_MESSAGEEXTFLAG_DO 0x8000U /* DNSSEC OK */ +#define DNS_MESSAGEEXTFLAG_CO 0x4000U /* Compact denial of existence OK */ /*%< EDNS0 extended OPT codes */ #define DNS_OPT_LLQ 1 /*%< LLQ opt code */ diff --git a/lib/dns/message.c b/lib/dns/message.c index 63c07abecb..9fdc2db30e 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -3513,9 +3513,13 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_pseudosection_t section, if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) { ADD_STRING(target, " do"); } + if ((ps->ttl & DNS_MESSAGEEXTFLAG_CO) != 0) { + ADD_STRING(target, " co"); + } ADD_STRING(target, "\n"); mbz = ps->ttl & 0xffff; - mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ + /* Exclude Known Flags. */ + mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO); if (mbz != 0) { INDENT(style); ADD_STRING(target, "MBZ: "); @@ -3871,8 +3875,12 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section, if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) { ADD_STRING(target, " do"); } + if ((ps->ttl & DNS_MESSAGEEXTFLAG_CO) != 0) { + ADD_STRING(target, " co"); + } mbz = ps->ttl & 0xffff; - mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ + /* Exclude Known Flags. */ + mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO); if (mbz != 0) { ADD_STRING(target, "; MBZ: "); snprintf(buf, sizeof(buf), "0x%.4x", mbz); From 0890fba57b25e6f074c14a7c11e3c5d281e5b95b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 27 May 2025 15:12:53 +1000 Subject: [PATCH 2/3] Add tests for 'dig +coflag' (cherry picked from commit c56af212f06556f6009c0509a02b300200c055c1) --- bin/tests/system/digdelv/tests.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh index 252884c4f7..aa9525df37 100644 --- a/bin/tests/system/digdelv/tests.sh +++ b/bin/tests/system/digdelv/tests.sh @@ -284,6 +284,27 @@ if [ -x "$DIG" ]; then if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status + ret)) + n=$((n + 1)) + echo_i "checking dig +coflag works ($n)" + ret=0 + dig_with_opts +tcp @10.53.0.3 +coflag +qr example >dig.out.test$n || ret=1 + grep "^; EDNS: version: 0, flags: co;" /dev/null || ret=1 + check_ttl_range dig.out.test$n "SOA" 300 || ret=1 + if [ $ret -ne 0 ]; then echo_i "failed"; fi + status=$((status + ret)) + + if [ $HAS_PYYAML -ne 0 ]; then + n=$((n + 1)) + echo_i "checking dig +coflag +yaml works ($n)" + ret=0 + dig_with_opts +yaml +tcp @10.53.0.3 +coflag +qr example >dig.out.test$n || ret=1 + $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS flags >yamlget.out.test$n 2>&1 || ret=1 + read -r value Date: Tue, 3 Jun 2025 10:04:01 +1000 Subject: [PATCH 3/3] Add "undefined" to +ednsflags description Reflow help message. (cherry picked from commit bbfb7ebda2da0998ec04adf6553f115b1b8ef302) --- bin/dig/dig.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 1e724c6185..db73a74d9f 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -216,7 +216,8 @@ help(void) { " +[no]dnssec (Request DNSSEC records)\n" " +domain=### (Set default domainname)\n" " +[no]edns[=###] (Set EDNS version) [0]\n" - " +ednsflags=### (Set EDNS flag bits)\n" + " +ednsflags=### (Set undefined EDNS flag " + "bits)\n" " +[no]ednsnegotiation (Set EDNS version " "negotiation)\n" " +ednsopt=###[:value] (Send specified EDNS " @@ -232,12 +233,14 @@ help(void) { " +[no]https[=###] (DNS-over-HTTPS mode) " "[/]\n" " +[no]https-get (Use GET instead of " - "default POST method while using HTTPS)\n" - " +[no]http-plain[=###] (DNS over plain HTTP " - "mode) " - "[/]\n" - " +[no]http-plain-get (Use GET instead of " - "default POST method while using plain HTTP)\n" + "default POST method\n" + " while using HTTPS)\n" + " +[no]http-plain[=###] (DNS over plain HTTP " + "mode) [/]\n" + " +[no]http-plain-get (Use GET instead of " + "default POST " + "method\n" + " while using plain HTTP)\n" " +[no]identify (ID responders in short " "answers)\n" #ifdef HAVE_LIBIDN2 @@ -266,7 +269,8 @@ help(void) { " +padding=### (Set padding block size " "[0])\n" " +qid=### (Specify the query ID to " - "use when sending queries)\n" + "use when sending\n" + " queries)\n" " +[no]qr (Print question before " "sending)\n" " +[no]question (Control display of " @@ -303,16 +307,19 @@ help(void) { " +timeout=### (Set query timeout) [5]\n" " +[no]tls (DNS-over-TLS mode)\n" " +[no]tls-ca[=file] (Enable remote server's " - "TLS certificate validation)\n" + "TLS certificate\n" + " validation)\n" " +[no]tls-hostname=hostname (Explicitly set " - "the expected TLS hostname)\n" + "the expected TLS\n" + " hostname)\n" " +[no]tls-certfile=file (Load client TLS " - "certificate chain from file)\n" + "certificate chain from\n" + " file)\n" " +[no]tls-keyfile=file (Load client TLS " "private key from file)\n" " +[no]trace (Trace delegation down " - "from root " - "[+dnssec])\n" + "from root [implies\n" + " +dnssec])\n" " +tries=### (Set number of UDP " "attempts) [3]\n" " +[no]ttlid (Control display of ttls "