|
| 1 | +From c02b7ded63778466911c47f821ea594cc98ce234 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Mark Andrews < [email protected]> |
| 3 | +Date: Tue, 2 Dec 2025 11:02:34 +1100 |
| 4 | +Subject: [PATCH 1/3] Allow rndc addzone to replace automatic empty zones |
| 5 | + |
| 6 | +Check if the found zone is an automatic zone and if so remove it |
| 7 | +from the view prior to adding the new zone. If the addzone fails |
| 8 | +restore the automatic zone to the view. |
| 9 | +--- |
| 10 | + bin/named/server.c | 34 +++++++++++++++++++++++++++++++++- |
| 11 | + lib/dns/view.c | 4 +++- |
| 12 | + 2 files changed, 36 insertions(+), 2 deletions(-) |
| 13 | + |
| 14 | +--- a/bin/named/server.c |
| 15 | ++++ b/bin/named/server.c |
| 16 | +@@ -13979,6 +13979,7 @@ do_addzone(named_server_t *server, ns_cf |
| 17 | + bool redirect, isc_buffer_t **text) { |
| 18 | + isc_result_t result, tresult; |
| 19 | + dns_zone_t *zone = NULL; |
| 20 | ++ dns_zone_t *oldzone = NULL; |
| 21 | + #ifndef HAVE_LMDB |
| 22 | + FILE *fp = NULL; |
| 23 | + bool cleanup_config = false; |
| 24 | +@@ -13997,7 +13998,13 @@ do_addzone(named_server_t *server, ns_cf |
| 25 | + } else { |
| 26 | + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); |
| 27 | + if (result == ISC_R_SUCCESS) { |
| 28 | +- result = ISC_R_EXISTS; |
| 29 | ++ if (dns_zone_getautomatic(zone)) { |
| 30 | ++ oldzone = zone; |
| 31 | ++ zone = NULL; |
| 32 | ++ result = ISC_R_NOTFOUND; |
| 33 | ++ } else { |
| 34 | ++ result = ISC_R_EXISTS; |
| 35 | ++ } |
| 36 | + } |
| 37 | + } |
| 38 | + if (result != ISC_R_NOTFOUND) { |
| 39 | +@@ -14006,6 +14013,10 @@ do_addzone(named_server_t *server, ns_cf |
| 40 | + |
| 41 | + isc_loopmgr_pause(named_g_loopmgr); |
| 42 | + |
| 43 | ++ if (oldzone != NULL) { |
| 44 | ++ dns_view_delzone(view, oldzone); |
| 45 | ++ } |
| 46 | ++ |
| 47 | + #ifndef HAVE_LMDB |
| 48 | + /* |
| 49 | + * Make sure we can open the configuration save file |
| 50 | +@@ -14110,6 +14121,11 @@ do_addzone(named_server_t *server, ns_cf |
| 51 | + /* Remove the zone from the zone table */ |
| 52 | + dns_view_delzone(view, zone); |
| 53 | + goto cleanup; |
| 54 | ++ } else if (oldzone != NULL) { |
| 55 | ++ /* |
| 56 | ++ * We no longer need to keep the old zone around. |
| 57 | ++ */ |
| 58 | ++ dns_zone_detach(&oldzone); |
| 59 | + } |
| 60 | + |
| 61 | + /* Flag the zone as having been added at runtime */ |
| 62 | +@@ -14126,6 +14142,22 @@ do_addzone(named_server_t *server, ns_cf |
| 63 | + |
| 64 | + cleanup: |
| 65 | + |
| 66 | ++ if (oldzone != NULL) { |
| 67 | ++ /* |
| 68 | ++ * Restore the old zone. |
| 69 | ++ */ |
| 70 | ++ dns_view_thaw(view); |
| 71 | ++ tresult = dns_view_addzone(view, oldzone); |
| 72 | ++ dns_view_freeze(view); |
| 73 | ++ dns_zone_detach(&oldzone); |
| 74 | ++ |
| 75 | ++ if (tresult != ISC_R_SUCCESS && tresult != ISC_R_SHUTTINGDOWN) { |
| 76 | ++ TCHECK(putstr(text, "\nUnable to restore automatic " |
| 77 | ++ "empty zone: ")); |
| 78 | ++ TCHECK(putstr(text, isc_result_totext(result))); |
| 79 | ++ } |
| 80 | ++ } |
| 81 | ++ |
| 82 | + #ifndef HAVE_LMDB |
| 83 | + if (fp != NULL) { |
| 84 | + (void)isc_stdio_close(fp); |
| 85 | +--- a/lib/dns/view.c |
| 86 | ++++ b/lib/dns/view.c |
| 87 | +@@ -785,7 +785,9 @@ dns_view_delzone(dns_view_t *view, dns_z |
| 88 | + |
| 89 | + REQUIRE(DNS_VIEW_VALID(view)); |
| 90 | + |
| 91 | +- dns_zone_prepare_shutdown(zone); |
| 92 | ++ if (!dns_zone_getautomatic(zone)) { |
| 93 | ++ dns_zone_prepare_shutdown(zone); |
| 94 | ++ } |
| 95 | + |
| 96 | + rcu_read_lock(); |
| 97 | + zonetable = rcu_dereference(view->zonetable); |
| 98 | +--- /dev/null |
| 99 | ++++ b/bin/tests/system/addzone/ns6/added.db |
| 100 | +@@ -0,0 +1,25 @@ |
| 101 | ++; Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
| 102 | ++; |
| 103 | ++; SPDX-License-Identifier: MPL-2.0 |
| 104 | ++; |
| 105 | ++; This Source Code Form is subject to the terms of the Mozilla Public |
| 106 | ++; License, v. 2.0. If a copy of the MPL was not distributed with this |
| 107 | ++; file, you can obtain one at https://mozilla.org/MPL/2.0/. |
| 108 | ++; |
| 109 | ++; See the COPYRIGHT file distributed with this work for additional |
| 110 | ++; information regarding copyright ownership. |
| 111 | ++ |
| 112 | ++$TTL 300 ; 5 minutes |
| 113 | ++@ IN SOA mname1. . ( |
| 114 | ++ 1 ; serial |
| 115 | ++ 20 ; refresh (20 seconds) |
| 116 | ++ 20 ; retry (20 seconds) |
| 117 | ++ 1814400 ; expire (3 weeks) |
| 118 | ++ 3600 ; minimum (1 hour) |
| 119 | ++ ) |
| 120 | ++ NS ns2 |
| 121 | ++ns2 A 10.53.0.2 |
| 122 | ++ MX 10 mail |
| 123 | ++ |
| 124 | ++a A 10.0.0.1 |
| 125 | ++mail A 10.0.0.2 |
| 126 | +--- /dev/null |
| 127 | ++++ b/bin/tests/system/addzone/ns6/named.conf.in |
| 128 | +@@ -0,0 +1,40 @@ |
| 129 | ++/* |
| 130 | ++ * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
| 131 | ++ * |
| 132 | ++ * SPDX-License-Identifier: MPL-2.0 |
| 133 | ++ * |
| 134 | ++ * This Source Code Form is subject to the terms of the Mozilla Public |
| 135 | ++ * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 136 | ++ * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
| 137 | ++ * |
| 138 | ++ * See the COPYRIGHT file distributed with this work for additional |
| 139 | ++ * information regarding copyright ownership. |
| 140 | ++ */ |
| 141 | ++ |
| 142 | ++options { |
| 143 | ++ port @PORT@; |
| 144 | ++ pid-file "named.pid"; |
| 145 | ++ listen-on { 10.53.0.6; }; |
| 146 | ++ listen-on-v6 { none; }; |
| 147 | ++ allow-query { any; }; |
| 148 | ++ recursion yes; |
| 149 | ++ allow-new-zones yes; |
| 150 | ++ dnssec-validation no; |
| 151 | ++}; |
| 152 | ++ |
| 153 | ++include "../../_common/rndc.key"; |
| 154 | ++ |
| 155 | ++controls { |
| 156 | ++ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; |
| 157 | ++}; |
| 158 | ++ |
| 159 | ++template primary { |
| 160 | ++ type primary; |
| 161 | ++ file "$view-$name.db"; |
| 162 | ++ initial-file "added.db"; |
| 163 | ++}; |
| 164 | ++ |
| 165 | ++zone "." { |
| 166 | ++ type hint; |
| 167 | ++ file "../../_common/root.hint"; |
| 168 | ++}; |
| 169 | +--- a/bin/tests/system/addzone/setup.sh |
| 170 | ++++ b/bin/tests/system/addzone/setup.sh |
| 171 | +@@ -20,6 +20,7 @@ cp -f ns3/redirect.db.1 ns3/redirect.db |
| 172 | + copy_setports ns1/named.conf.in ns1/named.conf |
| 173 | + copy_setports ns2/named1.conf.in ns2/named.conf |
| 174 | + copy_setports ns3/named1.conf.in ns3/named.conf |
| 175 | ++copy_setports ns6/named.conf.in ns6/named.conf |
| 176 | + |
| 177 | + cp -f ns2/default.nzf.in ns2/3bf305731dd26307.nzf |
| 178 | + mkdir ns2/new-zones |
| 179 | +--- a/bin/tests/system/addzone/tests.sh |
| 180 | ++++ b/bin/tests/system/addzone/tests.sh |
| 181 | +@@ -68,6 +68,35 @@ n=$((n + 1)) |
| 182 | + if [ $ret != 0 ]; then echo_i "failed"; fi |
| 183 | + status=$((status + ret)) |
| 184 | + |
| 185 | ++echo_i "adding new zone which replaces an automatic empty zone ($n)" |
| 186 | ++ret=0 |
| 187 | ++$DIG $DIGOPTS @10.53.0.6 168.192.in-addr.arpa SOA >dig.out.pre.$n || ret=1 |
| 188 | ++grep 'status: NOERROR' dig.out.pre.$n >/dev/null || ret=1 |
| 189 | ++grep '168\.192\.in-addr\.arpa\..86400.IN.SOA.168\.192\.IN-ADDR\.ARPA\. \. 0 28800 7200 604800 86400' dig.out.pre.$n >/dev/null || ret=1 |
| 190 | ++$RNDCCMD 10.53.0.6 addzone '168.192.in-addr.arpa { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns6 /' |
| 191 | ++_check_adding_new_zone() ( |
| 192 | ++ $DIG $DIGOPTS @10.53.0.6 a.168.192.in-addr.arpa a >dig.out.ns6.$n \ |
| 193 | ++ && grep 'status: NOERROR' dig.out.ns6.$n >/dev/null \ |
| 194 | ++ && grep '^a.168.192.in-addr.arpa' dig.out.ns6.$n >/dev/null |
| 195 | ++) |
| 196 | ++retry_quiet 10 _check_adding_new_zone || ret=1 |
| 197 | ++n=$((n + 1)) |
| 198 | ++if [ $ret != 0 ]; then echo_i "failed"; fi |
| 199 | ++status=$((status + ret)) |
| 200 | ++ |
| 201 | ++echo_i "adding new zone which replaces an automatic empty zone with bad file ($n)" |
| 202 | ++ret=0 |
| 203 | ++$DIG $DIGOPTS @10.53.0.6 10.in-addr.arpa SOA >dig.out.pre.$n || ret=1 |
| 204 | ++grep 'status: NOERROR' dig.out.pre.$n >/dev/null || ret=1 |
| 205 | ++grep '10\.in-addr\.arpa\..86400.IN.SOA.10\.IN-ADDR\.ARPA\. \. 0 28800 7200 604800 86400' dig.out.pre.$n >/dev/null || ret=1 |
| 206 | ++$RNDCCMD 10.53.0.6 addzone '10.in-addr.arpa { type primary; file "bad.db"; };' 2>&1 | sed 's/^/I:ns6 /' |
| 207 | ++$DIG $DIGOPTS @10.53.0.6 10.in-addr.arpa SOA >dig.out.post.$n || ret=1 |
| 208 | ++grep 'status: NOERROR' dig.out.post.$n >/dev/null || ret=1 |
| 209 | ++grep '10\.in-addr\.arpa\..86400.IN.SOA.10\.IN-ADDR\.ARPA\. \. 0 28800 7200 604800 86400' dig.out.post.$n >/dev/null || ret=1 |
| 210 | ++n=$((n + 1)) |
| 211 | ++if [ $ret != 0 ]; then echo_i "failed"; fi |
| 212 | ++status=$((status + ret)) |
| 213 | ++ |
| 214 | + nextpart ns2/named.run >/dev/null |
| 215 | + echo_i "checking addzone errors are logged correctly" |
| 216 | + ret=0 |
| 217 | +--- a/bin/rndc/rndc.rst |
| 218 | ++++ b/bin/rndc/rndc.rst |
| 219 | +@@ -128,19 +128,20 @@ Currently supported commands are: |
| 220 | + |
| 221 | + .. option:: addzone zone [class [view]] configuration |
| 222 | + |
| 223 | +- This command adds a zone while the server is running. This command requires the |
| 224 | +- ``allow-new-zones`` option to be set to ``yes``. The configuration |
| 225 | +- string specified on the command line is the zone configuration text |
| 226 | +- that would ordinarily be placed in :iscman:`named.conf`. |
| 227 | ++ This command adds a zone while the server is running. This command |
| 228 | ++ requires the ``allow-new-zones`` option to be set to ``yes``. |
| 229 | ++ The configuration string specified on the command line is the |
| 230 | ++ zone configuration text that would ordinarily be placed in |
| 231 | ++ :iscman:`named.conf`. Automatic empty zones will be replaced. |
| 232 | + |
| 233 | +- The configuration is saved in a file called ``viewname.nzf`` (or, if |
| 234 | +- :iscman:`named` is compiled with liblmdb, an LMDB database file called |
| 235 | +- ``viewname.nzd``). ``viewname`` is the name of the view, unless the view |
| 236 | +- name contains characters that are incompatible with use as a file |
| 237 | +- name, in which case a cryptographic hash of the view name is used |
| 238 | +- instead. When :iscman:`named` is restarted, the file is loaded into |
| 239 | +- the view configuration so that zones that were added can persist |
| 240 | +- after a restart. |
| 241 | ++ The configuration is saved in a file called ``viewname.nzf`` |
| 242 | ++ (or, if :iscman:`named` is compiled with liblmdb, an LMDB database |
| 243 | ++ file called ``viewname.nzd``). ``viewname`` is the name of the |
| 244 | ++ view, unless the view name contains characters that are incompatible |
| 245 | ++ with use as a file name, in which case a cryptographic hash of |
| 246 | ++ the view name is used instead. When :iscman:`named` is restarted, |
| 247 | ++ the file is loaded into the view configuration so that zones |
| 248 | ++ that were added can persist after a restart. |
| 249 | + |
| 250 | + This sample ``addzone`` command adds the zone ``example.com`` to |
| 251 | + the default view: |
0 commit comments