]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
ensure rndc modzone succeeds twice for a zone in named.conf
authorJINMEI Tatuya <jtatuya@infoblox.com>
Mon, 23 Mar 2026 16:58:39 +0000 (09:58 -0700)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 25 Mar 2026 08:38:16 +0000 (09:38 +0100)
If a zone is in named.conf, not originally added by rndc addzone,
rndc modzone for that zone succeeds once, but subsequent modzone
attempts fail. This is because do_modzone removes the zone config
from global or view options, but it would fail due to 'not found'
once the config is removed.

The fix is to ensure re-adding the updated zone config to the
global or view options. This also works as a more complete fix
for the issue 85453d3 atempted to solve, ensuring rndc showzone
shows the latest config: it now works for multple attemps of
modzone, and with named that is not built with LMDB.

The change in this commit relies on UNCONST in a few places.
That's not clean, but 'add/mod/delzone' generally seems to
need it (for example, delete_zoneconf uses it to modify the list
of zones). In that sense, this change follows the convention
(for a longer term, there may have to be a better API so that we
can modify config obtions that were once parsed).

bin/named/server.c
bin/tests/system/addzone/tests_rndc_modzone_without_add.py

index 95b387e34223e4013ab2bd73e616fa149a407185..ad472112e2e77662f819c45f36bd041d3a7a6288 100644 (file)
@@ -14113,6 +14113,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
        dns_zone_t *zone = NULL;
        bool added;
        bool locked = false;
+       const cfg_obj_t *options = NULL;
 #ifndef HAVE_LMDB
        FILE *fp = NULL;
        cfg_obj_t *z;
@@ -14220,17 +14221,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
 
        if (!added) {
                if (cfg->vconfig == NULL) {
-                       result = delete_zoneconf(
-                               view, cfg->conf_parser, cfg->config,
-                               dns_zone_getorigin(zone), NULL, locked);
+                       options = cfg->config;
                } else {
-                       const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig,
-                                                                 "options");
-                       result = delete_zoneconf(
-                               view, cfg->conf_parser, voptions,
-                               dns_zone_getorigin(zone), NULL, locked);
+                       options = cfg_tuple_get(cfg->vconfig, "options");
                }
-
+               result = delete_zoneconf(view, cfg->conf_parser, options,
+                                        dns_zone_getorigin(zone), NULL,
+                                        locked);
                if (result != ISC_R_SUCCESS) {
                        TCHECK(putstr(text, "former zone configuration "
                                            "not deleted: "));
@@ -14301,6 +14298,9 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
                TCHECK(putstr(text, zname));
                TCHECK(putstr(text, "' reconfigured."));
        } else {
+               CHECK(cfg_parser_mapadd(cfg->conf_parser, UNCONST(options),
+                                       UNCONST(zoneobj), "zone"));
+
                TCHECK(putstr(text, "zone '"));
                TCHECK(putstr(text, zname));
                TCHECK(putstr(text, "' must also be reconfigured in\n"));
index 3658f5f518324309bf4b380361f91f7a5f0bdff6..b2a7335625b0413d00ab7f85d39555da9f5faa91 100644 (file)
@@ -35,3 +35,22 @@ def test_rndc_modzone_without_add(ns3):
         raise_on_exception=False,
     )
     assert cmd.rc == 0
+
+    # Confirm that the modzone took effect in 'rndc showzone'.
+    cmd = ns3.rndc("showzone .", raise_on_exception=False)
+    assert cmd.rc == 0
+    assert 'allow-query { "none"; }' in cmd.out
+
+    # Confirm that 'rndc modzone' still works after the first modzone.
+    # This was not the case before as the zone config was incorrectly
+    # removed in-memory after the first modzone.
+    cmd = ns3.rndc(
+        'modzone . {type primary; file "redirect.db"; allow-query {any;};};',
+        raise_on_exception=False,
+    )
+    assert cmd.rc == 0
+
+    # Confirm that the second modzone took effect in 'rndc showzone'.
+    cmd = ns3.rndc("showzone .", raise_on_exception=False)
+    assert cmd.rc == 0
+    assert 'allow-query { "any"; }' in cmd.out