Download raw body.
dig(1): Implement zoneversion edns option (RFC 9660)
I'm running nsd 4.11.0 on b.ns.sha256.net for now, which implements RFC
9660:
$ obj/dig +norec +zoneversion @b.ns.sha256.net sha256.net. AAAA
; <<>> dig 9.10.8-P1 <<>> +norec +zoneversion @b.ns.sha256.net sha256.net. AAAA
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8188
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; ZONEVERSION: 02 00 78 a5 a8 e9 ("SOA-SERIAL: 2024122601 (sha256.net.)")
;; QUESTION SECTION:
;sha256.net. IN AAAA
;; ANSWER SECTION:
sha256.net. 60 IN AAAA 2a01:4f8:191:3241:662e:7b7d:deb5:93a3
;; Query time: 23 msec
;; SERVER: 2a05:f480:1000:22:3829:171:d537:dabe#53(2a05:f480:1000:22:3829:171:d537:dabe)
;; WHEN: Thu Dec 26 09:56:41 CET 2024
;; MSG SIZE rcvd: 77
I've also tested it against nsd serving the root zone according to RFC
8806:
$ obj/dig +norec +zoneversion +nsid @$(hostname) sha256.net. AAAA
; <<>> dig 9.10.8-P1 <<>> +norec +zoneversion +nsid @XXX sha256.net. AAAA
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62775
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; ZONEVERSION: 00 00 78 a5 a8 e8 ("SOA-SERIAL: 2024122600 (.)")
;; QUESTION SECTION:
;sha256.net. IN AAAA
;; AUTHORITY SECTION:
net. 172800 IN NS a.gtld-servers.net.
net. 172800 IN NS b.gtld-servers.net.
[...]
OK?
diff --git dig.1 dig.1
index 1031c377c32..063be1114d7 100644
--- dig.1
+++ dig.1
@@ -810,6 +810,12 @@ This alternate syntax to
.Cm tcp
is provided for backwards compatibility.
The "vc" stands for "virtual circuit".
+.It Xo
+.Cm + Ns
+.Op Cm no Ns
+.Cm zoneversion
+.Xc
+Include an EDNS zone version request when sending a query (off by default).
.El
.Sh MULTIPLE QUERIES
The BIND 9 implementation of
diff --git dig.c dig.c
index a23bcbeb4d9..14a854bbf4d 100644
--- dig.c
+++ dig.c
@@ -498,7 +498,7 @@ repopulate_buffer:
if (query->lookup->comments && headers && !short_form) {
result = dns_message_pseudosectiontotext(msg,
DNS_PSEUDOSECTION_OPT,
- style, flags, buf);
+ style, flags, query->lookup->textname, buf);
if (result == ISC_R_NOSPACE) {
buftoosmall:
len += OUTPUTBUF;
@@ -563,7 +563,9 @@ buftoosmall:
result = dns_message_pseudosectiontotext(
msg,
DNS_PSEUDOSECTION_TSIG,
- style, flags, buf);
+ style, flags,
+ query->lookup->textname,
+ buf);
if (result == ISC_R_NOSPACE)
goto buftoosmall;
check_result(result,
@@ -571,7 +573,9 @@ buftoosmall:
result = dns_message_pseudosectiontotext(
msg,
DNS_PSEUDOSECTION_SIG0,
- style, flags, buf);
+ style, flags,
+ query->lookup->textname,
+ buf);
if (result == ISC_R_NOSPACE)
goto buftoosmall;
check_result(result,
@@ -1250,6 +1254,12 @@ plus_option(const char *option, int is_batchfile,
lookup->tcp_mode_set = 1;
}
break;
+ case 'z':
+ FULLCHECK("zoneversion");
+ if (!state)
+ break;
+ save_opt(lookup, "zoneversion", NULL);
+ break;
default:
invalid_option:
need_value:
diff --git dighost.c dighost.c
index 57a8e4a2deb..b8dda7a9f13 100644
--- dighost.c
+++ dighost.c
@@ -1274,6 +1274,7 @@ dig_ednsoptname_t optnames[] = {
{ 12, "PAD" }, /* shorthand */
{ 13, "CHAIN" }, /* RFC 7901 */
{ 14, "KEY-TAG" }, /* RFC 8145 */
+ { 19, "ZONEVERSION" }, /* RFC 9660 */
{ 26946, "DEVICEID" }, /* Brian Hartvigsen */
};
diff --git lib/dns/include/dns/message.h lib/dns/include/dns/message.h
index 6cd42be4176..6d0f2a50d32 100644
--- lib/dns/include/dns/message.h
+++ lib/dns/include/dns/message.h
@@ -105,6 +105,7 @@
#define DNS_OPT_PAD 12 /*%< PAD opt code */
#define DNS_OPT_KEY_TAG 14 /*%< Key tag opt code */
#define DNS_OPT_EDE 15 /* RFC 8914 */
+#define DNS_OPT_ZONEVERSION 19 /* RFC 9660 */
/*%< The number of EDNS options we know about. */
#define DNS_EDNSOPTIONS 4
@@ -288,6 +289,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
dns_pseudosection_t section,
const dns_master_style_t *style,
dns_messagetextflag_t flags,
+ const char *textname,
isc_buffer_t *target);
/*%<
* Convert section 'section' or 'pseudosection' of message 'msg' to
diff --git lib/dns/message.c lib/dns/message.c
index 49ea973ffa3..8ecedacf4f1 100644
--- lib/dns/message.c
+++ lib/dns/message.c
@@ -2484,11 +2484,42 @@ ede_info_code2str(uint16_t info_code)
}
}
+static const char *
+zoneversion_zone(const char *zone, int labelcount)
+{
+ size_t pos;
+
+ if (zone == NULL || labelcount == 0)
+ return ".";
+
+ pos = strlen(zone);
+ if (pos == 0)
+ return ".";
+
+ pos--; /* go to last char in string */
+ if (zone[pos] == '.')
+ pos--; /* the labelcount does not count the empty root label */
+
+ for (; pos > 0; pos--) {
+ if (zone[pos] == '.') {
+ labelcount--;
+
+ if (labelcount == 0) {
+ pos++;
+ break;
+ }
+ }
+ }
+
+ return (zone + pos);
+}
+
isc_result_t
dns_message_pseudosectiontotext(dns_message_t *msg,
dns_pseudosection_t section,
const dns_master_style_t *style,
dns_messagetextflag_t flags,
+ const char *textname,
isc_buffer_t *target)
{
dns_rdataset_t *ps = NULL;
@@ -2621,6 +2652,46 @@ dns_message_pseudosectiontotext(dns_message_t *msg,
ede_info_code2str(info_code));
ADD_STRING(target, ")");
}
+ } else if (optcode == DNS_OPT_ZONEVERSION) {
+ int i;
+
+ ADD_STRING(target, "; ZONEVERSION: ");
+ optdata = isc_buffer_current(&optbuf);
+ for (i = 0; i < optlen; i++) {
+ snprintf(buf, sizeof(buf), "%02x ",
+ optdata[i]);
+ ADD_STRING(target, buf);
+ }
+
+ if (optlen >= 2) {
+ uint8_t labelcount, type;
+ const char *zone;
+
+ labelcount =
+ isc_buffer_getuint8(&optbuf);
+ optlen -= 1;
+ type = isc_buffer_getuint8(&optbuf);
+ optlen -= 1;
+ zone = zoneversion_zone(textname,
+ labelcount);
+
+ if (type == 0 && optlen == 4) {
+ uint32_t serial;
+
+ serial = isc_buffer_getuint32(
+ &optbuf);
+ optlen -= 4;
+ ADD_STRING(target,
+ "(\"SOA-SERIAL: ");
+ snprintf(buf, sizeof(buf), "%u",
+ serial);
+ ADD_STRING(target, buf);
+ ADD_STRING(target, " (");
+ ADD_STRING(target, zone);
+ ADD_STRING(target, ")");
+ ADD_STRING(target, "\")");
+ }
+ }
} else {
ADD_STRING(target, "; OPT=");
snprintf(buf, sizeof(buf), "%u", optcode);
--
In my defence, I have been left unsupervised.
dig(1): Implement zoneversion edns option (RFC 9660)