]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Allow send-report-channel to be set at the zone level
authorMark Andrews <marka@isc.org>
Wed, 15 May 2024 04:10:43 +0000 (14:10 +1000)
committerEvan Hunt <each@isc.org>
Wed, 23 Oct 2024 21:29:32 +0000 (21:29 +0000)
If send-report-channel is set at the zone level, it will
be stored in the zone object and used instead of the
view-level agent-domain when constructing the EDNS
Report-Channel option.

13 files changed:
bin/named/config.c
bin/named/zoneconf.c
bin/tests/system/auth/ns1/named.conf.in
bin/tests/system/auth/tests.sh
doc/arm/reference.rst
doc/misc/primary.zoneopt
doc/misc/secondary.zoneopt
lib/dns/include/dns/zone.h
lib/dns/zone.c
lib/isccfg/namedconf.c
lib/ns/client.c
lib/ns/include/ns/client.h
lib/ns/query.c

index 94df346db4f48c48977d4794757cf271acf4ebe0..3a89ef1bd2026647736d622fdd1df5633b964922 100644 (file)
@@ -236,6 +236,7 @@ options {\n\
        notify yes;\n\
        notify-delay 5;\n\
        notify-to-soa no;\n\
+#      send-report-channel <none>\n\
        serial-update-method increment;\n\
        sig-signing-nodes 100;\n\
        sig-signing-signatures 10;\n\
index 4253a73821c123b78ebaa2de940edffccf8bece1..3c4f43e6a6b22b4ccf23e5f040efa0957f5dc916 100644 (file)
@@ -1481,6 +1481,18 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
                                   cfg_obj_asboolean(obj));
