Commit 28438393fd for bind
commit 28438393fde21788a37915ef68cc5fadcb27540b
Author: Evan Hunt <each@isc.org>
Date: Wed Sep 17 03:13:52 2025 -0700
Add support for DELEG (DE) flag in messages
The DE bit is now correctly interpreted when encountered on the wire.
dig can send the bit by specifing "dig +deflag" or "dig +de".
In querylog output, the DE flag is indicated with the letter "G".
When the DE flag is sent in a query, it is echoed back in the
response to the client, similar to DO.
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
index e8d83c5288..2e42bfd2ce 100644
--- a/bin/dig/dig.c
+++ b/bin/dig/dig.c
@@ -206,6 +206,8 @@ help(void) {
" +[no]crypto (Control display of "
"cryptographic\n"
" fields in records)\n"
+ " +[no]deflag (Request DELEG if "
+ "available)\n"
" +[no]defname (Use search list "
"(+[no]search))\n"
" +[no]dns64prefix (Get the DNS64 prefixes "
@@ -1684,12 +1686,13 @@ plus_option(char *option, bool is_batchfile, bool *need_clone,
break;
case 'd':
switch (cmd[1]) {
- case 'e': /* defname */
- FULLCHECK("defname");
- fprintf(stderr, ";; +[no]defname option is "
- "deprecated; use +[no]search\n");
- if (!lookup->trace) {
- usesearch = state;
+ case 'e': /* deflag */
+ switch (cmd[2]) {
+ case 'f':
+ case '\0': /* +de is a synonym for +deflag */
+ FULLCHECK("deflag");
+ lookup->deflag = state;
+ break;
}
break;
case 'n':
diff --git a/bin/dig/dig.rst b/bin/dig/dig.rst
index 636a03d198..c57d47ab3c 100644
--- a/bin/dig/dig.rst
+++ b/bin/dig/dig.rst
@@ -337,6 +337,12 @@ abbreviation is unambiguous; for example, :option:`+cd` is equivalent to
they are replaced by the string ``[omitted]`` or, in the DNSKEY case, the
key ID is displayed as the replacement, e.g. ``[ key id = value ]``.
+.. option:: +deflag, +nodeflag
+
+ This option requests that DELEG records be sent if available, by setting
+ the DELEG OK (DE) bit in the OPT record in the additional section of the
+ query.
+
.. option:: +defname, +nodefname
This option, which is deprecated, is treated as a synonym for
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 2f73bdf436..57575a2ece 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -760,6 +760,7 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
looknew->adflag = lookold->adflag;
looknew->cdflag = lookold->cdflag;
looknew->coflag = lookold->coflag;
+ looknew->deflag = lookold->deflag;
looknew->raflag = lookold->raflag;
looknew->tcflag = lookold->tcflag;
looknew->print_unknown_format = lookold->print_unknown_format;
@@ -2380,13 +2381,17 @@ setup_lookup(dig_lookup_t *lookup) {
/* Set the EDNS flags */
unsigned int flags = lookup->ednsflags;
- flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO);
+ flags &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO |
+ DNS_MESSAGEEXTFLAG_DE);
if (lookup->dnssec) {
flags |= DNS_MESSAGEEXTFLAG_DO;
}
if (lookup->coflag) {
flags |= DNS_MESSAGEEXTFLAG_CO;
}
+ if (lookup->deflag) {
+ flags |= DNS_MESSAGEEXTFLAG_DE;
+ }
/* Set the EDNS UDP size */
if (lookup->udpsize < 0) {
diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h
index 196f83284e..6213b236f9 100644
--- a/bin/dig/dighost.h
+++ b/bin/dig/dighost.h
@@ -104,9 +104,9 @@ struct dig_lookup {
unsigned int magic;
isc_refcount_t references;
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 */
+ comments, dns64prefix, deflag, dnssec, doing_xfr, done_as_is,
+ ednsneg, expandaaaa, svcparamkeycompat, expire, fuzzing,
+ header_only, identify, /*%< Append "on server <foo>" message */
identify_previous_line, /*% Prepend a "Nameserver <foo>:"
message, with newline and tab */
idnin, idnout, ignore, multiline, need_search, new_search,
diff --git a/bin/tests/system/digdelv/tests_dig.py b/bin/tests/system/digdelv/tests_dig.py
index b03b432431..7f4f8e105d 100644
--- a/bin/tests/system/digdelv/tests_dig.py
+++ b/bin/tests/system/digdelv/tests_dig.py
@@ -1270,3 +1270,13 @@ def test_yaml_character_values(dig, ns3):
answer = response["ANSWER_SECTION"][0]
strings = " ".join(quoted(i) for i in range(256))
assert answer == f"all.yaml.example. 300 IN TXT {strings}"
+
+
+def test_deflag(dig, ns3):
+ """
+ Check that the DE flag is sent when specified.
+ """
+ result = dig(f"@{ns3.ip} +de a.example +qr")
+ assert "flags: de" in result.out
+ result = dig(f"@{ns3.ip} a.example +qr")
+ assert "flags: de" not in result.out
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
index 4a26d308ea..3a003c5a9a 100644
--- a/lib/dns/include/dns/message.h
+++ b/lib/dns/include/dns/message.h
@@ -103,6 +103,7 @@ enum {
enum {
DNS_MESSAGEEXTFLAG_DO = 0x8000U, /* DNSSEC OK */
DNS_MESSAGEEXTFLAG_CO = 0x4000U, /* Compact denial of existence OK */
+ DNS_MESSAGEEXTFLAG_DE = 0x2000U, /* DELEG OK */
};
/*%< EDNS0 extended OPT codes */
@@ -140,7 +141,8 @@ enum {
#define DNS_EDNS_MAX_OPTIONS DNS_OPT_COUNT + DNS_EDE_MAX_ERRORS
#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD | DNS_MESSAGEFLAG_CD)
-#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
+#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE \
+ (DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_DE)
#define DNS_MESSAGE_HEADERLEN 12 /*%< 6 uint16_t's */
diff --git a/lib/dns/message.c b/lib/dns/message.c
index 0e5416c5ca..f61d85d88b 100644
--- a/lib/dns/message.c
+++ b/lib/dns/message.c
@@ -3668,10 +3668,14 @@ dns_message_pseudosectiontoyaml(dns_message_t *msg, dns_pseudosection_t section,
if ((ps->ttl & DNS_MESSAGEEXTFLAG_CO) != 0) {
ADD_STRING(target, " co");
}
+ if ((ps->ttl & DNS_MESSAGEEXTFLAG_DE) != 0) {
+ ADD_STRING(target, " de");
+ }
ADD_STRING(target, "\n");
mbz = ps->ttl & 0xffff;
/* Exclude Known Flags. */
- mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO);
+ mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO |
+ DNS_MESSAGEEXTFLAG_DE);
if (mbz != 0) {
INDENT(style);
ADD_STRING(target, "MBZ: ");
@@ -4100,9 +4104,13 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section,
if ((ps->ttl & DNS_MESSAGEEXTFLAG_CO) != 0) {
ADD_STRING(target, " co");
}
+ if ((ps->ttl & DNS_MESSAGEEXTFLAG_DE) != 0) {
+ ADD_STRING(target, " de");
+ }
mbz = ps->ttl & 0xffff;
/* Exclude Known Flags. */
- mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO);
+ mbz &= ~(DNS_MESSAGEEXTFLAG_DO | DNS_MESSAGEEXTFLAG_CO |
+ DNS_MESSAGEEXTFLAG_DE);
if (mbz != 0) {
ADD_STRING(target, "; MBZ: ");
snprintf(buf, sizeof(buf), "0x%.4x", mbz);
diff --git a/lib/ns/query.c b/lib/ns/query.c
index 50a04e2160..649bfb0ae8 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -563,6 +563,9 @@ ns_client_log_flags(ns_client_t *client, unsigned int flags,
} else if (client->inner.wantcookie) {
isc_buffer_putuint8(&b, 'K');
}
+ if ((extflags & DNS_MESSAGEEXTFLAG_DE) != 0) {
+ isc_buffer_putuint8(&b, 'G');
+ }
isc_buffer_putuint8(&b, 0);
}