bind: backport patch replace automatic empty zones

The RFC-1918 zones are automatically synthesized locally by bind
to avoid forwarding queries about them to root nameservers.  As
a result, we can't easily replace them with rndc addzone on the
fly.  We need this for DHCP integration.

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
This commit is contained in:
Philip Prindeville
2025-12-10 14:50:48 -07:00
committed by Noah Meyerhans
parent 09c148177a
commit 505ca0a0d4
5 changed files with 299 additions and 1 deletions

View File

@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=bind
PKG_VERSION:=9.20.18
PKG_RELEASE:=1
PKG_RELEASE:=2
USERID:=bind=57:bind=57
PKG_MAINTAINER:=Noah Meyerhans <frodo@morgul.net>

View File

@@ -0,0 +1,97 @@
From 6e1450ef0f9d66679587092cef2e83e6deb1575f Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Tue, 2 Dec 2025 11:02:34 +1100
Subject: [PATCH 1/4] Allow rndc addzone to replace automatic empty zones
Check if the found zone is an automatic zone and if so remove it
from the view prior to adding the new zone. If the addzone fails
restore the automatic zone to the view.
---
bin/named/server.c | 34 +++++++++++++++++++++++++++++++++-
lib/dns/view.c | 4 +++-
2 files changed, 36 insertions(+), 2 deletions(-)
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -13946,6 +13946,7 @@ do_addzone(named_server_t *server, ns_cf
bool redirect, isc_buffer_t **text) {
isc_result_t result, tresult;
dns_zone_t *zone = NULL;
+ dns_zone_t *oldzone = NULL;
#ifndef HAVE_LMDB
FILE *fp = NULL;
bool cleanup_config = false;
@@ -13964,7 +13965,13 @@ do_addzone(named_server_t *server, ns_cf
} else {
result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone);
if (result == ISC_R_SUCCESS) {
- result = ISC_R_EXISTS;
+ if (dns_zone_getautomatic(zone)) {
+ oldzone = zone;
+ zone = NULL;
+ result = ISC_R_NOTFOUND;
+ } else {
+ result = ISC_R_EXISTS;
+ }
}
}
if (result != ISC_R_NOTFOUND) {
@@ -13973,6 +13980,10 @@ do_addzone(named_server_t *server, ns_cf
isc_loopmgr_pause(named_g_loopmgr);
+ if (oldzone != NULL) {
+ dns_view_delzone(view, oldzone);
+ }
+
#ifndef HAVE_LMDB
/*
* Make sure we can open the configuration save file
@@ -14077,6 +14088,11 @@ do_addzone(named_server_t *server, ns_cf
/* Remove the zone from the zone table */
dns_view_delzone(view, zone);
goto cleanup;
+ } else if (oldzone != NULL) {
+ /*
+ * We no longer need to keep the old zone around.
+ */
+ dns_zone_detach(&oldzone);
}
/* Flag the zone as having been added at runtime */
@@ -14093,6 +14109,22 @@ do_addzone(named_server_t *server, ns_cf
cleanup:
+ if (oldzone != NULL) {
+ /*
+ * Restore the old zone.
+ */
+ dns_view_thaw(view);
+ tresult = dns_view_addzone(view, oldzone);
+ dns_view_freeze(view);
+ dns_zone_detach(&oldzone);
+
+ if (tresult != ISC_R_SUCCESS && tresult != ISC_R_SHUTTINGDOWN) {
+ TCHECK(putstr(text, "\nUnable to restore automatic "
+ "empty zone: "));
+ TCHECK(putstr(text, isc_result_totext(result)));
+ }
+ }
+
#ifndef HAVE_LMDB
if (fp != NULL) {
(void)isc_stdio_close(fp);
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -778,7 +778,9 @@ dns_view_delzone(dns_view_t *view, dns_z
REQUIRE(DNS_VIEW_VALID(view));
- dns_zone_prepare_shutdown(zone);
+ if (!dns_zone_getautomatic(zone)) {
+ dns_zone_prepare_shutdown(zone);
+ }
rcu_read_lock();
zonetable = rcu_dereference(view->zonetable);

View File

@@ -0,0 +1,123 @@
From cb9cb3c8d9f1c8e5e6a0fb55fea8dba43ea5d529 Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Tue, 2 Dec 2025 11:05:51 +1100
Subject: [PATCH 2/4] Check if adding new zone can replace an automatic empty
zone
---
bin/tests/system/addzone/ns6/added.db | 25 ++++++++++++++
bin/tests/system/addzone/ns6/named.conf.j2 | 40 ++++++++++++++++++++++
bin/tests/system/addzone/tests.sh | 29 ++++++++++++++++
3 files changed, 94 insertions(+)
create mode 100644 bin/tests/system/addzone/ns6/added.db
create mode 100644 bin/tests/system/addzone/ns6/named.conf.j2
--- /dev/null
+++ b/bin/tests/system/addzone/ns6/added.db
@@ -0,0 +1,25 @@
+; 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.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
+ MX 10 mail
+
+a A 10.0.0.1
+mail A 10.0.0.2
--- /dev/null
+++ b/bin/tests/system/addzone/ns6/named.conf.j2
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+options {
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ allow-query { any; };
+ recursion yes;
+ allow-new-zones yes;
+ dnssec-validation no;
+};
+
+include "../../_common/rndc.key";
+
+controls {
+ inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+template primary {
+ type primary;
+ file "$view-$name.db";
+ initial-file "added.db";
+};
+
+zone "." {
+ type hint;
+ file "../../_common/root.hint";
+};
--- a/bin/tests/system/addzone/tests.sh
+++ b/bin/tests/system/addzone/tests.sh
@@ -68,6 +68,35 @@ n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
+echo_i "adding new zone which replaces an automatic empty zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 168.192.in-addr.arpa SOA >dig.out.pre.$n || ret=1
+grep 'status: NOERROR' dig.out.pre.$n >/dev/null || ret=1
+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
+$RNDCCMD 10.53.0.6 addzone '168.192.in-addr.arpa { type primary; file "added.db"; };' 2>&1 | sed 's/^/I:ns6 /'
+_check_adding_new_zone() (
+ $DIG $DIGOPTS @10.53.0.6 a.168.192.in-addr.arpa a >dig.out.ns6.$n \
+ && grep 'status: NOERROR' dig.out.ns6.$n >/dev/null \
+ && grep '^a.168.192.in-addr.arpa' dig.out.ns6.$n >/dev/null
+)
+retry_quiet 10 _check_adding_new_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+echo_i "adding new zone which replaces an automatic empty zone with bad file ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 10.in-addr.arpa SOA >dig.out.pre.$n || ret=1
+grep 'status: NOERROR' dig.out.pre.$n >/dev/null || ret=1
+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
+$RNDCCMD 10.53.0.6 addzone '10.in-addr.arpa { type primary; file "bad.db"; };' 2>&1 | sed 's/^/I:ns6 /'
+$DIG $DIGOPTS @10.53.0.6 10.in-addr.arpa SOA >dig.out.post.$n || ret=1
+grep 'status: NOERROR' dig.out.post.$n >/dev/null || ret=1
+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
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
nextpart ns2/named.run >/dev/null
echo_i "checking addzone errors are logged correctly"
ret=0

View File

@@ -0,0 +1,42 @@
From 6cea04633d2461456d30cbdd69695ca0da540b4f Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Tue, 9 Dec 2025 15:51:34 +1100
Subject: [PATCH 3/4] Document rndc addzone with automatic empty zones
---
bin/rndc/rndc.rst | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
--- a/bin/rndc/rndc.rst
+++ b/bin/rndc/rndc.rst
@@ -129,18 +129,19 @@ Currently supported commands are:
.. option:: addzone zone [class [view]] configuration
This command adds a zone while the server is running. This command
- requires the ``allow-new-zones`` option to be set to ``yes``. The
- configuration string specified on the command line is the zone
- configuration text that would ordinarily be placed in :iscman:`named.conf`.
+ requires the ``allow-new-zones`` option to be set to ``yes``.
+ The configuration string specified on the command line is the
+ zone configuration text that would ordinarily be placed in
+ :iscman:`named.conf`. Automatic empty zones will be replaced.
- The configuration is saved in a file called ``viewname.nzf`` (or, if
- :iscman:`named` is compiled with liblmdb, an LMDB database file called
- ``viewname.nzd``). ``viewname`` is the name of the view, unless the view
- name contains characters that are incompatible with use as a file
- name, in which case a cryptographic hash of the view name is used
- instead. When :iscman:`named` is restarted, the file is loaded into
- the view configuration so that zones that were added can persist
- after a restart.
+ The configuration is saved in a file called ``viewname.nzf``
+ (or, if :iscman:`named` is compiled with liblmdb, an LMDB database
+ file called ``viewname.nzd``). ``viewname`` is the name of the
+ view, unless the view name contains characters that are incompatible
+ with use as a file name, in which case a cryptographic hash of
+ the view name is used instead. When :iscman:`named` is restarted,
+ the file is loaded into the view configuration so that zones
+ that were added can persist after a restart.
This sample ``addzone`` command adds the zone ``example.com`` to
the default view:

View File

@@ -0,0 +1,36 @@
From be735c1b5e12117039ac64f802e30b075987dd22 Mon Sep 17 00:00:00 2001
From: Matthijs Mekking <matthijs@isc.org>
Date: Thu, 11 Dec 2025 15:14:55 +0100
Subject: [PATCH 4/4] fixup! Check if adding new zone can replace an automatic
empty zone
---
bin/tests/system/addzone/tests.sh | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/bin/tests/system/addzone/tests.sh
+++ b/bin/tests/system/addzone/tests.sh
@@ -84,6 +84,23 @@ n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
+echo_i "deleting zone which replaced an automatic empty zone ($n)"
+ret=0
+$DIG $DIGOPTS @10.53.0.6 a.168.192.in-addr.arpa a >dig.out.pre.$n || ret=1
+grep 'status: NOERROR' dig.out.pre.$n >/dev/null || ret=1
+grep '^a.168.192.in-addr.arpa' dig.out.pre.$n >/dev/null || ret=1
+$RNDCCMD 10.53.0.6 delzone '168.192.in-addr.arpa' 2>&1 | sed 's/^/I:ns6 /'
+_check_removing_new_zone() (
+ DIGOPTS2="+tcp +nosea +nostat +nocmd +norec +noauth +noadd +nostats +dnssec -p ${PORT}"
+ $DIG $DIGOPTS2 @10.53.0.6 168.192.in-addr.arpa SOA >dig.out.ns6.$n \
+ && grep 'status: NOERROR' dig.out.ns6.$n >/dev/null \
+ && grep '168\.192\.in-addr\.arpa\..86400.IN.SOA.168\.192\.IN-ADDR\.ARPA\. \. 0 28800 7200 604800 86400' dig.out.ns6.$n >/dev/null
+)
+retry_quiet 10 _check_removing_new_zone || ret=1
+n=$((n + 1))
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
echo_i "adding new zone which replaces an automatic empty zone with bad file ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.6 10.in-addr.arpa SOA >dig.out.pre.$n || ret=1