]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add option request-zoneversion
authorMark Andrews <marka@isc.org>
Fri, 14 Jun 2024 01:23:53 +0000 (11:23 +1000)
committerMark Andrews <marka@isc.org>
Mon, 24 Mar 2025 22:16:09 +0000 (22:16 +0000)
This can be set at the option, view and server levels and causes
named to add an EDNS ZONEVERSION option to requests.  Replies are
logged to the 'zoneversion' category.

15 files changed:
bin/named/config.c
bin/named/server.c
bin/tests/system/checkconf/good-server-christmas-tree.conf.in
doc/arm/logging-categories.inc.rst
doc/arm/reference.rst
doc/misc/options
lib/dns/include/dns/peer.h
lib/dns/include/dns/resolver.h
lib/dns/include/dns/view.h
lib/dns/peer.c
lib/dns/resolver.c
lib/isc/include/isc/log.h
lib/isc/log.c
lib/isccfg/check.c
lib/isccfg/namedconf.c

index 3ac41a80b2ad1936a0340f5e00f0936702d88923..d398a92990461da666aaeafcc42f95a3db4d1420 100644 (file)
@@ -99,6 +99,7 @@ options {\n\
        recursing-file \"named.recursing\";\n\
        recursive-clients 1000;\n\
        request-nsid false;\n\
+       request-zoneversion false;\n\
        resolver-query-timeout 10;\n\
 #      responselog <boolean>;\n\
        rrset-order { order random; };\n\
index bffe2333f3d7f424399b45beb0664eb2ae44c1f4..d271c153cf2a111a9a65fd1e6ec6dd20cf604bce 100644 (file)
@@ -1391,6 +1391,13 @@ configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
                CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
        }
 
