new: usr: Add support to set and display the CO flag

Add support to display the CO (Compact denial of existence Ok flag) when displaying messages.

Add support to set the CO flag when making queries in dig (+coflag).

Closes #5319

Merge branch '5319-add-support-to-set-and-display-the-co-flag' into 'main'

See merge request isc-projects/bind9!10482
This commit is contained in:
Mark Andrews 2025-06-13 09:50:06 +00:00
commit 419ad06023
7 changed files with 94 additions and 27 deletions

View file

@ -193,6 +193,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"
@ -210,7 +213,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 "
@ -226,12 +230,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
@ -258,15 +264,23 @@ help(void) {
" +padding=### (Set padding block size "
"[0])\n"
" "
"+[no]proxy[=src_addr[#src_port]-dst_addr[#dst_port]] "
"(Add PROXYv2 headers to the queries. If addresses are omitted, "
"LOCAL PROXYv2 headers are added)\n"
"+[no]proxy[=src_addr[#src_port]-dst_addr[#dst_port]]\n"
" (Add PROXYv2 headers to "
"the queries. If\n"
" addresses are omitted, "
"LOCAL PROXYv2\n"
" headers are added)\n"
" "
"+[no]proxy-plain[=src_addr[#src_port]-dst_addr[#dst_port]] "
"(The same as '+[no]proxy', but send PROXYv2 headers ahead of "
"any encryption if an encrypted transport is used)\n"
"+[no]proxy-plain[=src_addr[#src_port]-dst_addr[#dst_port]]\n"
" (The same as'+[no]proxy', "
"but send PROXYv2\n"
" headers ahead of any "
"encryption if an\n"
" encrypted transport is "
"used)\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 "
@ -299,22 +313,29 @@ help(void) {
" +subnet=addr (Set edns-client-subnet "
"option)\n"
" +[no]svcparamkeycompat (Display backward-"
"compatible SvcParamKey names (keyN) for non-initial entries)\n"
"compatible\n"
" SvcParamKey names (keyN) "
"for non-initial\n"
" entries)\n"
" +[no]tcflag (Set TC flag in query "
"(+[no]tcflag))\n"
" +[no]tcp (TCP mode (+[no]vc))\n"
" +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 [implies +dnssec])\n"
"from root [implies\n"
" +dnssec])\n"
" +tries=### (Set number of UDP "
"attempts) [3]\n"
" +[no]ttlid (Control display of ttls "
@ -1618,6 +1639,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;

View file

@ -302,6 +302,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
@ -362,7 +369,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

View file

@ -760,6 +760,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;
@ -2576,10 +2577,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);
}

View file

@ -102,9 +102,9 @@ 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,
svcparamkeycompat, expire, fuzzing, header_only,
bool aaonly, adflag, badcookie, besteffort, cdflag, cleared, coflag,
comments, dns64prefix, dnssec, doing_xfr, done_as_is, ednsneg,
expandaaaa, svcparamkeycompat, expire, fuzzing, header_only,
identify, /*%< Append an "on server <foo>" message */
identify_previous_line, /*% Prepend a "Nameserver <foo>:"
message, with newline and tab */

View file

@ -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;" <dig.out.test$n >/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 <yamlget.out.test$n
[ "$value" = "co" ] || ret=1
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
fi
n=$((n + 1))
echo_i "checking dig +raflag works ($n)"
ret=0

View file

@ -99,7 +99,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 */

View file

@ -3685,9 +3685,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: ");
@ -4124,8 +4128,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);