]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Change notify-cds option to notify-cfg CDS
authorMatthijs Mekking <matthijs@isc.org>
Wed, 17 Dec 2025 08:51:03 +0000 (09:51 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Mon, 29 Dec 2025 09:06:16 +0000 (10:06 +0100)
Change the notify configuration to be more flexible for other types
of generalized DNS notifications.

Also allow for notify-cfg SOA.

15 files changed:
bin/include/defaultconfig.h
bin/named/zoneconf.c
bin/tests/system/checkconf/bad-notifycdstype.conf
bin/tests/system/checkconf/bad-notifycfgtype.conf [new file with mode: 0644]
bin/tests/system/checkconf/good.conf.j2
bin/tests/system/multisigner/ns3/named.conf.j2
bin/tests/system/multisigner/ns4/named.conf.j2
bin/tests/system/rollover/ns3/named.common.conf.j2
doc/arm/reference.rst
doc/misc/mirror.zoneopt
doc/misc/options
doc/misc/primary.zoneopt
doc/misc/secondary.zoneopt
lib/isccfg/check.c
lib/isccfg/namedconf.c

index 9ecd96588e583f15111c1c9100513652e70236d2..8e247572607db24f2225bd15d01e83a732cb07a0 100644 (file)
@@ -215,7 +215,6 @@ options {\n\
        min-transfer-rate-in 10240 5;\n\
        multi-master no;\n\
        notify yes;\n\
-       notify-cds no;\n\
        notify-defer 0;\n\
        notify-delay 5;\n\
        notify-to-soa no;\n\
index 4498b01fde3e0b3ad10d6882cc7df81c07037faf..f3799dd14d34e213704df6b3f0f2102b7bbd89fe 100644 (file)
@@ -62,6 +62,10 @@ typedef enum {
        allow_update_forwarding
 } acl_type_t;
 
+#define MAPS_SIZE          6
+#define NODEFAULT_MAPS_SIZE 5
+#define NOOPTIONS_MAPS_SIZE 3
+
 /*%
  * Convenience function for configuring a single zone ACL.
  */
@@ -71,7 +75,7 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
                   cfg_aclconfctx_t *aclctx, dns_zone_t *zone,
                   void (*setzacl)(dns_zone_t *, dns_acl_t *),
                   void (*clearzacl)(dns_zone_t *)) {
-       const cfg_obj_t *maps[6] = { 0 };
+       const cfg_obj_t *maps[MAPS_SIZE] = { 0 };
        const cfg_obj_t *aclobj = NULL;
        int i = 0;
        dns_acl_t **aclp = NULL, *acl = NULL;
@@ -819,8 +823,8 @@ isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr,
  * default configuration.
  */
 static dns_notifytype_t
-process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
-                  const char *zname, const cfg_obj_t **maps) {
+process_notifysoatype(dns_notifytype_t ntype, dns_zonetype_t ztype,
+                     const char *zname, const cfg_obj_t **maps) {
        const cfg_obj_t *obj = NULL;
 
        /*
@@ -845,6 +849,105 @@ process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
        return dns_notifytype_explicit;
 }
 
+static void
+process_notify_options(dns_rdatatype_t type, const cfg_obj_t **maps,
+                      dns_zone_t *zone, dns_zone_t *raw, bool notifycfg) {
+       isc_result_t result;
+       const cfg_obj_t *obj = NULL;
+
+       /*
+        * "notify" for SOA is already inherited and set in
+        * named_zone_configure(), and for other types it can only be
+        * configured within "notify-cfg".  Only look into first map
+        * to see if sending NOTIFY(type) messages are allowed.
+        */
+       if (notifycfg) {
+               obj = NULL;
+               result = cfg_map_get(maps[0], "notify", &obj);
+               if (result == ISC_R_SUCCESS && obj != NULL) {
+                       dns_zone_setnotifytype(zone, type,
+                                              cfg_obj_asboolean(obj));
+               } else {
+                       dns_zone_setnotifytype(zone, type, dns_notifytype_no);
+               }
+               if (raw != NULL) {
+                       dns_zone_setnotifytype(raw, type, dns_notifytype_no);
+               }
+       }
+
+       obj = NULL;
+       result = named_config_get(maps, "notify-delay", &obj);
+       INSIST(result == ISC_R_SUCCESS && obj != NULL);
+       dns_zone_setnotifydelay(zone, type, cfg_obj_asuint32(obj));
+
+       obj = NULL;
+       result = named_config_get(maps, "notify-defer", &obj);
+       INSIST(result == ISC_R_SUCCESS && obj != NULL);
+       dns_zone_setnotifydefer(zone, type, cfg_obj_asuint32(obj));
+
+       obj = NULL;
+       result = named_config_get(maps, "notify-source", &obj);
+       INSIST(result == ISC_R_SUCCESS && obj != NULL);
+       dns_zone_setnotifysrc4(zone, type, cfg_obj_assockaddr(obj));
+
+       obj = NULL;
+       result = named_config_get(maps, "notify-source-v6", &obj);
+       INSIST(result == ISC_R_SUCCESS && obj != NULL);
+       dns_zone_setnotifysrc6(zone, type, cfg_obj_assockaddr(obj));
+}
+
+static isc_result_t
+process_notify_cfg(const cfg_obj_t **maps, dns_zone_t *zone, dns_zone_t *raw) {
+       isc_result_t result;
+       const cfg_obj_t *obj = NULL;
+
+       result = named_config_get(maps, "notify-cfg", &obj);
+       if (result == ISC_R_SUCCESS && obj != NULL) {
+               CFG_LIST_FOREACH(obj, element) {
+                       const cfg_obj_t *nmaps[MAPS_SIZE + 1];
+                       const cfg_obj_t *map = cfg_listelt_value(element);
+                       const char *name =
+                               cfg_obj_asstring(cfg_map_getname(map));
+                       isc_textregion_t tr;
+                       dns_rdatatype_t rdtype = 0;
+
+                       tr.base = UNCONST(name);
+                       tr.length = strlen(name);
+                       result = dns_rdatatype_fromtext(&rdtype, &tr);
+                       if (result != ISC_R_SUCCESS) {
+                               cfg_obj_log(map, ISC_LOG_ERROR,
+                                           "%s is not a valid notify type",
+                                           name);
+                               return result;
+                       }
+                       switch (rdtype) {
+                       case dns_rdatatype_soa:
+                       case dns_rdatatype_cds:
+                               break;
+                       default:
+                               cfg_obj_log(map, ISC_LOG_ERROR,
+                                           "%s notify type is not supported",
+                                           name);
+                               return ISC_R_NOTIMPLEMENTED;
+                       }
+
+                       /* Prepend the notify-cfg map. */
+                       size_t i = 0;
+                       nmaps[i] = map;
+                       while (maps[i] != NULL) {
+                               nmaps[i + 1] = maps[i];
+                               i++;
+                       }
+                       INSIST(i <= MAPS_SIZE);
+                       nmaps[i + 1] = NULL;
+
+                       process_notify_options(rdtype, nmaps, zone, raw, true);
+               }
+       }
+
+       return ISC_R_SUCCESS;
+}
+
 isc_result_t
 named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                     const cfg_obj_t *zconfig, cfg_aclconfctx_t *aclctx,
@@ -854,9 +957,9 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
        const char *zname;
        dns_rdataclass_t zclass;
        dns_rdataclass_t vclass;
-       const cfg_obj_t *maps[6];
-       const cfg_obj_t *nodefault[5];
-       const cfg_obj_t *nooptions[3];
+       const cfg_obj_t *maps[MAPS_SIZE];
+       const cfg_obj_t *nodefault[NODEFAULT_MAPS_SIZE];
+       const cfg_obj_t *nooptions[NOOPTIONS_MAPS_SIZE];
        const cfg_obj_t *zoptions = NULL;
        const cfg_obj_t *toptions = NULL;
        const cfg_obj_t *options = NULL;
@@ -1194,6 +1297,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                        } else {
                                notifytype = dns_notifytype_no;
                        }
+                       notifytype = cfg_obj_asboolean(obj);
                } else {
                        const char *str = cfg_obj_asstring(obj);
                        if (strcasecmp(str, "explicit") == 0) {
@@ -1206,24 +1310,14 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                                UNREACHABLE();
                        }
                }