+       obj = NULL;
+       (void)cfg_map_get(cpeer, "request-zoneversion", &obj);
+       if (obj != NULL) {
+               CHECK(dns_peer_setrequestzoneversion(peer,
+                                                    cfg_obj_asboolean(obj)));
+       }
+
        obj = NULL;
        (void)cfg_map_get(cpeer, "send-cookie", &obj);
        if (obj != NULL) {
@@ -5132,6 +5139,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
        INSIST(result == ISC_R_SUCCESS);
        view->requestnsid = cfg_obj_asboolean(obj);
 
+       obj = NULL;
+       result = named_config_get(maps, "request-zoneversion", &obj);
+       INSIST(result == ISC_R_SUCCESS);
+       view->requestzoneversion = cfg_obj_asboolean(obj);
+
        obj = NULL;
        result = named_config_get(maps, "send-cookie", &obj);
        INSIST(result == ISC_R_SUCCESS);
index 2eceee6baf6e6da6b583a1ef7f69145fb8b70eee..6353e191cd016d7482ed1113c148998e0b083762 100644 (file)
@@ -31,6 +31,7 @@ server 0.0.0.0 {
        request-ixfr no;
        request-ixfr-max-diffs 0;
        request-nsid no;
+       request-zoneversion no;
        require-cookie no;
        send-cookie no;
        tcp-keepalive no;
@@ -55,6 +56,7 @@ server :: {
        request-ixfr no;
        request-ixfr-max-diffs 0;
        request-nsid no;
+       request-zoneversion no;
        require-cookie no;
        send-cookie no;
        tcp-keepalive no;
index 88d4f8b180ef9c8525ad1019faf89aa615faaa71..6fb0799df86f6de2b16e23e1b00b86747506e056 100644 (file)
 
 ``zoneload``
     Loading of zones and creation of automatic empty zones.
+
+``zoneversion``
+    ZONEVERSION options received from upstream servers.
+
index 612fda7ad48f7098632841b8c21a0ef63944d168..67cde91d2959baff12b9b565f33a883221916d47 100644 (file)
@@ -2188,6 +2188,18 @@ Boolean Options
    option in its response, then its contents are logged in the ``nsid``
    category at level ``info``. The default is ``no``.
 
+.. namedconf:statement:: request-zoneversion
+   :tags: query
+   :short: Controls whether an empty EDNS(0) ZONEVERSION option is sent with all queries to authoritative name servers during iterative resolution.
+
+   If ``yes``, then an empty EDNS(0) ZONEVERSION option is sent
+   with all queries to authoritative name servers during iterative
+   resolution. If the authoritative server returns an ZONEVERSION
+   option in its response, then its contents are logged in the
+   ``zoneversion`` category at level ``info``.  If the NSID has
+   also been requested and it is returned then that is appended to
+   the log message.  The default is ``no``.
+
 .. namedconf:statement:: require-cookie
    :tags: query
    :short: Controls whether responses without a server cookie are accepted.
@@ -5606,6 +5618,7 @@ and :namedconf:ref:`options` blocks:
    - :namedconf:ref:`request-expire`
    - :namedconf:ref:`request-ixfr`
    - :namedconf:ref:`request-nsid`
+   - :namedconf:ref:`request-zoneversion`
    - :namedconf:ref:`require-cookie`
    - :namedconf:ref:`send-cookie`
    - :namedconf:ref:`transfer-format`
index 3fa81f4baedb7771797d49f129db4ed0b850aef4..e233c042dc9d05334b161e7b3468c1a5a70f50de 100644 (file)
@@ -254,6 +254,7 @@ options {
        request-ixfr <boolean>;
        request-ixfr-max-diffs <integer>;
        request-nsid <boolean>;
+       request-zoneversion <boolean>;
        require-server-cookie <boolean>;
        resolver-query-timeout <integer>;
        resolver-use-dns64 <boolean>;
@@ -343,6 +344,7 @@ server <netprefix> {
        request-ixfr <boolean>;
        request-ixfr-max-diffs <integer>;
        request-nsid <boolean>;
+       request-zoneversion <boolean>;
        require-cookie <boolean>;
        send-cookie <boolean>;
        tcp-keepalive <boolean>;
@@ -534,6 +536,7 @@ view <string> [ <class> ] {
        request-ixfr <boolean>;
        request-ixfr-max-diffs <integer>;
        request-nsid <boolean>;
+       request-zoneversion <boolean>;
        require-server-cookie <boolean>;
        resolver-query-timeout <integer>;
        resolver-use-dns64 <boolean>;
@@ -561,6 +564,7 @@ view <string> [ <class> ] {
                request-ixfr <boolean>;
                request-ixfr-max-diffs <integer>;
                request-nsid <boolean>;
+               request-zoneversion <boolean>;
                require-cookie <boolean>;
                send-cookie <boolean>;
                tcp-keepalive <boolean>;
index e2bcc667257c321005619558b109c96a4406fed9..213bdf0cc6bc3432ebf3be6595677affd0df5d43 100644 (file)
@@ -115,6 +115,12 @@ dns_peer_setrequestnsid(dns_peer_t *peer, bool newval);
 isc_result_t
 dns_peer_getrequestnsid(dns_peer_t *peer, bool *retval);
 
+isc_result_t
+dns_peer_setrequestzoneversion(dns_peer_t *peer, bool newval);
+
+isc_result_t
+dns_peer_getrequestzoneversion(dns_peer_t *peer, bool *retval);
+
 isc_result_t
 dns_peer_setsendcookie(dns_peer_t *peer, bool newval);
 
index 7bedc07ee2938239301200b468e949ffcd0c92e7..0b00df679cebe280f245103a16184ab717d8b538 100644 (file)
@@ -105,31 +105,32 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t;
  * Options that modify how a 'fetch' is done.
  */
 enum {
-       DNS_FETCHOPT_TCP = 1 << 0,             /*%< Use TCP. */
-       DNS_FETCHOPT_UNSHARED = 1 << 1,        /*%< See below. */
-       DNS_FETCHOPT_RECURSIVE = 1 << 2,       /*%< Set RD? */
-       DNS_FETCHOPT_NOEDNS0 = 1 << 3,         /*%< Do not use EDNS. */
-       DNS_FETCHOPT_FORWARDONLY = 1 << 4,     /*%< Only use forwarders. */
-       DNS_FETCHOPT_NOVALIDATE = 1 << 5,      /*%< Disable validation. */
-       DNS_FETCHOPT_WANTNSID = 1 << 6,        /*%< Request NSID */
-       DNS_FETCHOPT_PREFETCH = 1 << 7,        /*%< Do prefetch */
-       DNS_FETCHOPT_NOCDFLAG = 1 << 8,        /*%< Don't set CD flag. */
-       DNS_FETCHOPT_NONTA = 1 << 9,           /*%< Ignore NTA table. */
-       DNS_FETCHOPT_NOCACHED = 1 << 10,       /*%< Force cache update. */
-       DNS_FETCHOPT_QMINIMIZE = 1 << 11,      /*%< Use qname minimization. */
-       DNS_FETCHOPT_NOFOLLOW = 1 << 12,       /*%< Don't retrieve the NS RRset
-                                               * from the child zone when a
-                                               * delegation is returned in
-                                               * response to a NS query. */
-       DNS_FETCHOPT_QMIN_STRICT = 1 << 13,    /*%< Do not work around servers
-                                               * that return errors on
-                                               * non-empty terminals. */
-       DNS_FETCHOPT_QMIN_SKIP_IP6A = 1 << 14, /*%< Skip some labels when
-                                               * doing qname minimization
-                                               * on ip6.arpa. */
-       DNS_FETCHOPT_NOFORWARD = 1 << 15,      /*%< Do not use forwarders if
-                                               * possible. */
-       DNS_FETCHOPT_QMINFETCH = 1 << 16,      /*%< Qmin fetch */
+       DNS_FETCHOPT_TCP = 1 << 0,              /*%< Use TCP. */
+       DNS_FETCHOPT_UNSHARED = 1 << 1,         /*%< See below. */
+       DNS_FETCHOPT_RECURSIVE = 1 << 2,        /*%< Set RD? */
+       DNS_FETCHOPT_NOEDNS0 = 1 << 3,          /*%< Do not use EDNS. */
+       DNS_FETCHOPT_FORWARDONLY = 1 << 4,      /*%< Only use forwarders. */
+       DNS_FETCHOPT_NOVALIDATE = 1 << 5,       /*%< Disable validation. */
+       DNS_FETCHOPT_WANTNSID = 1 << 6,         /*%< Request NSID */
+       DNS_FETCHOPT_PREFETCH = 1 << 7,         /*%< Do prefetch */
+       DNS_FETCHOPT_NOCDFLAG = 1 << 8,         /*%< Don't set CD flag. */
+       DNS_FETCHOPT_NONTA = 1 << 9,            /*%< Ignore NTA table. */
+       DNS_FETCHOPT_NOCACHED = 1 << 10,        /*%< Force cache update. */
+       DNS_FETCHOPT_QMINIMIZE = 1 << 11,       /*%< Use qname minimization. */
+       DNS_FETCHOPT_NOFOLLOW = 1 << 12,        /*%< Don't retrieve the NS RRset
+                                                * from the child zone when a
+                                                * delegation is returned in
+                                                * response to a NS query. */
+       DNS_FETCHOPT_QMIN_STRICT = 1 << 13,     /*%< Do not work around servers
+                                                * that return errors on
+                                                * non-empty terminals. */
+       DNS_FETCHOPT_QMIN_SKIP_IP6A = 1 << 14,  /*%< Skip some labels when
+                                                * doing qname minimization
+                                                * on ip6.arpa. */
+       DNS_FETCHOPT_NOFORWARD = 1 << 15,       /*%< Do not use forwarders if
+                                                * possible. */
+       DNS_FETCHOPT_QMINFETCH = 1 << 16,       /*%< Qmin fetch */
+       DNS_FETCHOPT_WANTZONEVERSION = 1 << 17, /*%< Request ZONEVERSION */
 
        /*% EDNS version bits: */
        DNS_FETCHOPT_EDNSVERSIONSET = 1 << 23,
index 266ba49d6c0ced6bfe72e57a70232a1327355391..4cd2f66ad1fca7a782ff7a82a05bb396683125df 100644 (file)
@@ -145,6 +145,7 @@ struct dns_view {
        dns_rrl_t            *rrl;
        bool                  provideixfr;
        bool                  requestnsid;
+       bool                  requestzoneversion;
        bool                  sendcookie;
        dns_ttl_t             maxcachettl;
        dns_ttl_t             maxncachettl;
index f633ab285f73219a6319a7b4c5786b4d647a2ab9..6f011d26deeac65b1c3c6d0e7f23ac8c8bb6eb4a 100644 (file)
@@ -57,6 +57,7 @@ struct dns_peer {
        bool request_ixfr;
        bool support_edns;
        bool request_nsid;
+       bool request_zoneversion;
        bool send_cookie;
        bool require_cookie;
        bool request_expire;
@@ -98,7 +99,8 @@ enum {
        SERVER_PADDING_BIT,
        REQUEST_TCP_KEEPALIVE_BIT,
        REQUIRE_COOKIE_BIT,
-       DNS_PEER_FLAGS_COUNT
+       DNS_PEER_FLAGS_COUNT,
+       REQUEST_ZONEVERSION
 };
 
 STATIC_ASSERT(DNS_PEER_FLAGS_COUNT <= CHAR_BIT * sizeof(uint32_t),
@@ -382,6 +384,8 @@ ACCESS_OPTION(requestixfr, REQUEST_IXFR_BIT, bool, request_ixfr)
 ACCESS_OPTION(requestixfrmaxdiffs, REQUEST_IXFRMAXDIFFS_BIT, uint32_t,
              request_ixfr_maxdiffs)
 ACCESS_OPTION(requestnsid, REQUEST_NSID_BIT, bool, request_nsid)
+ACCESS_OPTION(requestzoneversion, REQUEST_ZONEVERSION, bool,
+             request_zoneversion)
 ACCESS_OPTION(requirecookie, REQUIRE_COOKIE_BIT, bool, require_cookie)
 ACCESS_OPTION(sendcookie, SEND_COOKIE_BIT, bool, send_cookie)
 ACCESS_OPTION(supportedns, SUPPORT_EDNS_BIT, bool, support_edns)
index 410141f052657f9d830a71f9d4d41b50e0590aeb..aa3050b8a65227cea46d79e1c7293c73bffec7f3 100644 (file)
@@ -24,6 +24,7 @@
 #include <isc/counter.h>
 #include <isc/hash.h>
 #include <isc/hashmap.h>
+#include <isc/hex.h>
 #include <isc/log.h>
 #include <isc/loop.h>
 #include <isc/mutex.h>
@@ -2504,6 +2505,7 @@ resquery_send(resquery_t *query) {
                        unsigned int flags = query->addrinfo->flags;
                        bool reqnsid = res->view->requestnsid;
                        bool sendcookie = res->view->sendcookie;
+                       bool reqzoneversion = res->view->requestzoneversion;
                        bool tcpkeepalive = false;
                        unsigned char cookie[COOKIE_BUFFER_SIZE];
                        uint16_t padding = 0;
@@ -2546,8 +2548,6 @@ resquery_send(resquery_t *query) {
                         */
                        if (peer != NULL) {
                                uint8_t ednsversion;
-                               (void)dns_peer_getrequestnsid(peer, &reqnsid);
-                               (void)dns_peer_getsendcookie(peer, &sendcookie);
                                result = dns_peer_getednsversion(peer,
                                                                 &ednsversion);
                                if (result == ISC_R_SUCCESS &&
@@ -2555,6 +2555,10 @@ resquery_send(resquery_t *query) {
                                {
                                        version = ednsversion;
                                }
+                               (void)dns_peer_getrequestnsid(peer, &reqnsid);
+                               (void)dns_peer_getrequestzoneversion(
+                                       peer, &reqzoneversion);
+                               (void)dns_peer_getsendcookie(peer, &sendcookie);
                        }
                        if (NOCOOKIE(query->addrinfo)) {
                                sendcookie = false;
@@ -2566,6 +2570,13 @@ resquery_send(resquery_t *query) {
                                ednsopts[ednsopt].value = NULL;
                                ednsopt++;
                        }
+                       if (reqzoneversion) {
+                               INSIST(ednsopt < DNS_EDNSOPTIONS);
+                               ednsopts[ednsopt].code = DNS_OPT_ZONEVERSION;
+                               ednsopts[ednsopt].length = 0;
+                               ednsopts[ednsopt].value = NULL;
+                               ednsopt++;
+                       }
                        if (sendcookie) {
                                INSIST(ednsopt < DNS_EDNSOPTIONS);
                                ednsopts[ednsopt].code = DNS_OPT_COOKIE;
@@ -2620,8 +2631,14 @@ resquery_send(resquery_t *query) {
                        query->ednsversion = version;
                        result = fctx_addopt(fctx->qmessage, version, udpsize,
                                             ednsopts, ednsopt);
-                       if (reqnsid && result == ISC_R_SUCCESS) {
-                               query->options |= DNS_FETCHOPT_WANTNSID;
+                       if (result == ISC_R_SUCCESS) {
+                               if (reqnsid) {
+                                       query->options |= DNS_FETCHOPT_WANTNSID;
+                               }
+                               if (reqzoneversion) {
+                                       query->options |=
+                                               DNS_FETCHOPT_WANTZONEVERSION;
+                               }
                        } else if (result != ISC_R_SUCCESS) {
                                /*
                                 * We couldn't add the OPT, but we'll
@@ -7387,17 +7404,38 @@ checknames(dns_message_t *message) {
        checknamessection(message, DNS_SECTION_ADDITIONAL);
 }
 
+static void
+make_hex(unsigned char *src, size_t srclen, char *buf, size_t buflen) {
+       isc_buffer_t b;
+       isc_region_t r;
+       isc_result_t result;
+
+       r.base = src;
+       r.length = srclen;
+       isc_buffer_init(&b, buf, buflen);
+       result = isc_hex_totext(&r, 0, "", &b);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+       isc_buffer_putuint8(&b, '\0');
+}
+
+static void
+make_printable(unsigned char *src, size_t srclen, char *buf, size_t buflen) {
+       INSIST(buflen > srclen);
+       while (srclen-- > 0) {
+               unsigned char c = *src++;
+               *buf++ = isprint(c) ? c : '.';
+       }
+       *buf = '\0';
+}
+
 /*
  * Log server NSID at log level 'level'
  */
 static void
 log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, int level,
         isc_mem_t *mctx) {
-       static const char hex[17] = "0123456789abcdef";
-       char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+       char addrbuf[ISC_SOCKADDR_FORMATSIZE], *buf = NULL, *pbuf = NULL;
        size_t buflen;
-       unsigned char *p, *nsid;
-       unsigned char *buf = NULL, *pbuf = NULL;
 
        REQUIRE(nsid_len <= UINT16_MAX);
 
@@ -7407,20 +7445,10 @@ log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, int level,
        pbuf = isc_mem_get(mctx, nsid_len + 1);
 
        /* Convert to hex */
-       p = buf;
-       nsid = isc_buffer_current(opt);
-       for (size_t i = 0; i < nsid_len; i++) {
-               *p++ = hex[(nsid[i] >> 4) & 0xf];
-               *p++ = hex[nsid[i] & 0xf];
-       }
-       *p = '\0';
+       make_hex(isc_buffer_current(opt), nsid_len, buf, buflen);
 
        /* Make printable version */
-       p = pbuf;
-       for (size_t i = 0; i < nsid_len; i++) {
-               *p++ = isprint(nsid[i]) ? nsid[i] : '.';
-       }
-       *p = '\0';
+       make_printable(isc_buffer_current(opt), nsid_len, pbuf, nsid_len + 1);
 
        isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
                            sizeof(addrbuf));
@@ -7431,6 +7459,108 @@ log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, int level,
        isc_mem_put(mctx, buf, buflen);
 }
 
+static void
+log_zoneversion(unsigned char *version, size_t version_len, unsigned char *nsid,
+               size_t nsid_len, resquery_t *query, int level,
+               isc_mem_t *mctx) {
+       char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+       char namebuf[DNS_NAME_FORMATSIZE];
+       size_t nsid_buflen = 0;
+       char *nsid_buf = NULL;
+       char *nsid_pbuf = NULL;
+       const char *nsid_hex = "";
+       const char *nsid_print = "";
+       const char *sep_1 = "";
+       const char *sep_2 = "";
+       const char *sep_3 = "";
+       dns_name_t suffix = DNS_NAME_INITEMPTY;
+       unsigned int labels;
+
+       REQUIRE(version_len <= UINT16_MAX);
+
+       /*
+        * Don't log reflected ZONEVERSION option.
+        */
+       if (version_len == 0) {
+               return;
+       }
+
+       /* Enforced by dns_rdata_fromwire. */
+       INSIST(version_len >= 2);
+
+       /*
+        * Sanity check on label count.
+        */
+       labels = version[0] + 1;
+       if (dns_name_countlabels(query->fctx->name) < labels) {
+               return;
+       }
+
+       /*
+        * Get zone name.
+        */
+       dns_name_split(query->fctx->name, labels, NULL, &suffix);
+       dns_name_format(&suffix, namebuf, sizeof(namebuf));
+
+       if (nsid != NULL) {
+               nsid_buflen = nsid_len * 2 + 1;
+               nsid_hex = nsid_buf = isc_mem_get(mctx, nsid_buflen);
+               nsid_print = nsid_pbuf = isc_mem_get(mctx, nsid_len + 1);
+
+               /* Convert to hex */
+               make_hex(nsid, nsid_len, nsid_buf, nsid_buflen);
+
+               /* Convert to printable */
+               make_printable(nsid, nsid_len, nsid_pbuf, nsid_len + 1);
+
+               sep_1 = " (NSID ";
+               sep_2 = " (";
+               sep_3 = "))";
+       }
+
+       isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
+                           sizeof(addrbuf));
+       if (version[1] == 0 && version_len == 6) {
+               uint32_t serial = version[2] << 24 | version[3] << 2 |
+                                 version[4] << 8 | version[5];
+               isc_log_write(DNS_LOGCATEGORY_ZONEVERSION,
+                             DNS_LOGMODULE_RESOLVER, level,
+                             "received ZONEVERSION serial %u from %s for %s "
+                             "zone %s%s%s%s%s%s",
+                             serial, addrbuf, query->fctx->info, namebuf,
+                             sep_1, nsid_hex, sep_2, nsid_print, sep_3);
+       } else {
+               size_t version_buflen = version_len * 2 + 1;
+               char *version_hex = isc_mem_get(mctx, version_buflen);
+               char *version_pbuf = isc_mem_get(mctx, version_len - 1);
+
+               /* Convert to hex */
+               make_hex(version + 2, version_len - 2, version_hex,
+                        version_buflen);
+
+               /* Convert to printable */
+               make_printable(version + 2, version_len - 2, version_pbuf,
+                              version_len - 1);
+
+               isc_log_write(DNS_LOGCATEGORY_ZONEVERSION,
+                             DNS_LOGMODULE_RESOLVER, level,
+                             "received ZONEVERSION type %u value %s (%s) from "
+                             "%s for %s zone %s%s%s%s%s%s",
+                             version[1], version_hex, version_pbuf, addrbuf,
+                             query->fctx->info, namebuf, sep_1, nsid_hex,
+                             sep_2, nsid_print, sep_3);
+               isc_mem_put(mctx, version_hex, version_buflen);
+               isc_mem_put(mctx, version_pbuf, version_len - 1);
+       }
+
+       if (nsid_pbuf != NULL) {
+               isc_mem_put(mctx, nsid_pbuf, nsid_len + 1);
+       }
+       if (nsid_buf != NULL) {
+               isc_mem_put(mctx, nsid_buf, nsid_buflen);
+       }
+}
+
 static bool
 betterreferral(respctx_t *rctx) {
        isc_result_t result;
@@ -8191,6 +8321,11 @@ rctx_opt(respctx_t *rctx) {
        isc_result_t result;
        bool seen_cookie = false;
        bool seen_nsid = false;
+       bool seen_zoneversion = false;
+       unsigned char *nsid = NULL;
+       uint16_t nsidlen = 0;
+       unsigned char *zoneversion = NULL;
+       uint16_t zoneversionlen = 0;
 
        result = dns_rdataset_first(rctx->opt);
        if (result != ISC_R_SUCCESS) {
@@ -8216,7 +8351,8 @@ rctx_opt(respctx_t *rctx) {
                                break;
                        }
                        seen_nsid = true;
-
+                       nsid = isc_buffer_current(&optbuf);
+                       nsidlen = optlen;
                        if ((query->options & DNS_FETCHOPT_WANTNSID) != 0) {
                                log_nsid(&optbuf, optlen, query, ISC_LOG_INFO,
                                         fctx->mctx);
@@ -8254,12 +8390,27 @@ rctx_opt(respctx_t *rctx) {
                                                  optvalue, optlen);
                        }
                        break;
+               case DNS_OPT_ZONEVERSION:
+                       if (seen_zoneversion) {
+                               break;
+                       }
+                       seen_zoneversion = true;
+                       zoneversion = isc_buffer_current(&optbuf);
+                       zoneversionlen = optlen;
+                       break;
                default:
                        break;
                }
                isc_buffer_forward(&optbuf, optlen);
        }
        INSIST(isc_buffer_remaininglength(&optbuf) == 0U);
+
+       if ((query->options & DNS_FETCHOPT_WANTZONEVERSION) != 0 &&
+           zoneversion != NULL)
+       {
+               log_zoneversion(zoneversion, zoneversionlen, nsid, nsidlen,
+                               query, ISC_LOG_INFO, fctx->mctx);
+       }
 }
 
 /*
index ff954be1bac37bfbbfa94c537881f0378c042f63..a693be7cc12c0db25e4c4ee1afcceeff9baf4a5f 100644 (file)
@@ -119,36 +119,37 @@ enum isc_logcategory {
        NAMED_LOGCATEGORY_GENERAL = ISC_LOGCATEGORY_GENERAL,
        ISC_LOGCATEGORY_SSLKEYLOG,
        /* dns categories */
-       DNS_LOGCATEGORY_NOTIFY,
+       DNS_LOGCATEGORY_CNAME,
        DNS_LOGCATEGORY_DATABASE,
-       DNS_LOGCATEGORY_SECURITY,
-       DNS_LOGCATEGORY_DNSSEC,
-       DNS_LOGCATEGORY_RESOLVER,
-       DNS_LOGCATEGORY_XFER_IN,
-       DNS_LOGCATEGORY_XFER_OUT,
        DNS_LOGCATEGORY_DISPATCH,
-       DNS_LOGCATEGORY_LAME_SERVERS,
+       DNS_LOGCATEGORY_DNSSEC,
+       DNS_LOGCATEGORY_DNSTAP,
        DNS_LOGCATEGORY_EDNS_DISABLED,
+       DNS_LOGCATEGORY_LAME_SERVERS,
+       DNS_LOGCATEGORY_NOTIFY,
+       DNS_LOGCATEGORY_NSID,
+       DNS_LOGCATEGORY_RESOLVER,
        DNS_LOGCATEGORY_RPZ,
+       DNS_LOGCATEGORY_RPZ_PASSTHRU,
        DNS_LOGCATEGORY_RRL,
-       DNS_LOGCATEGORY_CNAME,
+       DNS_LOGCATEGORY_SECURITY,
        DNS_LOGCATEGORY_SPILL,
-       DNS_LOGCATEGORY_DNSTAP,
-       DNS_LOGCATEGORY_ZONELOAD,
-       DNS_LOGCATEGORY_NSID,
-       DNS_LOGCATEGORY_RPZ_PASSTHRU,
        DNS_LOGCATEGORY_UPDATE_POLICY,
+       DNS_LOGCATEGORY_XFER_IN,
+       DNS_LOGCATEGORY_XFER_OUT,
+       DNS_LOGCATEGORY_ZONELOAD,
+       DNS_LOGCATEGORY_ZONEVERSION,
        /* ns categories */
        NS_LOGCATEGORY_CLIENT,
+       NS_LOGCATEGORY_DRA,
        NS_LOGCATEGORY_NETWORK,
-       NS_LOGCATEGORY_UPDATE,
        NS_LOGCATEGORY_QUERIES,
-       NS_LOGCATEGORY_UPDATE_SECURITY,
        NS_LOGCATEGORY_QUERY_ERRORS,
-       NS_LOGCATEGORY_TAT,
-       NS_LOGCATEGORY_SERVE_STALE,
        NS_LOGCATEGORY_RESPONSES,
-       NS_LOGCATEGORY_DRA,
+       NS_LOGCATEGORY_SERVE_STALE,
+       NS_LOGCATEGORY_TAT,
+       NS_LOGCATEGORY_UPDATE,
+       NS_LOGCATEGORY_UPDATE_SECURITY,
        /* cfg categories */
        CFG_LOGCATEGORY_CONFIG,
        /* named categories */
index 79dbe3cf6d917f9ab767f22563ecc036086c7c7e..576e6b4150f2979d18fe69c338429883decdcefd 100644 (file)
@@ -170,36 +170,37 @@ static const char *categories_description[] = {
        [ISC_LOGCATEGORY_GENERAL] = "general",
        [ISC_LOGCATEGORY_SSLKEYLOG] = "sslkeylog",
        /* dns categories */
-       [DNS_LOGCATEGORY_NOTIFY] = "notify",
+       [DNS_LOGCATEGORY_CNAME] = "cname",
        [DNS_LOGCATEGORY_DATABASE] = "database",
-       [DNS_LOGCATEGORY_SECURITY] = "security",
-       [DNS_LOGCATEGORY_DNSSEC] = "dnssec",
-       [DNS_LOGCATEGORY_RESOLVER] = "resolver",
-       [DNS_LOGCATEGORY_XFER_IN] = "xfer-in",
-       [DNS_LOGCATEGORY_XFER_OUT] = "xfer-out",
        [DNS_LOGCATEGORY_DISPATCH] = "dispatch",
-       [DNS_LOGCATEGORY_LAME_SERVERS] = "lame-servers",
+       [DNS_LOGCATEGORY_DNSSEC] = "dnssec",
+       [DNS_LOGCATEGORY_DNSTAP] = "dnstap",
        [DNS_LOGCATEGORY_EDNS_DISABLED] = "edns-disabled",
+       [DNS_LOGCATEGORY_LAME_SERVERS] = "lame-servers",
+       [DNS_LOGCATEGORY_NOTIFY] = "notify",
+       [DNS_LOGCATEGORY_NSID] = "nsid",
+       [DNS_LOGCATEGORY_RESOLVER] = "resolver",
        [DNS_LOGCATEGORY_RPZ] = "rpz",
+       [DNS_LOGCATEGORY_RPZ_PASSTHRU] = "rpz-passthru",
        [DNS_LOGCATEGORY_RRL] = "rate-limit",
-       [DNS_LOGCATEGORY_CNAME] = "cname",
+       [DNS_LOGCATEGORY_SECURITY] = "security",
        [DNS_LOGCATEGORY_SPILL] = "spill",
-       [DNS_LOGCATEGORY_DNSTAP] = "dnstap",
-       [DNS_LOGCATEGORY_ZONELOAD] = "zoneload",
-       [DNS_LOGCATEGORY_NSID] = "nsid",
-       [DNS_LOGCATEGORY_RPZ_PASSTHRU] = "rpz-passthru",
        [DNS_LOGCATEGORY_UPDATE_POLICY] = "update-policy",
+       [DNS_LOGCATEGORY_XFER_IN] = "xfer-in",
+       [DNS_LOGCATEGORY_XFER_OUT] = "xfer-out",
+       [DNS_LOGCATEGORY_ZONELOAD] = "zoneload",
+       [DNS_LOGCATEGORY_ZONEVERSION] = "zoneversion",
        /* ns categories */
        [NS_LOGCATEGORY_CLIENT] = "client",
+       [NS_LOGCATEGORY_DRA] = "dns-reporting-agent",
        [NS_LOGCATEGORY_NETWORK] = "network",
-       [NS_LOGCATEGORY_UPDATE] = "update",
        [NS_LOGCATEGORY_QUERIES] = "queries",
-       [NS_LOGCATEGORY_UPDATE_SECURITY] = "update-security",
        [NS_LOGCATEGORY_QUERY_ERRORS] = "query-errors",
-       [NS_LOGCATEGORY_TAT] = "trust-anchor-telemetry",
-       [NS_LOGCATEGORY_DRA] = "dns-reporting-agent",
-       [NS_LOGCATEGORY_SERVE_STALE] = "serve-stale",
        [NS_LOGCATEGORY_RESPONSES] = "responses",
+       [NS_LOGCATEGORY_SERVE_STALE] = "serve-stale",
+       [NS_LOGCATEGORY_TAT] = "trust-anchor-telemetry",
+       [NS_LOGCATEGORY_UPDATE] = "update",
+       [NS_LOGCATEGORY_UPDATE_SECURITY] = "update-security",
        /* cfg categories */
        [CFG_LOGCATEGORY_CONFIG] = "config",
        /* named categories */
index 2e8a4b22973a0114893e6f9865231384772bae61..3df96f1b33fef3dd6177a8b309e5c20614ada9b5 100644 (file)
@@ -4242,6 +4242,7 @@ static struct {
        { "request-expire", dns_peer_setrequestexpire },
        { "request-ixfr", dns_peer_setrequestixfr },
        { "request-nsid", dns_peer_setrequestnsid },
+       { "request-zoneversion", dns_peer_setrequestzoneversion },
        { "send-cookie", dns_peer_setsendcookie },
        { "tcp-keepalive", dns_peer_settcpkeepalive },
        { "tcp-only", dns_peer_setforcetcp },
index 85d1c531c0037d2b663e5a11a7b7cd9b6ce4ef8c..45649d87701c3c8962602a3e00ef62c672030e91 100644 (file)
@@ -2110,6 +2110,7 @@ static cfg_clausedef_t view_clauses[] = {
        { "recursion", &cfg_type_boolean, 0 },
        { "request-nsid", &cfg_type_boolean, 0 },
        { "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
+       { "request-zoneversion", &cfg_type_boolean, 0 },
        { "require-server-cookie", &cfg_type_boolean, 0 },
        { "resolver-nonbackoff-tries", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "resolver-query-timeout", &cfg_type_uint32, 0 },
@@ -2603,6 +2604,7 @@ static cfg_clausedef_t server_clauses[] = {
        { "request-ixfr", &cfg_type_boolean, 0 },
        { "request-ixfr-max-diffs", &cfg_type_uint32, 0 },
        { "request-nsid", &cfg_type_boolean, 0 },
+       { "request-zoneversion", &cfg_type_boolean, 0 },
        { "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "require-cookie", &cfg_type_boolean, 0 },
        { "send-cookie", &cfg_type_boolean, 0 },