+
+               obj = NULL;
+               (void)cfg_map_get(zoptions, "send-report-channel", &obj);
+               if (obj != NULL) {
+                       dns_fixedname_t fixed;
+                       dns_name_t *rad = dns_fixedname_initname(&fixed);
+                       CHECK(dns_name_fromstring(rad, cfg_obj_asstring(obj),
+                                                 dns_rootname, 0, mctx));
+                       dns_zone_setrad(zone, rad);
+               } else {
+                       dns_zone_setrad(zone, NULL);
+               }
        } else if (ztype == dns_zone_redirect) {
                dns_zone_setnotifytype(zone, dns_notifytype_no);
 
index 027a08851d5dfa2746166fb0e942002471db3d90..0f40bbbf4a9a4d8d5f29f1e802441d9e867c1e41 100644 (file)
@@ -36,6 +36,7 @@ view main in {
        zone example.com {
                type primary;
                file "example.com.db";
+               send-report-channel "rad.example.com";
        };
 };
 
index 591adfd9c29cf2b96f0844671b98339a5c298bc2..7900ae0010fa9c7a18bf4414dc7ba7750fd80136 100644 (file)
@@ -194,6 +194,14 @@ grep "; Report-Channel: rad.example.net" dig.out.test$n >/dev/null || ret=1
 [ $ret -eq 0 ] || echo_i "failed"
 status=$((status + ret))
 
+n=$((n + 1))
+echo_i "check that a zone-level Report-Channel EDNS option is added to responses ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.1 example.com >dig.out.test$n
+grep "; Report-Channel: rad.example.com" dig.out.test$n >/dev/null || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+status=$((status + ret))
+
 n=$((n + 1))
 echo_i "check that error report queries are logged and no Report-Channel option is present in the response ($n)"
 ret=0
index c6ff719c12308de4d1a45c1fe6c1d438945846a7..ef2d15277a70d027a22cf285e6407d0117187305 100644 (file)
@@ -1691,11 +1691,14 @@ default is used.
    problems with resolution or validation elsewhere (for example,
    expired DNSSEC signatures).
 
-   When :any:`send-report-channel` is set in :namedconf:ref:`options`, or
-   :namedconf:ref:`view` :iscman:`named` adds a Report-Channel option to
-   authoritative responses, using the specified domain name as the
-   Agent-Domain.  :iscman:`named` also logs any TXT queries received for
-   names matching the prescribed error-reporting format
+   When :any:`send-report-channel` is set in :namedconf:ref:`options`,
+   :namedconf:ref:`view`, or :namedconf:ref:`zone`, :iscman:`named` adds a
+   Report-Channel option to authoritative responses, using the specified
+   domain name as the Agent-Domain.
+
+   When it is set in :namedconf:ref:`options` or :namedconf:ref:`view` (but
+   *not* :namedconf:ref:`zone`), :iscman:`named` also logs any TXT queries
+   received for names matching the prescribed error-reporting format
    (_er.<type>.<name>.<extended-rcode>._er.<agent-domain>) to the
    ``dns-reporting-agent`` logging category at level ``info``.
 
index a561aabc2dfb87435b65ebc85490cb7400813ce5..2a37f2b92674e46f3766ef2ab91908aa06c285f3 100644 (file)
@@ -50,6 +50,7 @@ zone <string> [ <class> ] {
        parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
        parental-source ( <ipv4_address> | * );
        parental-source-v6 ( <ipv6_address> | * );
+       send-report-channel <string>;
        serial-update-method ( date | increment | unixtime );
        sig-signing-nodes <integer>;
        sig-signing-signatures <integer>;
index 83be6bb37a2ca635dd9c44b55fdfaf3fcad5c572..a08fe56835ed39ad02f03a8127739dc1258cd833 100644 (file)
@@ -51,6 +51,7 @@ zone <string> [ <class> ] {
        request-expire <boolean>;
        request-ixfr <boolean>;
        request-ixfr-max-diffs <integer>;
+       send-report-channel <string>;
        sig-signing-nodes <integer>;
        sig-signing-signatures <integer>;
        sig-signing-type <integer>;
index e30ac2f73f91a98610243bbf0a8ca270ed667e02..cded4750bd72c8be96faca8c318f2195ed24ac53 100644 (file)
@@ -2770,6 +2770,26 @@ dns_zone_import_skr(dns_zone_t *zone, const char *file);
  * \li  ISC_R_SUCCESS if there were no errors loading the SKR.
  */
 
+void
+dns_zone_setrad(dns_zone_t *zone, dns_name_t *name);
+/**<
+ * \brief Set the per zone RAD
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ * \li 'name' is NULL or a valid name.
+ */
+
+isc_result_t
+dns_zone_getrad(dns_zone_t *zone, dns_name_t *name);
+/**<
+ * \brief get the per zone RAD
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ * \li 'name' is a valid name with a buffer.
+ */
+
 #if DNS_ZONE_TRACE
 #define dns_zone_ref(ptr)   dns_zone__ref(ptr, __func__, __FILE__, __LINE__)
 #define dns_zone_unref(ptr) dns_zone__unref(ptr, __func__, __FILE__, __LINE__)
index ed5763654f9822fb6654f4fa9ddc65e7f62d2752..188c23f6b666602f0c0da94bd5518471ac640370 100644 (file)
@@ -276,6 +276,7 @@ struct dns_zone {
        isc_timer_t *timer;
        isc_refcount_t irefs;
        dns_name_t origin;
+       dns_name_t rad;
        char *masterfile;
        const FILE *stream;                  /* loading from a stream? */
        ISC_LIST(dns_include_t) includes;    /* Include files */
@@ -1167,6 +1168,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) {
        isc_refcount_init(&zone->references, 1);
        isc_refcount_init(&zone->irefs, 0);
        dns_name_init(&zone->origin, NULL);
+       dns_name_init(&zone->rad, NULL);
        isc_sockaddr_any(&zone->notifysrc4);
        isc_sockaddr_any6(&zone->notifysrc6);
        isc_sockaddr_any(&zone->parentalsrc4);
@@ -1348,6 +1350,9 @@ zone_free(dns_zone_t *zone) {
        if (dns_name_dynamic(&zone->origin)) {
                dns_name_free(&zone->origin, zone->mctx);
        }
+       if (dns_name_dynamic(&zone->rad)) {
+               dns_name_free(&zone->rad, zone->mctx);
+       }
        if (zone->strnamerd != NULL) {
                isc_mem_free(zone->mctx, zone->strnamerd);
        }
@@ -24509,3 +24514,34 @@ failure:
 
        return (result);
 }
+
+isc_result_t
+dns_zone_getrad(dns_zone_t *zone, dns_name_t *name) {
+       isc_result_t result = ISC_R_NOTFOUND;
+
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(DNS_NAME_VALID(name));
+
+       LOCK_ZONE(zone);
+       if (dns_name_dynamic(&zone->rad)) {
+               dns_name_copy(&zone->rad, name);
+               result = ISC_R_SUCCESS;
+       }
+       UNLOCK_ZONE(zone);
+       return (result);
+}
+
+void
+dns_zone_setrad(dns_zone_t *zone, dns_name_t *name) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(name == NULL || DNS_NAME_VALID(name));
+
+       LOCK_ZONE(zone);
+       if (dns_name_dynamic(&zone->rad)) {
+               dns_name_free(&zone->rad, zone->mctx);
+       }
+       if (name != NULL) {
+               dns_name_dup(name, zone->mctx, &zone->rad);
+       }
+       UNLOCK_ZONE(zone);
+}
index d951101525c28a73521e75435e402b396e1aa2b2..791b47e27ea09740433227945e222a5c38ff3c48 100644 (file)
@@ -2132,7 +2132,6 @@ static cfg_clausedef_t view_clauses[] = {
        { "queryport-pool-updateinterval", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "rate-limit", &cfg_type_rrl, 0 },
        { "recursion", &cfg_type_boolean, 0 },
-       { "send-report-channel", &cfg_type_astring, 0 },
        { "request-nsid", &cfg_type_boolean, 0 },
        { "request-sit", NULL, CFG_CLAUSEFLAG_ANCIENT },
        { "require-server-cookie", &cfg_type_boolean, 0 },
@@ -2361,6 +2360,8 @@ static cfg_clausedef_t zone_clauses[] = {
          CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
        { "parental-source-v6", &cfg_type_sockaddr6wild,
          CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
+       { "send-report-channel", &cfg_type_astring,
+         CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
        { "request-expire", &cfg_type_boolean,
          CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
        { "request-ixfr", &cfg_type_boolean,
index 25bb7e5a8a65f2775d0dd2c09192266b957ca001..a1a2b4ad34febe0daed80d17760bab958d3a8c86 100644 (file)
@@ -315,6 +315,9 @@ ns_client_endrequest(ns_client_t *client) {
        client->extflags = 0;
        client->ednsversion = -1;
        client->additionaldepth = 0;
+       if (dns_name_dynamic(&client->rad)) {
+               dns_name_free(&client->rad, client->manager->mctx);
+       }
        dns_ecs_init(&client->ecs);
        dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
 
@@ -1236,14 +1239,20 @@ no_nsid:
                count++;
        }
 
-       if (WANTRC(client) && view != NULL && view->rad != NULL &&
-           !dns_name_equal(view->rad, dns_rootname))
-       {
-               INSIST(count < DNS_EDNSOPTIONS);
-               ednsopts[count].code = DNS_OPT_REPORT_CHANNEL;
-               ednsopts[count].length = view->rad->length;
-               ednsopts[count].value = view->rad->ndata;
-               count++;
+       if (WANTRC(client)) {
+               dns_name_t *rad = NULL;
+               if (dns_name_dynamic(&client->rad)) {
+                       rad = &client->rad;
+               } else if (view != NULL && view->rad != NULL) {
+                       rad = view->rad;
+               }
+               if (rad != NULL && !dns_name_equal(rad, dns_rootname)) {
+                       INSIST(count < DNS_EDNSOPTIONS);
+                       ednsopts[count].code = DNS_OPT_REPORT_CHANNEL;
+                       ednsopts[count].length = rad->length;
+                       ednsopts[count].value = rad->ndata;
+                       count++;
+               }
        }
 
        /* Padding must be added last */
@@ -2568,6 +2577,7 @@ ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
        client->udpsize = 512;
        client->ednsversion = -1;
        dns_name_init(&client->signername, NULL);
+       dns_name_init(&client->rad, NULL);
        dns_ecs_init(&client->ecs);
        isc_sockaddr_any(&client->formerrcache.addr);
        client->formerrcache.time = 0;
index e03bc11e6ddd4016fd94943818dff645ab33b6a7..2c516de3b87684caa2815c696f293e24329dfc58 100644 (file)
@@ -197,6 +197,8 @@ struct ns_client {
        isc_buffer_t *buffer;
        isc_buffer_t  tbuffer;
 
+       dns_name_t rad; /* Zone rad domain */
+
        isc_sockaddr_t peeraddr;
        bool           peeraddr_valid;
        isc_netaddr_t  destaddr;
index 4a11ca785734663821b0677ea8248858f5015e38..ed2662b0a71919b5fbdb9fdea0edf6a0f54f5c16 100644 (file)
@@ -5518,12 +5518,30 @@ ns__query_start(query_ctx_t *qctx) {
        if (qctx->is_zone) {
                qctx->authoritative = true;
                if (qctx->zone != NULL) {
-                       if (dns_zone_gettype(qctx->zone) == dns_zone_mirror) {
+                       dns_fixedname_t fixed;
+                       dns_name_t *rad;
+                       switch (dns_zone_gettype(qctx->zone)) {
+                       case dns_zone_mirror:
                                qctx->authoritative = false;
-                       }
-                       if (dns_zone_gettype(qctx->zone) == dns_zone_staticstub)
-                       {
+                               break;
+                       case dns_zone_staticstub:
                                qctx->is_staticstub_zone = true;
+                               break;
+                       case dns_zone_primary:
+                       case dns_zone_secondary:
+                               rad = dns_fixedname_initname(&fixed);
+                               if (!dns_name_dynamic(&qctx->client->rad) &&
+                                   dns_zone_getrad(qctx->zone, rad) ==
+                                           ISC_R_SUCCESS)
+                               {
+                                       dns_name_dup(
+                                               rad,
+                                               qctx->client->manager->mctx,
+                                               &qctx->client->rad);
+                               }
+                               break;
+                       default:
+                               break;
                        }
                }
        }