-               notifytype = process_notifytype(notifytype, ztype, zname,
-                                               nodefault);
+               notifytype = process_notifysoatype(notifytype, ztype, zname,
+                                                  nodefault);
                if (raw != NULL) {
                        dns_zone_setnotifytype(raw, dns_rdatatype_soa,
                                               dns_notifytype_no);
                }
                dns_zone_setnotifytype(zone, dns_rdatatype_soa, notifytype);
 
-               obj = NULL;
-               result = named_config_get(maps, "notify-cds", &obj);
-               INSIST(result == ISC_R_SUCCESS && obj != NULL);
-               if (raw != NULL) {
-                       dns_zone_setnotifytype(raw, dns_rdatatype_cds,
-                                              dns_notifytype_no);
-               }
-               dns_zone_setnotifytype(zone, dns_rdatatype_cds,
-                                      cfg_obj_asboolean(obj));
-
                obj = NULL;
                result = named_config_get(maps, "also-notify", &obj);
                if (result == ISC_R_SUCCESS &&
@@ -1255,18 +1349,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
                dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj));
 
-               obj = NULL;
-               result = named_config_get(maps, "notify-source", &obj);
-               INSIST(result == ISC_R_SUCCESS && obj != NULL);
-               dns_zone_setnotifysrc4(zone, dns_rdatatype_soa,
-                                      cfg_obj_assockaddr(obj));
-
-               obj = NULL;
-               result = named_config_get(maps, "notify-source-v6", &obj);
-               INSIST(result == ISC_R_SUCCESS && obj != NULL);
-               dns_zone_setnotifysrc6(zone, dns_rdatatype_soa,
-                                      cfg_obj_assockaddr(obj));
-
                obj = NULL;
                result = named_config_get(maps, "notify-to-soa", &obj);
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
@@ -1395,18 +1477,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                                           fail);
                }
 
