]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
conf: allow empty value for some zone items (references to remotes)
authorDaniel Salzman <daniel.salzman@nic.cz>
Thu, 9 May 2024 08:55:06 +0000 (10:55 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Thu, 16 May 2024 14:57:54 +0000 (16:57 +0200)
This allows overriding of corresponding non-empty template items.

doc/reference.rst
src/knot/conf/conf.c
src/knot/conf/conf.h
src/knot/conf/schema.c
src/knot/conf/tools.c
tests-extra/tests/config/template/test.py [new file with mode: 0644]

index 8538fd11bcada8dc40a046c2c68c79d6be51266b..ef34b25a7fccf6c437163f119057a5c841e62ead 100644 (file)
@@ -2604,6 +2604,7 @@ master
 An ordered list of references :ref:`remote<remote_id>` and
 :ref:`remotes<remotes_id>` to zone primary servers
 (formerly known as master servers).
+Empty value is allowed for template value overriding.
 
 *Default:* not set
 
@@ -2630,6 +2631,7 @@ notify
 An ordered list of references :ref:`remote<remote_id>` and
 :ref:`remotes<remotes_id>` to secondary servers to which notify
 message is sent if the zone changes.
+Empty value is allowed for template value overriding.
 
 *Default:* not set
 
@@ -2933,7 +2935,7 @@ ds-push
 -------
 
 Per zone configuration of :ref:`policy_ds-push`. This option overrides possible
-per policy option.
+per policy option. Empty value is allowed for template value overriding.
 
 *Default:* not set
 
index 977d9d8cf7d763d60c2571ace4094280bef46ee3..5e9ed8393f653aa39fc21292103f10c70843273b 100644 (file)
@@ -191,6 +191,10 @@ conf_val_t conf_zone_get_txn(
        conf_db_get(conf, txn, C_ZONE, key1_name, dname, dname_size, &val);
        switch (val.code) {
        case KNOT_EOK:
+               if (val.blob_len == 1 && (val.item->flags & CONF_REF_EMPTY)) {
+                       static const conf_val_t empty = { .code = KNOT_ENOENT };
+                       return empty;
+               }
                return val;
        default:
                CONF_LOG_ZONE(LOG_ERR, dname, "failed to read '%s/%s' (%s)",
index 91366a6bb028bcfb88ca0fa255254eb4fef3f0f2..f79a284ef2e81c233b6869551d6f3d50c2b5a603 100644 (file)
@@ -32,6 +32,7 @@
 #define CONF_IO_FRLD_MOD       YP_FUSR8  /*!< Reload global modules. */
 #define CONF_IO_FRLD_ZONE      YP_FUSR9  /*!< Reload a specific zone. */
 #define CONF_IO_FRLD_ZONES     YP_FUSR10 /*!< Reload all zones. */
+#define CONF_REF_EMPTY         YP_FUSR11 /*!< Allow empty reference value for zone item. */
 #define CONF_IO_FRLD_ALL       (CONF_IO_FRLD_SRV | CONF_IO_FRLD_LOG | \
                                 CONF_IO_FRLD_MOD | CONF_IO_FRLD_ZONES)
 
index b606e40400477fc2a1be85cfc6eb145cf4c8a899..f31b5b3ef06bb8a75292861792cbfb7661abe7f9 100644 (file)
@@ -454,9 +454,11 @@ static const yp_item_t desc_policy[] = {
 #define ZONE_ITEMS(FLAGS) \
        { C_STORAGE,             YP_TSTR,  YP_VSTR = { STORAGE_DIR }, FLAGS }, \
        { C_FILE,                YP_TSTR,  YP_VNONE, FLAGS }, \
-       { C_MASTER,              YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI, { check_ref } }, \
+       { C_MASTER,              YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY, \
+                                          { check_ref } }, \
        { C_DDNS_MASTER,         YP_TREF,  YP_VREF = { C_RMT }, YP_FNONE, { check_ref_empty } }, \
-       { C_NOTIFY,              YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI, { check_ref } }, \
+       { C_NOTIFY,              YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY, \
+                                          { check_ref } }, \
        { C_ACL,                 YP_TREF,  YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \
        { C_MASTER_PIN_TOL,      YP_TINT,  YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } }, \
        { C_PROVIDE_IXFR,        YP_TBOOL, YP_VBOOL = { true } }, \
@@ -474,7 +476,7 @@ static const yp_item_t desc_policy[] = {
        { C_DNSSEC_SIGNING,      YP_TBOOL, YP_VNONE, FLAGS }, \
        { C_DNSSEC_VALIDATION,   YP_TBOOL, YP_VNONE, FLAGS }, \
        { C_DNSSEC_POLICY,       YP_TREF,  YP_VREF = { C_POLICY }, FLAGS, { check_ref_dflt } }, \
-       { C_DS_PUSH,             YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | FLAGS, \
+       { C_DS_PUSH,             YP_TREF,  YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY | FLAGS, \
                                           { check_ref } }, \
        { C_REVERSE_GEN,         YP_TDNAME,YP_VNONE, FLAGS | CONF_IO_FRLD_ZONES }, \
        { C_SERIAL_POLICY,       YP_TOPT,  YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \
index c822621cd4f56271a14e471bef1e00825ea6de72..1ea8446a3de20f9b95cad1890e31658fb4eaee68 100644 (file)
@@ -236,6 +236,13 @@ int check_ref(
 
        bool found1 = false, found2 = false;
 
+       // Check if allowed empty value for specific zone items.
+       if (args->data_len == 1 && (args->item->flags & CONF_REF_EMPTY) &&
+           args->item->parent->name[0] == C_ZONE[0] &&
+           memcmp(&args->item->parent->name[1], &C_ZONE[1], C_ZONE[0]) == 0) {
+               return KNOT_EOK;
+       }
+
        // Try to find the id in the first section.
        found1 = conf_rawid_exists_txn(args->extra->conf, args->extra->txn,
                                       ref->name, args->data, args->data_len);
diff --git a/tests-extra/tests/config/template/test.py b/tests-extra/tests/config/template/test.py
new file mode 100644 (file)
index 0000000..d99801d
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+
+'''Test for configuration zone templates'''
+
+import os
+
+from dnstest.libknot import libknot
+from dnstest.test import Test
+
+t = Test()
+
+master = t.server("knot")
+slave = t.server("knot")
+zones = t.zone_rnd(2, records=5, dnssec=False)
+for z in zones:
+    z.name = z.name.lower()
+
+t.link(zones, master, slave, ixfr=True)
+
+ctl = libknot.control.KnotCtl()
+
+t.start()
+
+serials_init = master.zones_wait(zones)
+slave.zones_wait(zones)
+
+ctl.connect(os.path.join(master.dir, "knot.sock"))
+ctl.send_block(cmd="conf-begin")
+resp = ctl.receive_block()
+
+# Move notify setting from zones to the default template.
+ctl.send_block(cmd="conf-get", section="zone", item="notify", identifier=zones[0].name)
+resp = ctl.receive_block()
+for val in resp['zone'][zones[0].name]['notify']:
+    ctl.send_block(cmd="conf-set", section="template", identifier="default", item="notify", data=val)
+    resp = ctl.receive_block()
+ctl.send_block(cmd="conf-unset", section="zone", item="notify")
+resp = ctl.receive_block()
+
+# Override template setting with the default (none) for the first zone.
+ctl.send_block(cmd="conf-set", section="zone", item="notify", identifier=zones[0].name, data="")
+resp = ctl.receive_block()
+
+ctl.send_block(cmd="conf-commit")
+resp = ctl.receive_block()
+ctl.send(libknot.control.KnotCtlType.END)
+ctl.close()
+
+# Modify the zones and check that notify doesn't work for the first zone.
+serials_prev = serials_init
+serial1 = serials_init[zones[0].name]
+for i in range(2):
+    for zone in zones:
+        master.update_zonefile(zone, random=True)
+    master.ctl('zone-reload')
+
+    serials_prev = master.zones_wait(zones, serials_prev)
+    slave.zone_wait(zones[1], serials_prev[zones[1].name], equal=True, greater=False)
+    t.sleep(1)
+    slave.zone_wait(zones[0], serial1, equal=True, greater=False)
+
+t.end()