From fb2267ad99ee6e8b04f90d107f559397afdcce80 Mon Sep 17 00:00:00 2001 From: JINMEI Tatuya Date: Mon, 23 Mar 2026 09:58:39 -0700 Subject: [PATCH] ensure rndc modzone succeeds twice for a zone in named.conf 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). (cherry picked from commit f2115e9d58ee6584a091d697499875ff6a78a243) --- bin/named/server.c | 22 ++++++++++--------- .../addzone/tests_rndc_modzone_without_add.py | 19 ++++++++++++++++ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 21edf38377..c3c06d7d14 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -14269,9 +14269,11 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, bool added; bool exclusive = false; bool locked = false; + const cfg_obj_t *options = NULL; + cfg_obj_t *z; + cfg_obj_t *o; #ifndef HAVE_LMDB FILE *fp = NULL; - cfg_obj_t *z; #else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; @@ -14377,17 +14379,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: ")); @@ -14458,6 +14456,10 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, TCHECK(putstr(text, zname)); TCHECK(putstr(text, "' reconfigured.")); } else { + DE_CONST(zoneobj, z); + DE_CONST(options, o); + CHECK(cfg_parser_mapadd(cfg->conf_parser, o, z, "zone")); + TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zname)); TCHECK(putstr(text, "' must also be reconfigured in\n")); diff --git a/bin/tests/system/addzone/tests_rndc_modzone_without_add.py b/bin/tests/system/addzone/tests_rndc_modzone_without_add.py index 3658f5f518..b2a7335625 100644 --- a/bin/tests/system/addzone/tests_rndc_modzone_without_add.py +++ b/bin/tests/system/addzone/tests_rndc_modzone_without_add.py @@ -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