-               obj = NULL;
-               result = named_config_get(maps, "notify-delay", &obj);
-               INSIST(result == ISC_R_SUCCESS && obj != NULL);
-               dns_zone_setnotifydelay(zone, dns_rdatatype_soa,
-                                       cfg_obj_asuint32(obj));
-
-               obj = NULL;
-               result = named_config_get(maps, "notify-defer", &obj);
-               INSIST(result == ISC_R_SUCCESS && obj != NULL);
-               dns_zone_setnotifydefer(zone, dns_rdatatype_soa,
-                                       cfg_obj_asuint32(obj));
-
                obj = NULL;
                result = named_config_get(maps, "check-sibling", &obj);
                INSIST(result == ISC_R_SUCCESS && obj != NULL);
@@ -1487,6 +1557,11 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                                dns_zone_setrad(zone, rad);
                        }
                }
+
+               process_notify_options(dns_rdatatype_soa, maps, zone, raw,
+                                      false);
+               CHECK(process_notify_cfg(maps, zone, raw));
+
        } else if (ztype == dns_zone_redirect) {
                dns_zone_setnotifytype(zone, dns_rdatatype_soa,
                                       dns_notifytype_no);
@@ -2005,7 +2080,8 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
 bool
 named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
                         const cfg_obj_t *config, dns_kasplist_t *kasplist) {
-       const cfg_obj_t *maps[5] = { 0 }, *noopts[3] = { 0 };
+       const cfg_obj_t *maps[NODEFAULT_MAPS_SIZE] = { 0 },
+                       *noopts[NOOPTIONS_MAPS_SIZE] = { 0 };
        const cfg_obj_t *signing = NULL;
        const cfg_obj_t *policy = NULL;
        const cfg_obj_t *toptions = NULL;
index 6dc6ff9678a3350b60a0dc0ed2e1425ec4c97bbe..e5713d5f1959f591a9aac61bd9ae5ffdbdd15c4a 100644 (file)
  */
 
 /*
- * Bad notify-cds type
+ * Bad notify-cfg CDS notify type
  */
 
 zone dummy {
        type primary;
        file "xxxx";
-       notify-cds explicit;
+       notify-cfg CDS { notify explicit; };
 };
diff --git a/bin/tests/system/checkconf/bad-notifycfgtype.conf b/bin/tests/system/checkconf/bad-notifycfgtype.conf
new file mode 100644 (file)
index 0000000..e4a21ab
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Bad notify-cfg TXT not supported
+ */
+
+zone dummy {
+       type primary;
+       file "xxxx";
+       notify-cfg TXT { notify yes; };
+};
index 2f98e67bf973cd5e2038600f2f5096f9e6eb449b..d4d99969c26299e820c2936ebd5b59ccd5e08f51 100644 (file)
@@ -194,7 +194,16 @@ view "fourth" {
                        1.2.3.5;
                };
                dnssec-policy "test";
-               notify-cds no;
+               notify-cfg "SOA" {
+                       notify yes;
+                       notify-defer 1;
+                       notify-delay 3;
+                       notify-source 192.0.2.1;
+                       notify-source-v6 2001:db8::1;
+               };
+               notify-cfg "CDS" {
+                       notify no;
+               };
                parental-source 10.10.10.10;
        };
        zone "dnssec-default" {
@@ -204,7 +213,13 @@ view "fourth" {
                        "parents";
                };
                dnssec-policy "default";
-               notify-cds yes;
+               notify-cfg "CDS" {
+                       notify yes;
+                       notify-defer 0;
+                       notify-delay 5;
+                       notify-source 0.0.0.0;
+                       notify-source-v6 ::;
+               };
        };
        zone "dnssec-inherit" {
                type primary;
index b56f01bf279cf4162bb45ef673908fb29b77819a..796c1f0fd07021477c36f9c2a337491ba40c78c4 100644 (file)
@@ -26,7 +26,7 @@ options {
        allow-transfer { any; };
        key-directory ".";
        dnssec-validation yes;
-       notify-cds yes;
+       notify-cfg CDS { notify yes; };
 };
 
 key rndc_key {
index 3d551d04c4013b51f2ebeb751ca2bcbfe6f290d4..6e5ef7e688e6cdef606f419e2a7c0ac708d592e1 100644 (file)
@@ -26,7 +26,7 @@ options {
        allow-transfer { any; };
        key-directory ".";
        dnssec-validation yes;
-       notify-cds yes;
+       notify-cfg cds { notify yes; };
 };
 
 key rndc_key {
index 2c64dbeaa3e6fd6cf364fd5a9626041c1bb26693..8218ed61b448bc24c62b9197ae599b5bee97c640 100644 (file)
@@ -30,7 +30,7 @@ options {
         allow-transfer { any; };
         recursion yes;
         dnssec-validation @dnssec_validation@;
-        notify-cds yes;
+        notify-cfg CDS { notify yes; };
 };
 
 key rndc_key {
index e2381957485b0efa2d60bb3a70a0e56a3dda8a08..f3255078903aad91af693882c2be58ee66c53a4a 100644 (file)
@@ -2115,21 +2115,40 @@ Boolean Options
    statement. It would only be necessary to turn off this option if it
    caused secondary zones to crash.
 
-.. namedconf:statement:: notify-cds
+.. namedconf:statement:: notify-cfg
    :tags: dnssec
-   :short: Controls whether ``NOTIFY(CDS)`` messages are sent on zone changes.
-
-   If set to ``yes``, DNS NOTIFY(CDS) messages are sent when the CDS or CDNSKEY
-   RRset changes. The messages are sent to the servers listed in the parent
-   zone's matching DSYNC records. A DSYNC record matches if the owner name under
-   `_dsync` subdomain of the parent zone corresponds to the given zone.  For
-   example, the zone `child.example` should have a DSYNC record at
-   `child._dsync.example`.  In addition, the RRtype field of the record must be
-   `CDS` and the Scheme field must be 1 (NOTIFY).
-
-   The default is ``no``.  The :namedconf:ref:`notify-cds` option may also be
-   specified in the :any:`zone` statement, in which case it overrides the
-   ``options notify-cds`` statement.
+   :short: Controls generalized DNS notifications configuration.
+
+    This option can be used to override NOTIFY configuration options
+    for specific types.  The following options can be set within a
+    :any:`notify-cfg` statement: :any:`notify-defer`, :any:`notify-delay`,
+    :any:`notify-source`, :any:`notify-source-v6`, and
+    :namedconf:ref:`notify`.  The latter can only be set to
+    ``yes`` or ``no``.
+
+    By default, only NOTIFY(SOA) messages are enabled.  When configuring
+    notify configuration for other types you enable sending DNS notifications
+    for the given type. For example, to enable NOTIFY(CDS) messages, using a
+    specific source, you can add the following configuration:
+
+    ::
+
+        notify-cfg CDS { notify yes; notify-source-v6 2001:DB8::1; };
+
+    If enabled, DNS NOTIFY(CDS) messages are sent when the CDS or CDNSKEY
+    RRset changes. The messages are sent to the servers listed in the parent
+    zone's matching DSYNC records. A DSYNC record matches if the owner name under
+    `_dsync` subdomain of the parent zone corresponds to the given zone.  For
+    example, the zone `child.example` should have a DSYNC record at
+    `child._dsync.example`.  In addition, the RRtype field of the record must be
+    `CDS` and the Scheme field must be 1 (NOTIFY).
+
+    The :any:`notify-defer` and :any:`notify-delay` options are not applicable
+    to NOTIFY(CDS) messages and they are ignored for that type.
+
+    The :namedconf:ref:`notify-cfg` option may also be specified in the
+    :any:`zone` statement, in which case it overrides the ``options notify-cfg``
+    statement. The only supported types are ``SOA`` and ``CDS``.
 
 .. namedconf:statement:: notify-to-soa
    :tags: transfer
index 2cdf57f2af96ede00c98f48b9733ac3389b1f3e0..78ce7a50449825d1150bfee3848e62e42490f1d2 100644 (file)
@@ -29,7 +29,13 @@ zone <string> [ <class> ] {
        min-transfer-rate-in <integer> <integer>;
        multi-master <boolean>;
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-source ( <ipv4_address> | * );
index 2f1f03ec98309fa75dd23080c7a0e9149c16bf71..b5701e1f597599ddb39d9283f2a7c39345b7325a 100644 (file)
@@ -210,7 +210,13 @@ options {
        no-case-compress { <address_match_element>; ... };
        nocookie-udp-size <integer>;
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-rate <integer>;
@@ -416,7 +422,13 @@ template <string> {
        min-transfer-rate-in <integer> <integer>;
        multi-master <boolean>;
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-source ( <ipv4_address> | * );
@@ -588,7 +600,13 @@ view <string> [ <class> ] {
        no-case-compress { <address_match_element>; ... };
        nocookie-udp-size <integer>;
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-source ( <ipv4_address> | * );
index a5e26bee89ca22a0630f5cea76b1fb80fb71c157..3bdbf9ee65ba8221b9bad66285d56235c300e1fc 100644 (file)
@@ -44,7 +44,13 @@ zone <string> [ <class> ] {
        max-types-per-name <integer>;
        max-zone-ttl ( unlimited | <duration> ); // deprecated
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-source ( <ipv4_address> | * );
index cc1d28a9849d38b6159f308a8719915a0d3562a5..631ee731c34c140e19a7ad11022009c79e6930ce 100644 (file)
@@ -41,7 +41,13 @@ zone <string> [ <class> ] {
        min-transfer-rate-in <integer> <integer>;
        multi-master <boolean>;
        notify ( explicit | master-only | primary-only | <boolean> );
-       notify-cds <boolean>;
+       notify-cfg <string> {
+               notify <boolean>;
+               notify-defer <integer>;
+               notify-delay <integer>;
+               notify-source ( <ipv4_address> | * );
+               notify-source-v6 ( <ipv6_address> | * );
+       }; // may occur multiple times
        notify-defer <integer>;
        notify-delay <integer>;
        notify-source ( <ipv4_address> | * );
index 3851ecaec67575c88e16cf8066efc81cd44ada10..c10916b82e60ad19fdc6385812df7e5710467407 100644 (file)
@@ -3629,7 +3629,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
 
        /*
         * Primary, secondary, and mirror zones may have an "also-notify"
-        * field, but shouldn't if notify is disabled.
+        * field, but shouldn't if notify is disabled. Also check "notify-cfg"
+        * for valid types.
         */
        if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY ||
            ztype == CFG_ZONE_MIRROR)
@@ -3674,6 +3675,47 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
                                result = tresult;
                        }
                }
+
+               obj = NULL;
+               (void)get_zoneopt(zoptions, toptions, voptions, goptions,
+                                 "notify-cfg", &obj);
+               if (obj != NULL) {
+                       CFG_LIST_FOREACH(obj, element) {
+                               const cfg_obj_t *map =
+                                       cfg_listelt_value(element);
+                               const char *name =
+                                       cfg_obj_asstring(cfg_map_getname(map));
+                               isc_textregion_t tr;
+                               dns_rdatatype_t rdtype = 0;
+
+                               tr.base = UNCONST(name);
+                               tr.length = strlen(name);
+                               tresult = dns_rdatatype_fromtext(&rdtype, &tr);
+                               if (tresult != ISC_R_SUCCESS &&
+                                   result == ISC_R_SUCCESS)
+                               {
+                                       cfg_obj_log(
+                                               map, ISC_LOG_ERROR,
+                                               "%s is not a valid notify type",
+                                               name);
+                                       result = tresult;
+                               }
+
+                               switch (rdtype) {
+                               case dns_rdatatype_soa:
+                               case dns_rdatatype_cds:
+                                       break;
+                               default:
+                                       if (result == ISC_R_SUCCESS) {
+                                               cfg_obj_log(map, ISC_LOG_ERROR,
+                                                           "%s notify type is "
+                                                           "not supported",
+                                                           name);
+                                               result = ISC_R_NOTIMPLEMENTED;
+                                       }
+                               }
+                       }
+               }
        }
 
        /*
index f50c20d31ece360b913160ac0553303d273f63ad..d8392755a15015e2dadbec551d7017263cc4e566 100644 (file)
@@ -108,6 +108,7 @@ static cfg_type_t cfg_type_maxcachesize;
 static cfg_type_t cfg_type_maxduration;
 static cfg_type_t cfg_type_minimal;
 static cfg_type_t cfg_type_nameportiplist;
+static cfg_type_t cfg_type_notifycfg;
 static cfg_type_t cfg_type_notifytype;
 static cfg_type_t cfg_type_optional_allow;
 static cfg_type_t cfg_type_optional_class;
@@ -2685,8 +2686,10 @@ static cfg_clausedef_t zone_clauses[] = {
          CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB, NULL },
        { "notify", &cfg_type_notifytype,
          CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
-       { "notify-cds", &cfg_type_boolean,
-         CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
+       { "notify-cfg", &cfg_type_notifycfg,
+         CFG_CLAUSEFLAG_MULTI | CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY |
+                 CFG_ZONE_MIRROR,
+         NULL },
        { "notify-defer", &cfg_type_uint32,
          CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
        { "notify-delay", &cfg_type_uint32,
@@ -3399,6 +3402,25 @@ static cfg_type_t cfg_type_notifytype = {
        doc_notify_type, &cfg_rep_string,   notify_enums,
 };
 
+/*
+ * Generalized DNS Notifications.
+ */
+static cfg_clausedef_t notify_clauses[] = {
+       { "notify", &cfg_type_boolean, 0, NULL }, /* this limits the options for
+                                                    NOTIFY(SOA) */
+       { "notify-defer", &cfg_type_uint32, 0, NULL },
+       { "notify-delay", &cfg_type_uint32, 0, NULL },
+       { "notify-source", &cfg_type_sockaddr4wild, 0, NULL },
+       { "notify-source-v6", &cfg_type_sockaddr6wild, 0, NULL },
+       { NULL, NULL, 0, NULL },
+};
+
+static cfg_clausedef_t *notify_clausesets[] = { notify_clauses, NULL };
+
+static cfg_type_t cfg_type_notifycfg = { "notify-cfg", cfg_parse_named_map,
+                                        cfg_print_map, cfg_doc_map,
+                                        &cfg_rep_map,  notify_clausesets };
+
 static const char *minimal_enums[] = { "no-auth", "no-auth-recursive", NULL };
 static isc_result_t
 parse_minimal(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {