Commit 821a497d55 for bind
commit 821a497d55449d62e013713eaf1019a04c7fd605
Author: Alessio Podda <alessio@isc.org>
Date: Sat Sep 12 01:21:32 2026 +0200
Do not link zones into the zonemgr
Previously zones were part of a linked list owned by the zonemgr
that was used to print statistics. This commit instead walks the
view list and the zone table for each view.
As a side effect, it also makes the zonemgr explicitely a global
singleton. Previously, only one instance existed but it was
reference counted.
diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
index 3268779d63..5f6bafa432 100644
--- a/bin/named/include/named/server.h
+++ b/bin/named/include/named/server.h
@@ -128,6 +128,15 @@ named_server_destroy(named_server_t **serverp);
* Destroy a server object, freeing its memory.
*/
+isc_result_t
+named_server_applyzones(named_server_t *server,
+ isc_result_t (*action)(dns_zone_t *, void *),
+ void *arg);
+/*%<
+ * Apply 'action' to every active zone owned by the server's current views,
+ * including raw, managed-keys, and redirect zones.
+ */
+
void
named_server_reloadwanted(void *arg, int signum);
/*%<
diff --git a/bin/named/server.c b/bin/named/server.c
index 8e53d71e85..5122ec96a6 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -1735,7 +1735,6 @@ dlzconfigure_callback(dns_view_t *view, dns_dlzdb_t *dlzdb, dns_zone_t *zone) {
dns_rdataclass_t zclass = view->rdclass;
dns_zone_setclass(zone, zclass);
- RETERR(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
dns_zone_setstats(zone, named_g_server->zonestats);
@@ -1791,10 +1790,9 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
isc_buffer_constinit(&b, reverse, strlen(reverse));
isc_buffer_add(&b, strlen(reverse));
CHECK(dns_name_fromtext(name, &b, dns_rootname, 0));
- dns_zone_create(&zone, mctx, 0);
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
dns_zone_setorigin(zone, name);
dns_zone_setview(zone, view);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
dns_zone_setclass(zone, view->rdclass);
dns_zone_settype(zone, dns_zone_primary);
dns_zone_setstats(zone, named_g_server->zonestats);
@@ -3166,7 +3164,6 @@ create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
if (pzone == NULL) {
CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
dns_zone_setorigin(zone, name);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
if (db == NULL) {
dns_zone_setdbtype(zone, empty_dbtypec, empty_dbtype);
}
@@ -3237,7 +3234,7 @@ cleanup:
static isc_result_t
create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view,
- const dns_name_t *name, const char *type, isc_mem_t *mctx,
+ const dns_name_t *name, const char *type,
const char *server, const char *contact) {
char namebuf[DNS_NAME_FORMATSIZE];
const char *dbtype[4] = { "_builtin", NULL, "@", "." };
@@ -3273,9 +3270,8 @@ create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view,
/*
* Create the actual zone.
*/
- dns_zone_create(&zone, mctx, 0);
+ CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
dns_zone_setorigin(zone, name);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
dns_zone_setclass(zone, view->rdclass);
dns_zone_settype(zone, dns_zone_primary);
dns_zone_setstats(zone, named_g_server->zonestats);
@@ -5371,7 +5367,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
CHECK(create_ipv4only_zone(zone, view, name,
zones[ipv4only_zone].type,
- mctx, server, contact));
+ server, contact));
if (zone != NULL) {
dns_zone_detach(&zone);
}
@@ -6124,8 +6120,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
&zone));
dns_zone_setorigin(zone, origin);
dns_zone_setview(zone, view);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr,
- zone));
dns_zone_setstats(zone, named_g_server->zonestats);
}
CHECK(named_zone_configure(config, vconfig, zconfig, aclctx,
@@ -6226,7 +6220,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
dns_zone_setorigin(zone, origin);
dns_zone_setview(zone, view);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
dns_zone_setstats(zone, named_g_server->zonestats);
}
if (rpz_num != DNS_RPZ_INVALID_NUM) {
@@ -6403,8 +6396,6 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
dns_zone_settype(zone, dns_zone_key);
dns_zone_setclass(zone, view->rdclass);
- CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
-
dns_acl_none(mctx, &none);
dns_zone_setqueryacl(zone, none);
dns_zone_setqueryonacl(zone, none);
@@ -8995,6 +8986,9 @@ cleanup:
return result;
}
+static isc_result_t
+force_zone_maintenance(dns_zone_t *zone, void *arg);
+
static void
destroy_zoneload(zoneload_t *zl) {
isc_result_t result;
@@ -9040,8 +9034,10 @@ destroy_zoneload(zoneload_t *zl) {
* so that we know when we need to force AXFR of
* secondary zones whose master files are missing.
*/
- CHECKFATAL(dns_zonemgr_forcemaint(server->zonemgr),
- "forcing zone maintenance");
+ CHECKFATAL(
+ named_server_applyzones(server, force_zone_maintenance, NULL),
+ "forcing zone maintenance");
+ dns_zonemgr_resumexfrs(server->zonemgr);
named_os_started();
@@ -9059,6 +9055,100 @@ destroy_zoneload(zoneload_t *zl) {
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
ISC_LOG_NOTICE, "running");
}
+
+typedef struct applyzones_arg {
+ dns_view_t *view;
+ dns_zone_t *managed_keys;
+ dns_zone_t *redirect;
+ isc_result_t (*action)(dns_zone_t *, void *);
+ void *arg;
+} applyzones_arg_t;
+
+static isc_result_t
+apply_zone_and_raw(dns_zone_t *zone, applyzones_arg_t *aza) {
+ dns_zone_t *raw = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ RETERR(aza->action(zone, aza->arg));
+
+ dns_zone_getraw(zone, &raw);
+ if (raw != NULL) {
+ result = aza->action(raw, aza->arg);
+ dns_zone_detach(&raw);
+ }
+ return result;
+}
+
+static isc_result_t
+apply_view_zone(dns_zone_t *zone, void *arg) {
+ applyzones_arg_t *aza = arg;
+
+ /* In-view zones may also be mounted in another view's table. */
+ if (dns_zone_getview(zone) != aza->view || zone == aza->managed_keys ||
+ zone == aza->redirect)
+ {
+ return ISC_R_SUCCESS;
+ }
+
+ return apply_zone_and_raw(zone, aza);
+}
+
+isc_result_t
+named_server_applyzones(named_server_t *server,
+ isc_result_t (*action)(dns_zone_t *, void *),
+ void *arg) {
+ REQUIRE(NAMED_SERVER_VALID(server));
+ REQUIRE(action != NULL);
+
+ ISC_LIST_FOREACH(server->viewlist, view, link) {
+ applyzones_arg_t aza = {
+ .view = view,
+ .managed_keys = view->managed_keys,
+ .redirect = view->redirect,
+ .action = action,
+ .arg = arg,
+ };
+ RETERR(dns_view_apply(view, true, NULL, apply_view_zone, &aza));
+ if (view->managed_keys != NULL &&
+ dns_zone_getview(view->managed_keys) == view)
+ {
+ RETERR(apply_zone_and_raw(view->managed_keys, &aza));
+ }
+ if (view->redirect != NULL &&
+ dns_zone_getview(view->redirect) == view &&
+ view->redirect != view->managed_keys)
+ {
+ RETERR(apply_zone_and_raw(view->redirect, &aza));
+ }
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+typedef struct zonecounts {
+ unsigned int any;
+ unsigned int xferfirstrefresh;
+ unsigned int soaquery;
+ unsigned int automatic;
+} zonecounts_t;
+
+static isc_result_t
+count_zone_states(dns_zone_t *zone, void *arg) {
+ zonecounts_t *counts = arg;
+
+ counts->any += dns_zone_getcount(zone, DNS_ZONESTATE_ANY);
+ counts->xferfirstrefresh +=
+ dns_zone_getcount(zone, DNS_ZONESTATE_XFERFIRSTREFRESH);
+ counts->soaquery += dns_zone_getcount(zone, DNS_ZONESTATE_SOAQUERY);
+ counts->automatic += dns_zone_getcount(zone, DNS_ZONESTATE_AUTOMATIC);
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+force_zone_maintenance(dns_zone_t *zone, void *arg ISC_ATTR_UNUSED) {
+ dns_zone_forcemaint(zone);
+ return ISC_R_SUCCESS;
+}
ISC_REFCOUNT_STATIC_IMPL(zoneload, destroy_zoneload);
static isc_result_t
@@ -9573,7 +9663,8 @@ named_server_destroy(named_server_t **serverp) {
clearhostname(server);
if (server->zonemgr != NULL) {
- dns_zonemgr_detach(&server->zonemgr);
+ /* All zone activity has drained before server destruction. */
+ dns_zonemgr_destroy(&server->zonemgr);
}
INSIST(ISC_LIST_EMPTY(server->kasplist));
@@ -11625,6 +11716,7 @@ named_server_status(named_server_t *server, isc_buffer_t *text) {
char configtime[ISC_FORMATHTTPTIMESTAMP_SIZE];
char line[1024], hostname[256];
named_reload_t reload_status;
+ zonecounts_t zonecounts = { 0 };
REQUIRE(text != NULL);
@@ -11637,17 +11729,15 @@ named_server_status(named_server_t *server, isc_buffer_t *text) {
alt = (char *)named_g_server->version.base;
}
}
- zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
+ CHECK(named_server_applyzones(server, count_zone_states, &zonecounts));
+ zonecount = zonecounts.any;
xferrunning = dns_zonemgr_getcount(server->zonemgr,
DNS_ZONESTATE_XFERRUNNING);
xferdeferred = dns_zonemgr_getcount(server->zonemgr,
DNS_ZONESTATE_XFERDEFERRED);
- xferfirstrefresh = dns_zonemgr_getcount(server->zonemgr,
- DNS_ZONESTATE_XFERFIRSTREFRESH);
- soaqueries = dns_zonemgr_getcount(server->zonemgr,
- DNS_ZONESTATE_SOAQUERY);
- automatic = dns_zonemgr_getcount(server->zonemgr,
- DNS_ZONESTATE_AUTOMATIC);
+ xferfirstrefresh = zonecounts.xferfirstrefresh;
+ soaqueries = zonecounts.soaquery;
+ automatic = zonecounts.automatic;
isc_time_formathttptimestamp(&named_g_boottime, boottime,
sizeof(boottime));
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
index f5a05e7e24..ea1a1ecb92 100644
--- a/bin/named/statschannel.c
+++ b/bin/named/statschannel.c
@@ -4133,17 +4133,66 @@ named_statschannels_shutdown(named_server_t *server) {
}
}
+static isc_result_t
+dump_zone_query_stats(dns_zone_t *zone, void *arg) {
+ FILE *fp = arg;
+ isc_stats_t *zonestats;
+ dns_view_t *view;
+ char zonename[DNS_NAME_FORMATSIZE];
+ uint64_t values[ns_statscounter_max];
+
+ if (dns_zone_getstatlevel(zone) != dns_zonestat_full ||
+ (zonestats = dns_zone_getrequeststats(zone)) == NULL ||
+ (view = dns_zone_getview(zone)) == NULL)
+ {
+ return ISC_R_SUCCESS;
+ }
+ dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
+ fprintf(fp, "[%s", zonename);
+ if (strcmp(view->name, "_default") != 0) {
+ fprintf(fp, " (view: %s)", view->name);
+ }
+ fprintf(fp, "]\n");
+ (void)dump_stats(zonestats, isc_statsformat_file, fp, NULL,
+ nsstats_desc, ns_statscounter_max, nsstats_index,
+ values, 0);
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+dump_zone_glue_stats(dns_zone_t *zone, void *arg) {
+ FILE *fp = arg;
+ isc_stats_t *gluecachestats;
+ dns_view_t *view;
+ char zonename[DNS_NAME_FORMATSIZE];
+ uint64_t values[dns_gluecachestatscounter_max];
+
+ if (dns_zone_getstatlevel(zone) != dns_zonestat_full ||
+ (gluecachestats = dns_zone_getgluecachestats(zone)) == NULL ||
+ (view = dns_zone_getview(zone)) == NULL)
+ {
+ return ISC_R_SUCCESS;
+ }
+ dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
+ fprintf(fp, "[%s", zonename);
+ if (strcmp(view->name, "_default") != 0) {
+ fprintf(fp, " (view: %s)", view->name);
+ }
+ fprintf(fp, "]\n");
+ (void)dump_stats(gluecachestats, isc_statsformat_file, fp, NULL,
+ gluecachestats_desc, dns_gluecachestatscounter_max,
+ gluecachestats_index, values, 0);
+ return ISC_R_SUCCESS;
+}
+
isc_result_t
named_stats_dump(named_server_t *server, FILE *fp) {
- isc_result_t result;
- dns_zone_t *zone, *next;
stats_dumparg_t dumparg;
uint64_t nsstat_values[ns_statscounter_max];
uint64_t resstat_values[dns_resstatscounter_max];
uint64_t adbstat_values[dns_adbstats_max];
uint64_t zonestat_values[dns_zonestatscounter_max];
uint64_t sockstat_values[isc_sockstatscounter_max];
- uint64_t gluecachestats_values[dns_gluecachestatscounter_max];
isc_stdtime_t now = isc_stdtime_now();
isc_once_do(&once, init_desc);
@@ -4291,75 +4340,12 @@ named_stats_dump(named_server_t *server, FILE *fp) {
sockstats_index, sockstat_values, 0);
fprintf(fp, "++ Per Zone Query Statistics ++\n");
- zone = NULL;
- for (result = dns_zonemgr_first_zone(server->zonemgr, &zone);
- result == ISC_R_SUCCESS; next = NULL,
- result = dns_zonemgr_next_zone(zone, &next), zone = next)
- {
- if (dns_zone_getstatlevel(zone) != dns_zonestat_full) {
- continue;
- }
-
- isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
-
- if (zonestats != NULL) {
- char zonename[DNS_NAME_FORMATSIZE];
- dns_view_t *view = dns_zone_getview(zone);
- if (view == NULL) {
- continue;
- }
-
- dns_name_format(dns_zone_getorigin(zone), zonename,
- sizeof(zonename));
- fprintf(fp, "[%s", zonename);
- if (strcmp(view->name, "_default") != 0) {
- fprintf(fp, " (view: %s)", view->name);
- }
- fprintf(fp, "]\n");
-
- (void)dump_stats(zonestats, isc_statsformat_file, fp,
- NULL, nsstats_desc,
- ns_statscounter_max, nsstats_index,
- nsstat_values, 0);
- }
- }
+ RETERR(named_server_applyzones(server, dump_zone_query_stats, fp));
fprintf(fp, "++ Per Zone Glue Cache Statistics ++\n");
- zone = NULL;
- for (result = dns_zonemgr_first_zone(server->zonemgr, &zone);
- result == ISC_R_SUCCESS; next = NULL,
- result = dns_zonemgr_next_zone(zone, &next), zone = next)
- {
- if (dns_zone_getstatlevel(zone) != dns_zonestat_full) {
- continue;
- }
-
- isc_stats_t *gluecachestats = dns_zone_getgluecachestats(zone);
-
- if (gluecachestats != NULL) {
- char zonename[DNS_NAME_FORMATSIZE];
- dns_view_t *view = dns_zone_getview(zone);
- if (view == NULL) {
- continue;
- }
-
- dns_name_format(dns_zone_getorigin(zone), zonename,
- sizeof(zonename));
- fprintf(fp, "[%s", zonename);
- if (strcmp(view->name, "_default") != 0) {
- fprintf(fp, " (view: %s)", view->name);
- }
- fprintf(fp, "]\n");
-
- (void)dump_stats(gluecachestats, isc_statsformat_file,
- fp, NULL, gluecachestats_desc,
- dns_gluecachestatscounter_max,
- gluecachestats_index,
- gluecachestats_values, 0);
- }
- }
+ RETERR(named_server_applyzones(server, dump_zone_glue_stats, fp));
fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
- return ISC_R_SUCCESS; /* this function currently always succeeds */
+ return ISC_R_SUCCESS;
}
diff --git a/bin/tests/system/dyndb/driver/instance.c b/bin/tests/system/dyndb/driver/instance.c
index cf4d075af1..85180b9a86 100644
--- a/bin/tests/system/dyndb/driver/instance.c
+++ b/bin/tests/system/dyndb/driver/instance.c
@@ -133,7 +133,7 @@ new_sample_instance(isc_mem_t *mctx, const char *db_name, int argc, char **argv,
}
dns_view_attach(dctx->view, &inst->view);
- dns_zonemgr_attach(dctx->zmgr, &inst->zmgr);
+ inst->zmgr = dctx->zmgr;
/* Register new DNS DB implementation. */
result = dns_db_register(db_name, create_db, inst, mctx, &inst->db_imp);
@@ -221,7 +221,6 @@ destroy_sample_instance(sample_instance_t **instp) {
}
dns_view_detach(&inst->view);
- dns_zonemgr_detach(&inst->zmgr);
isc_mem_putanddetach(&inst->mctx, inst, sizeof(*inst));
}
diff --git a/bin/tests/system/dyndb/driver/zone.c b/bin/tests/system/dyndb/driver/zone.c
index d366a8ef67..9bbdff9e48 100644
--- a/bin/tests/system/dyndb/driver/zone.c
+++ b/bin/tests/system/dyndb/driver/zone.c
@@ -68,21 +68,12 @@ create_zone(sample_instance_t *const inst, dns_name_t *const name,
zone_argv[0] = inst->db_name;
- dns_zone_create(&raw, inst->mctx, 0); /* FIXME: all zones are assigned
- to loop 0 */
+ CHECK(dns_zonemgr_createzone(inst->zmgr, &raw));
dns_zone_setorigin(raw, name);
dns_zone_setclass(raw, dns_rdataclass_in);
dns_zone_settype(raw, dns_zone_primary);
dns_zone_setdbtype(raw, 1, zone_argv);
- result = dns_zonemgr_managezone(inst->zmgr, raw);
- if (result != ISC_R_SUCCESS) {
- log_write(ISC_LOG_ERROR,
- "create_zone: dns_zonemgr_managezone -> %s\n",
- isc_result_totext(result));
- goto cleanup;
- }
-
/* This is completely insecure - use some sensible values instead! */
dns_acl_any(inst->mctx, &acl_any);
dns_zone_setupdateacl(raw, acl_any);
@@ -98,9 +89,6 @@ cleanup:
log_error_r("failed to create new zone '%s'", zone_name);
if (raw != NULL) {
- if (dns_zone_getmgr(raw) != NULL) {
- dns_zonemgr_releasezone(inst->zmgr, raw);
- }
dns_zone_detach(&raw);
}
diff --git a/bin/tests/system/shutdown/forwarder/forward.db.j2 b/bin/tests/system/shutdown/forwarder/forward.db.j2
new file mode 100644
index 0000000000..fcc1366784
--- /dev/null
+++ b/bin/tests/system/shutdown/forwarder/forward.db.j2
@@ -0,0 +1,4 @@
+$TTL 300
+forward.test. IN SOA ns.forward.test. hostmaster.forward.test. 1 3600 3600 86400 300
+ IN NS ns.forward.test.
+ns IN A 10.53.0.4
diff --git a/bin/tests/system/shutdown/forwarder/named.conf.j2 b/bin/tests/system/shutdown/forwarder/named.conf.j2
new file mode 100644
index 0000000000..20a1b4faa3
--- /dev/null
+++ b/bin/tests/system/shutdown/forwarder/named.conf.j2
@@ -0,0 +1,26 @@
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+options {
+ port @PORT@;
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ pid-file "named.pid";
+ recursion no;
+ dnssec-validation no;
+ notify no;
+};
+view "@ 'replacement' if retired | default(false) else 'original' @" {
+{% if not retired | default(false) %}
+ zone "forward.test" {
+ type secondary;
+ file "forward.db";
+ primaries { 10.53.0.4 port @PORT@; };
+ allow-update-forwarding { any; };
+ };
+{% endif %}
+};
diff --git a/bin/tests/system/shutdown/tests_shutdown.py b/bin/tests/system/shutdown/tests_shutdown.py
index 9e44c1fd7c..c5bff8e04e 100644
--- a/bin/tests/system/shutdown/tests_shutdown.py
+++ b/bin/tests/system/shutdown/tests_shutdown.py
@@ -15,10 +15,15 @@ from string import ascii_lowercase as letters
import os
import random
import signal
+import socket
+import struct
import subprocess
import time
import dns.exception
+import dns.message
+import dns.opcode
+import dns.update
import pytest
import isctest
@@ -27,6 +32,10 @@ pytestmark = pytest.mark.extra_artifacts(
[
"resolver/named.conf",
"resolver/named.run",
+ "forwarder/named.conf",
+ "forwarder/named.run",
+ "forwarder/forward.db",
+ "forwarder/db-*",
]
)
@@ -185,3 +194,75 @@ def test_named_shutdown(kill_method):
assert named_proc.returncode == 0, "named crashed"
finally: # Ensure named is terminated in case of an exception
named_proc.kill()
+
+
+@pytest.mark.parametrize("retired_view", [False, True])
+@pytest.mark.parametrize("kill_method", ["rndc", "sigterm"])
+def test_shutdown_pending_forward(retired_view, kill_method, templates, named_port):
+ """
+ Shutdown must not wait for an unanswered forwarded UPDATE.
+
+ Keep the primary connection open until named exits. In particular, do not
+ let closing the test socket accidentally unblock shutdown. Reconfiguring
+ with a different view name leaves the old view held by the pending client.
+ """
+ cfg_dir = "forwarder"
+ templates.render(f"{cfg_dir}/named.conf", {"retired": False})
+ templates.render(f"{cfg_dir}/forward.db")
+ instance = isctest.instance.NamedInstance(cfg_dir, num=3)
+
+ def receive_exact(connection, length):
+ result = b""
+ while len(result) < length:
+ chunk = connection.recv(length - len(result))
+ assert chunk, "forwarding connection closed before UPDATE arrived"
+ result += chunk
+ return result
+
+ with socket.socket() as primary, socket.socket(
+ socket.AF_INET, socket.SOCK_DGRAM
+ ) as client:
+ primary.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ primary.bind(("10.53.0.4", named_port))
+ primary.listen()
+ primary.settimeout(10)
+ client.settimeout(0.2)
+ with open(f"{cfg_dir}/named.run", "ab") as log:
+ with subprocess.Popen(
+ isctest.run.get_named_cmdline(cfg_dir), cwd=cfg_dir, stderr=log
+ ) as proc:
+ try:
+ isctest.check.named_alive(proc, "10.53.0.3")
+ update = dns.update.Update("forward.test")
+ update.add("pending", 300, "A", "192.0.2.1")
+ client.sendto(update.to_wire(), ("10.53.0.3", named_port))
+ connection, _ = primary.accept()
+ with connection:
+ connection.settimeout(10)
+ length = struct.unpack("!H", receive_exact(connection, 2))[0]
+ forwarded = dns.message.from_wire(
+ receive_exact(connection, length)
+ )
+ assert forwarded.opcode() == dns.opcode.UPDATE
+ assert forwarded.question == update.question
+ if retired_view:
+ templates.render(f"{cfg_dir}/named.conf", {"retired": True})
+ instance.rndc("reconfig")
+ # Prove the old view is no longer in the active config.
+ result = instance.rndc(
+ "showzone forward.test IN original",
+ raise_on_exception=False,
+ )
+ assert result.rc != 0
+ # The operation must still be outstanding at shutdown.
+ with pytest.raises(socket.timeout):
+ client.recv(65535)
+ if kill_method == "rndc":
+ instance.rndc("stop")
+ else:
+ proc.terminate()
+ assert proc.wait(timeout=10) == 0
+ finally:
+ if proc.poll() is None:
+ proc.kill()
+ proc.wait()
diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c
index 5adc697794..7331b5a294 100644
--- a/lib/dns/dlz.c
+++ b/lib/dns/dlz.c
@@ -71,6 +71,7 @@
#include <dns/master.h>
#include <dns/ssu.h>
#include <dns/zone.h>
+#include <dns/zonemgr.h>
#include <dns/zoneproperties.h>
#include "dlz_p.h"
@@ -423,7 +424,7 @@ dns_dlz_writeablezone(dns_view_t *view, dns_dlzdb_t *dlzdb,
INSIST(dupzone == NULL);
/* Create it */
- dns_zone_create(&zone, view->mctx, 0);
+ CHECK(dns_zonemgr_createzone(dns_g_zonemgr, &zone));
dns_zone_setorigin(zone, origin);
dns_zone_setview(zone, view);
diff --git a/lib/dns/dyndb.c b/lib/dns/dyndb.c
index 55043ec2ee..b7feeba33b 100644
--- a/lib/dns/dyndb.c
+++ b/lib/dns/dyndb.c
@@ -265,9 +265,8 @@ dns_dyndb_createctx(isc_mem_t *mctx, const void *hashinit, dns_view_t *view,
if (view != NULL) {
dns_view_attach(view, &dctx->view);
}
- if (zmgr != NULL) {
- dns_zonemgr_attach(zmgr, &dctx->zmgr);
- }
+ /* The runtime keeps the manager alive through module cleanup. */
+ dctx->zmgr = zmgr;
isc_mem_attach(mctx, &dctx->mctx);
dctx->magic = DNS_DYNDBCTX_MAGIC;
@@ -289,9 +288,6 @@ dns_dyndb_destroyctx(dns_dyndbctx_t **dctxp) {
if (dctx->view != NULL) {
dns_view_detach(&dctx->view);
}
- if (dctx->zmgr != NULL) {
- dns_zonemgr_detach(&dctx->zmgr);
- }
isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
}
diff --git a/lib/dns/include/dns/dyndb.h b/lib/dns/include/dns/dyndb.h
index 4f6b376c3e..64919af80a 100644
--- a/lib/dns/include/dns/dyndb.h
+++ b/lib/dns/include/dns/dyndb.h
@@ -28,7 +28,8 @@
* initializer, log context, etc. The structure doesn't persist
* beyond configuring the dyndb module. The module's register function
* should attach to all reference-counted variables and its destroy
- * function should detach from them.
+ * function should detach from them. The zone manager is borrowed: the runtime
+ * keeps it alive until all modules and their outstanding zone activity finish.
*/
struct dns_dyndbctx {
unsigned int magic;
@@ -51,7 +52,7 @@ struct dns_dyndbctx {
* if not, set DNS_DYNDB_AGE to 0.
*/
#ifndef DNS_DYNDB_VERSION
-#define DNS_DYNDB_VERSION 3
+#define DNS_DYNDB_VERSION 4
#define DNS_DYNDB_AGE 0
#endif /* ifndef DNS_DYNDB_VERSION */
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
index 633315add0..b06b40f783 100644
--- a/lib/dns/include/dns/zone.h
+++ b/lib/dns/include/dns/zone.h
@@ -355,6 +355,15 @@ dns_zone_markdirty(dns_zone_t *zone);
*\li 'zone' to be a valid zone.
*/
+void
+dns_zone_forcemaint(dns_zone_t *zone);
+/*%<
+ * Reconsider the maintenance timer of a configured zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
void
dns_zone_refresh(dns_zone_t *zone);
/*%<
@@ -596,6 +605,17 @@ dns_zone_prepare_shutdown(dns_zone_t *zone);
*\li 'zone' to be a valid initialised zone.
*/
+unsigned int
+dns_zone_getcount(dns_zone_t *zone, dns_zonestate_t state);
+/*%<
+ * Return this zone's contribution to a non-transfer status count.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ *\li 'state' is DNS_ZONESTATE_XFERFIRSTREFRESH, DNS_ZONESTATE_SOAQUERY,
+ * DNS_ZONESTATE_ANY, or DNS_ZONESTATE_AUTOMATIC.
+ */
+
isc_result_t
dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
bool *is_running, bool *is_deferred, bool *is_presoa,
diff --git a/lib/dns/include/dns/zonemgr.h b/lib/dns/include/dns/zonemgr.h
index e1478826aa..00426aad71 100644
--- a/lib/dns/include/dns/zonemgr.h
+++ b/lib/dns/include/dns/zonemgr.h
@@ -17,10 +17,17 @@
#include <dns/zone.h>
+/*
+ * Process-wide shared zone services owned by the runtime. Borrowed by zones
+ * and DynDB modules; valid until the runtime calls dns_zonemgr_destroy().
+ */
+extern dns_zonemgr_t *dns_g_zonemgr;
+
void
dns_zonemgr_create(isc_mem_t *mctx, dns_zonemgr_t **zmgrp);
/*%<
- * Create a zone manager.
+ * Create the process-wide zone manager. Only one may exist at a time.
+ * The caller owns its lifetime and must destroy it after all loops drain.
*
* Requires:
*\li 'mctx' to be a valid memory context.
@@ -31,75 +38,43 @@ isc_result_t
dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep);
/*%<
* Allocate a new zone using a memory context from the
- * zone manager's memory context pool.
+ * zone manager's memory context pool, attached to an existing event loop.
+ * The runtime must keep the manager alive until zone cleanup finishes.
*
* Require:
*\li 'zmgr' to be a valid zone manager.
*\li 'zonep' != NULL and '*zonep' == NULL.
*/
-isc_result_t
-dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
-/*%<
- * Bring the zone under control of a zone manager.
- *
- * Require:
- *\li 'zmgr' to be a valid zone manager.
- *\li 'zone' to be a valid zone.
- */
-
-isc_result_t
-dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr);
-/*%<
- * Force zone maintenance of all loaded zones managed by 'zmgr'
- * to take place at the system's earliest convenience.
- */
-
void
-dns_zonemgr_shutdown(dns_zonemgr_t *zmgr);
+dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr);
/*%<
- * Shut down the zone manager.
+ * Retry transfers waiting for quota after a configuration change.
+ * Zone timer maintenance is scheduled separately by the view owner.
*
* Requires:
*\li 'zmgr' to be a valid zone manager.
*/
void
-dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target);
-/*%<
- * Attach '*target' to 'source' incrementing its external
- * reference count.
- *
- * Require:
- *\li 'zone' to be a valid zone.
- *\li 'target' to be non NULL and '*target' to be NULL.
- */
-
-void
-dns_zonemgr_detach(dns_zonemgr_t **zmgrp);
+dns_zonemgr_shutdown(dns_zonemgr_t *zmgr);
/*%<
- * Detach from a zone manager.
+ * Stop zone services while the event loops are running. The manager
+ * remains allocated until dns_zonemgr_destroy() is called after the loops
+ * drain.
*
* Requires:
- *\li '*zmgrp' is a valid, non-NULL zone manager pointer.
- *
- * Ensures:
- *\li '*zmgrp' is NULL.
+ *\li 'zmgr' to be a valid zone manager.
*/
void
-dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
+dns_zonemgr_destroy(dns_zonemgr_t **zmgrp);
/*%<
- * Release 'zone' from the managed by 'zmgr'. 'zmgr' is implicitly
- * detached from 'zone'.
- *
- * Requires:
- *\li 'zmgr' to be a valid zone manager.
- *\li 'zone' to be a valid zone.
- *\li 'zmgr' == 'zone->zmgr'
+ * Destroy the process-wide zone manager and clear '*zmgrp' and dns_g_zonemgr.
*
- * Ensures:
- *\li 'zone->zmgr' == NULL;
+ * The runtime must first shut down the manager and all DynDB instances, then
+ * drain all zone activity by waiting for isc_loopmgr_run() to return. Zones
+ * and DynDB instances borrow the manager and must not outlive it.
*/
void
@@ -209,7 +184,7 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state);
*
* Requires:
*\li 'zmgr' to be a valid zone manager.
- *\li 'state' to be a valid DNS_ZONESTATE_ enum.
+ *\li 'state' is DNS_ZONESTATE_XFERRUNNING or DNS_ZONESTATE_XFERDEFERRED.
*/
void
@@ -223,35 +198,3 @@ dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
*\li 'zmgr' is a valid zone manager.
*\li 'tlsctx_cache' is a valid TLS context cache.
*/
-
-isc_result_t
-dns_zonemgr_next_zone(dns_zone_t *zone, dns_zone_t **next);
-/*%<
- * Find the next zone in the list of managed zones.
- *
- * Requires:
- *\li 'zone' to be valid
- *\li The zone manager for the indicated zone MUST be locked
- * by the caller. This is not checked.
- *\li 'next' be non-NULL, and '*next' be NULL.
- *
- * Ensures:
- *\li 'next' points to a valid zone (result ISC_R_SUCCESS) or to NULL
- * (result ISC_R_NOMORE).
- */
-
-isc_result_t
-dns_zonemgr_first_zone(dns_zonemgr_t *zmgr, dns_zone_t **first);
-/*%<
- * Find the first zone in the list of managed zones.
- *
- * Requires:
- *\li 'zonemgr' to be valid
- *\li The zone manager for the indicated zone MUST be locked
- * by the caller. This is not checked.
- *\li 'first' be non-NULL, and '*first' be NULL
- *
- * Ensures:
- *\li 'first' points to a valid zone (result ISC_R_SUCCESS) or to NULL
- * (result ISC_R_NOMORE).
- */
diff --git a/lib/dns/include/dns/zoneproperties.h b/lib/dns/include/dns/zoneproperties.h
index c9c4c3ff17..41631b5527 100644
--- a/lib/dns/include/dns/zoneproperties.h
+++ b/lib/dns/include/dns/zoneproperties.h
@@ -918,15 +918,6 @@ dns_zone_getmctx(dns_zone_t *zone);
* \li 'zone' to be a valid zone.
*/
-dns_zonemgr_t *
-dns_zone_getmgr(dns_zone_t *zone);
-/*%<
- * If 'zone' is managed return the zone manager otherwise NULL.
- *
- * Requires:
- * \li 'zone' to be a valid zone.
- */
-
void
dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval);
/*%<
diff --git a/lib/dns/notify.c b/lib/dns/notify.c
index 979ee35c46..73bedf2ccc 100644
--- a/lib/dns/notify.c
+++ b/lib/dns/notify.c
@@ -26,6 +26,7 @@
#include <dns/stats.h>
#include <dns/tsig.h>
#include <dns/zone.h>
+#include <dns/zonemgr.h>
#include <dns/zoneproperties.h>
#include "zone_p.h"
@@ -339,7 +340,7 @@ notify_send_toaddr(void *arg) {
dns__zone_lock(notify->zone);
notifyctx = dns__zone_getnotifyctx(notify->zone, notify->type);
- zmgr = dns_zone_getmgr(notify->zone);
+ zmgr = dns_g_zonemgr;
view = dns_zone_getview(notify->zone);
loop = dns_zone_getloop(notify->zone);
result = dns_zone_getdb(notify->zone, &zonedb);
@@ -526,7 +527,7 @@ notify_queue(dns_notify_t *notify, bool startup, bool dequeue) {
REQUIRE(DNS_NOTIFY_VALID(notify));
isc_loop_t *loop = dns_zone_getloop(notify->zone);
- dns_zonemgr_t *zmgr = dns_zone_getmgr(notify->zone);
+ dns_zonemgr_t *zmgr = dns_g_zonemgr;
isc_ratelimiter_t *notifyrl = NULL;
isc_ratelimiter_t *startupnotifyrl = NULL;
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
index 9bcdf5fc43..06755fffb0 100644
--- a/lib/dns/xfrin.c
+++ b/lib/dns/xfrin.c
@@ -1434,7 +1434,6 @@ xfrin_connect_done(isc_result_t eresult, isc_region_t *region ISC_ATTR_UNUSED,
char addrtext[ISC_SOCKADDR_FORMATSIZE];
char signerbuf[DNS_NAME_FORMATSIZE];
const char *signer = "", *sep = "";
- dns_zonemgr_t *zmgr = NULL;
isc_result_t result;
REQUIRE(VALID_XFRIN(xfr));
@@ -1454,8 +1453,7 @@ xfrin_connect_done(isc_result_t eresult, isc_region_t *region ISC_ATTR_UNUSED,
goto cleanup;
}
- zmgr = dns_zone_getmgr(xfr->zone);
- if (zmgr != NULL) {
+ if (dns_zone_getloop(xfr->zone) != NULL) {
dns_view_t *view = dns_zone_getview(xfr->zone);
dns_unreachcache_remove(view->unreachcache, &xfr->primaryaddr,
&xfr->sourceaddr);
@@ -1493,8 +1491,7 @@ cleanup:
* the server has a permanent networking error or
* the connection attempt as timed out.
*/
- zmgr = dns_zone_getmgr(xfr->zone);
- if (zmgr != NULL) {
+ if (dns_zone_getloop(xfr->zone) != NULL) {
dns_view_t *view = dns_zone_getview(xfr->zone);
dns_unreachcache_add(view->unreachcache,
&xfr->primaryaddr,
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 15ffc0241c..03dc3eeb26 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -512,7 +512,6 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, isc_tid_t tid) {
.nsec3chain = ISC_LIST_INITIALIZER,
.maintenance_queue = ISC_LIST_INITIALIZER,
.forwards = ISC_LIST_INITIALIZER,
- .link = ISC_LINK_INITIALIZER,
.statelink = ISC_LINK_INITIALIZER,
};
dns_remote_t r = {
@@ -561,7 +560,6 @@ dns__zone_free(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(!LOCKED_ZONE(zone));
REQUIRE(zone->timer == NULL);
- REQUIRE(zone->zmgr == NULL);
dns_zone_unloadplugins(zone);
@@ -711,6 +709,9 @@ dns__zone_free(dns_zone_t *zone) {
}
/* last stuff */
+ if (zone->loop != NULL) {
+ isc_loop_detach(&zone->loop);
+ }
ZONEDB_DESTROYLOCK(&zone->dblock);
isc_mutex_destroy(&zone->lock);
zone->magic = 0;
@@ -1487,7 +1488,7 @@ dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_callback_t *done,
REQUIRE(DNS_ZONE_VALID(zone));
- if (zone->zmgr == NULL) {
+ if (zone->loop == NULL) {
return ISC_R_FAILURE;
}
@@ -1714,7 +1715,7 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
CHECK(dns_db_beginload(db, &load->callbacks));
- if (zone->zmgr != NULL && zone->db != NULL) {
+ if (zone->loop != NULL && zone->db != NULL) {
CHECK(dns_master_loadfileasync(
zone->masterfile, dns_db_origin(db), dns_db_origin(db),
zone->rdclass, options, 0, &load->callbacks, zone->loop,
@@ -4583,6 +4584,41 @@ dns__zone_free_check(dns_zone_t *zone) {
return false;
}
+void
+dns_zone_forcemaint(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ LOCK_ZONE(zone);
+ dns__zone_settimer(zone, isc_time_now());
+ UNLOCK_ZONE(zone);
+}
+
+unsigned int
+dns_zone_getcount(dns_zone_t *zone, dns_zonestate_t state) {
+ unsigned int count = 0;
+ REQUIRE(DNS_ZONE_VALID(zone));
+ LOCK_ZONE(zone);
+ switch (state) {
+ case DNS_ZONESTATE_XFERFIRSTREFRESH:
+ count = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
+ break;
+ case DNS_ZONESTATE_SOAQUERY:
+ count = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH);
+ break;
+ case DNS_ZONESTATE_ANY:
+ case DNS_ZONESTATE_AUTOMATIC:
+ if (zone->view == NULL ||
+ strcmp(zone->view->name, "_bind") != 0)
+ {
+ count = state == DNS_ZONESTATE_ANY || zone->automatic;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ UNLOCK_ZONE(zone);
+ return count;
+}
+
static bool
zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
dns_name_t *name, bool logit) {
@@ -12534,7 +12570,7 @@ queue_soa_query(dns_zone_t *zone) {
* Attach so that we won't clean up until the event is delivered.
*/
zone_iattach(zone, &sq->zone);
- result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->loop,
+ result = isc_ratelimiter_enqueue(dns_g_zonemgr->refreshrl, zone->loop,
soa_query, sq, &sq->rlevent);
if (result != ISC_R_SUCCESS) {
zone_idetach(&sq->zone);
@@ -13061,24 +13097,23 @@ zone_shutdown(void *arg) {
/*
* If we were waiting for xfrin quota, step out of
* the queue.
- * If there's no zone manager, we can't be waiting for the
- * xfrin quota
+ * A zone without an event loop cannot be waiting for transfer quota.
*/
- if (zone->zmgr != NULL) {
- RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
- if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
- ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
+ if (zone->loop != NULL) {
+ RWLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_write);
+ if (zone->statelist == &dns_g_zonemgr->waiting_for_xfrin) {
+ ISC_LIST_UNLINK(dns_g_zonemgr->waiting_for_xfrin, zone,
statelink);
linked = true;
zone->statelist = NULL;
}
- if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
- ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
+ if (zone->statelist == &dns_g_zonemgr->xfrin_in_progress) {
+ ISC_LIST_UNLINK(dns_g_zonemgr->xfrin_in_progress, zone,
statelink);
zone->statelist = NULL;
- dns__zonemgr_resume_xfrs(zone->zmgr, false);
+ dns__zonemgr_resume_xfrs(dns_g_zonemgr, false);
}
- RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
+ RWUNLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_write);
}
/*
@@ -13089,11 +13124,6 @@ zone_shutdown(void *arg) {
dns_xfrin_shutdown(zone->xfr);
}
- /* Safe to release the zone now */
- if (zone->zmgr != NULL) {
- dns_zonemgr_releasezone(zone->zmgr, zone);
- }
-
/* Detach the zone configuration pointer */
dns_zone_setcfg(zone, NULL, NULL);
@@ -15712,15 +15742,16 @@ again:
* This transfer finishing freed up a transfer quota slot.
* Let any other zones waiting for quota have it.
*/
- if (zone->zmgr != NULL &&
- zone->statelist == &zone->zmgr->xfrin_in_progress)
+ if (zone->loop != NULL &&
+ zone->statelist == &dns_g_zonemgr->xfrin_in_progress)
{
UNLOCK_ZONE(zone);
- RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
- ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
+ RWLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_write);
+ ISC_LIST_UNLINK(dns_g_zonemgr->xfrin_in_progress, zone,
+ statelink);
zone->statelist = NULL;
- dns__zonemgr_resume_xfrs(zone->zmgr, false);
- RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
+ dns__zonemgr_resume_xfrs(dns_g_zonemgr, false);
+ RWUNLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_write);
LOCK_ZONE(zone);
}
@@ -15814,7 +15845,7 @@ again:
static void
queue_xfrin(dns_zone_t *zone) {
isc_result_t result;
- dns_zonemgr_t *zmgr = zone->zmgr;
+ dns_zonemgr_t *zmgr = dns_g_zonemgr;
ENTER;
@@ -15935,7 +15966,7 @@ next:
}
}
- dns__zonemgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
+ dns__zonemgr_tlsctx_attach(dns_g_zonemgr, &zmgr_tlsctx_cache);
const unsigned int connect_timeout = isc_nm_getprimariestimeout() /
MS_PER_SEC;
result = dns_request_createraw(
@@ -16182,15 +16213,15 @@ dns_zone_stopxfr(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
- RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+ RWLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_read);
LOCK_ZONE(zone);
- if (zone->statelist == &zone->zmgr->xfrin_in_progress &&
+ if (zone->statelist == &dns_g_zonemgr->xfrin_in_progress &&
zone->xfr != NULL)
{
dns_xfrin_attach(zone->xfr, &xfr);
}
UNLOCK_ZONE(zone);
- RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+ RWUNLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_read);
if (xfr != NULL) {
dns_xfrin_shutdown(xfr);
@@ -16278,7 +16309,7 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(xfrp != NULL && *xfrp == NULL);
- if (zone->zmgr == NULL) {
+ if (zone->loop == NULL) {
return ISC_R_FAILURE;
}
@@ -16290,20 +16321,20 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
*is_pending = false;
*needs_refresh = false;
- RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+ RWLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_read);
LOCK_ZONE(zone);
*is_firstrefresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
if (zone->xfr != NULL) {
dns_xfrin_attach(zone->xfr, xfrp);
}
- if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
+ if (zone->statelist == &dns_g_zonemgr->xfrin_in_progress) {
*is_running = true;
/*
* The NEEDREFRESH flag is set only when a notify was received
* while the current zone transfer is running.
*/
*needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
- } else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
+ } else if (zone->statelist == &dns_g_zonemgr->waiting_for_xfrin) {
*is_deferred = true;
} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
if (zone->request != NULL) {
@@ -16329,7 +16360,7 @@ dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
}
}
UNLOCK_ZONE(zone);
- RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
+ RWUNLOCK(&dns_g_zonemgr->rwlock, isc_rwlocktype_read);
return ISC_R_SUCCESS;
}
@@ -17570,7 +17601,7 @@ checkds_send_toaddr(void *arg) {
options |= DNS_REQUESTOPT_TCP;
- dns__zonemgr_tlsctx_attach(checkds->zone->zmgr, &zmgr_tlsctx_cache);
+ dns__zonemgr_tlsctx_attach(dns_g_zonemgr, &zmgr_tlsctx_cache);
const unsigned int connect_timeout = isc_nm_getinitialtimeout() /
MS_PER_SEC;
@@ -17644,10 +17675,9 @@ checkds_send_tons(dns_checkds_t *checkds) {
UNREACHABLE();
}
- CHECK(isc_ratelimiter_enqueue(newcheckds->zone->zmgr->checkdsrl,
- newcheckds->zone->loop,
- checkds_send_toaddr, newcheckds,
- &newcheckds->rlevent));
+ CHECK(isc_ratelimiter_enqueue(
+ dns_g_zonemgr->checkdsrl, newcheckds->zone->loop,
+ checkds_send_toaddr, newcheckds, &newcheckds->rlevent));
newcheckds = NULL;
}
@@ -17764,7 +17794,7 @@ checkds_send(dns_zone_t *zone) {
ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
result = isc_ratelimiter_enqueue(
- checkds->zone->zmgr->checkdsrl, checkds->zone->loop,
+ dns_g_zonemgr->checkdsrl, checkds->zone->loop,
checkds_send_toaddr, checkds, &checkds->rlevent);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_DEBUG(3),
@@ -19715,32 +19745,30 @@ again:
}
/*
- * Lock hierarchy: zmgr, zone, raw.
+ * Link a fresh raw zone to its signed counterpart on the same event loop.
*/
isc_result_t
dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
- dns_zonemgr_t *zmgr;
-
REQUIRE(DNS_ZONE_VALID(zone));
- REQUIRE(zone->zmgr != NULL);
REQUIRE(zone->loop != NULL);
REQUIRE(zone->raw == NULL);
REQUIRE(DNS_ZONE_VALID(raw));
- REQUIRE(raw->zmgr == NULL);
- REQUIRE(raw->loop == NULL);
REQUIRE(raw->secure == NULL);
REQUIRE(zone != raw);
/*
- * Lock hierarchy: zmgr, zone, raw.
+ * Lock hierarchy: zone, raw. No global registration is needed.
*/
- zmgr = zone->zmgr;
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
LOCK_ZONE(zone);
LOCK_ZONE(raw);
+ REQUIRE(raw->timer == NULL);
+ if (raw->loop != NULL) {
+ isc_loop_detach(&raw->loop);
+ }
+ raw->tid = zone->tid;
isc_loop_attach(zone->loop, &raw->loop);
/* dns_zone_attach(raw, &zone->raw); */
@@ -19750,13 +19778,8 @@ dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
/* dns_zone_iattach(zone, &raw->secure); */
zone_iattach(zone, &raw->secure);
- ISC_LIST_APPEND(zmgr->zones, raw, link);
- raw->zmgr = zmgr;
- isc_refcount_increment(&zmgr->refs);
-
UNLOCK_ZONE(raw);
UNLOCK_ZONE(zone);
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
return ISC_R_SUCCESS;
}
diff --git a/lib/dns/zone_p.h b/lib/dns/zone_p.h
index 0ebdb6bc86..ae93941540 100644
--- a/lib/dns/zone_p.h
+++ b/lib/dns/zone_p.h
@@ -334,7 +334,7 @@ typedef struct zone_settimer {
struct dns_zonemgr {
unsigned int magic;
isc_mem_t *mctx;
- isc_refcount_t refs;
+ bool shuttingdown;
uint32_t workers;
isc_mem_t **mctxpool;
isc_ratelimiter_t *checkdsrl;
@@ -345,7 +345,6 @@ struct dns_zonemgr {
isc_rwlock_t rwlock;
/* Locked by rwlock. */
- dns_zonelist_t zones;
dns_zonelist_t waiting_for_xfrin;
dns_zonelist_t xfrin_in_progress;
@@ -454,8 +453,6 @@ struct dns_zone {
isc_tid_t tid;
/* Locked */
- dns_zonemgr_t *zmgr;
- ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
isc_loop_t *loop;
isc_timer_t *timer;
isc_refcount_t irefs;
diff --git a/lib/dns/zonemgr.c b/lib/dns/zonemgr.c
index ce21814716..3e47e7e712 100644
--- a/lib/dns/zonemgr.c
+++ b/lib/dns/zonemgr.c
@@ -26,8 +26,7 @@
#include "zone_p.h"
-static void
-zonemgr_free(dns_zonemgr_t *zmgr);
+dns_zonemgr_t *dns_g_zonemgr = NULL;
/***
*** Zone manager.
@@ -71,6 +70,7 @@ dns_zonemgr_create(isc_mem_t *mctx, dns_zonemgr_t **zmgrp) {
isc_loop_t *loop = isc_loop();
REQUIRE(mctx != NULL);
+ REQUIRE(dns_g_zonemgr == NULL);
REQUIRE(zmgrp != NULL && *zmgrp == NULL);
zmgr = isc_mem_get(mctx, sizeof(*zmgr));
@@ -81,10 +81,8 @@ dns_zonemgr_create(isc_mem_t *mctx, dns_zonemgr_t **zmgrp) {
.transfersperns = 2,
};
- isc_refcount_init(&zmgr->refs, 1);
isc_mem_attach(mctx, &zmgr->mctx);
- ISC_LIST_INIT(zmgr->zones);
ISC_LIST_INIT(zmgr->waiting_for_xfrin);
ISC_LIST_INIT(zmgr->xfrin_in_progress);
isc_rwlock_init(&zmgr->rwlock);
@@ -115,6 +113,7 @@ dns_zonemgr_create(isc_mem_t *mctx, dns_zonemgr_t **zmgrp) {
zmgr->magic = ZONEMGR_MAGIC;
+ dns_g_zonemgr = zmgr;
*zmgrp = zmgr;
}
@@ -139,97 +138,16 @@ dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
}
dns_zone_create(&zone, mctx, tid);
+ isc_loop_attach(isc_loop_get(tid), &zone->loop);
*zonep = zone;
return ISC_R_SUCCESS;
}
-isc_result_t
-dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
- REQUIRE(DNS_ZONE_VALID(zone));
- REQUIRE(DNS_ZONEMGR_VALID(zmgr));
-
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
- LOCK_ZONE(zone);
- REQUIRE(zone->timer == NULL);
- REQUIRE(zone->zmgr == NULL);
-
- isc_loop_t *loop = isc_loop_get(zone->tid);
- isc_loop_attach(loop, &zone->loop);
-
- ISC_LIST_APPEND(zmgr->zones, zone, link);
- zone->zmgr = zmgr;
-
- isc_refcount_increment(&zmgr->refs);
-
- UNLOCK_ZONE(zone);
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
- return ISC_R_SUCCESS;
-}
-
void
-dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
- REQUIRE(DNS_ZONE_VALID(zone));
+dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- REQUIRE(zone->zmgr == zmgr);
-
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
- LOCK_ZONE(zone);
-
- ISC_LIST_UNLINK(zmgr->zones, zone, link);
-
- if (zone->timer != NULL) {
- isc_refcount_decrement(&zone->irefs);
- isc_timer_destroy(&zone->timer);
- }
-
- isc_loop_detach(&zone->loop);
-
- /* Detach below, outside of the write lock. */
- zone->zmgr = NULL;
-
- UNLOCK_ZONE(zone);
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
-
- dns_zonemgr_detach(&zmgr);
-}
-
-void
-dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
- REQUIRE(DNS_ZONEMGR_VALID(source));
- REQUIRE(target != NULL && *target == NULL);
-
- isc_refcount_increment(&source->refs);
-
- *target = source;
-}
-
-void
-dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
- dns_zonemgr_t *zmgr;
-
- REQUIRE(zmgrp != NULL);
- zmgr = *zmgrp;
- *zmgrp = NULL;
- REQUIRE(DNS_ZONEMGR_VALID(zmgr));
-
- if (isc_refcount_decrement(&zmgr->refs) == 1) {
- zonemgr_free(zmgr);
- }
-}
-
-isc_result_t
-dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
- REQUIRE(DNS_ZONEMGR_VALID(zmgr));
-
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- LOCK_ZONE(zone);
- dns__zone_settimer(zone, isc_time_now());
- UNLOCK_ZONE(zone);
- }
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
/*
* Recent configuration changes may have increased the
@@ -240,12 +158,14 @@ dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
dns__zonemgr_resume_xfrs(zmgr, true);
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
- return ISC_R_SUCCESS;
}
void
dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+ REQUIRE(!zmgr->shuttingdown);
+
+ zmgr->shuttingdown = true;
isc_ratelimiter_shutdown(zmgr->checkdsrl);
isc_ratelimiter_shutdown(zmgr->notifyrl);
@@ -256,23 +176,22 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
for (size_t i = 0; i < zmgr->workers; i++) {
isc_mem_detach(&zmgr->mctxpool[i]);
}
-
- RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- LOCK_ZONE(zone);
- dns__zone_forward_cancel(zone);
- UNLOCK_ZONE(zone);
- }
- RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
}
-static void
-zonemgr_free(dns_zonemgr_t *zmgr) {
- REQUIRE(ISC_LIST_EMPTY(zmgr->zones));
+void
+dns_zonemgr_destroy(dns_zonemgr_t **zmgrp) {
+ REQUIRE(zmgrp != NULL && DNS_ZONEMGR_VALID(*zmgrp));
+ REQUIRE(isc_loop() == NULL);
+ dns_zonemgr_t *zmgr = *zmgrp;
+ REQUIRE(zmgr->shuttingdown);
+ REQUIRE(zmgr == dns_g_zonemgr);
+ REQUIRE(ISC_LIST_EMPTY(zmgr->waiting_for_xfrin));
+ REQUIRE(ISC_LIST_EMPTY(zmgr->xfrin_in_progress));
+ *zmgrp = NULL;
+ dns_g_zonemgr = NULL;
zmgr->magic = 0;
- isc_refcount_destroy(&zmgr->refs);
isc_ratelimiter_detach(&zmgr->checkdsrl);
isc_ratelimiter_detach(&zmgr->notifyrl);
isc_ratelimiter_detach(&zmgr->refreshrl);
@@ -528,7 +447,7 @@ got_transfer_quota(void *arg) {
INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
- dns__zonemgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
+ dns__zonemgr_tlsctx_attach(dns_g_zonemgr, &zmgr_tlsctx_cache);
dns_xfrin_create(zone, xfrtype, ixfr_maxdiffs, &primaryaddr,
&sourceaddr, zone->tsigkey, soa_transport_type,
@@ -766,40 +685,6 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state) {
count++;
}
break;
- case DNS_ZONESTATE_XFERFIRSTREFRESH:
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH)) {
- count++;
- }
- }
- break;
- case DNS_ZONESTATE_SOAQUERY:
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
- count++;
- }
- }
- break;
- case DNS_ZONESTATE_ANY:
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- dns_view_t *view = zone->view;
- if (view != NULL && strcmp(view->name, "_bind") == 0) {
- continue;
- }
- count++;
- }
- break;
- case DNS_ZONESTATE_AUTOMATIC:
- ISC_LIST_FOREACH(zmgr->zones, zone, link) {
- dns_view_t *view = zone->view;
- if (view != NULL && strcmp(view->name, "_bind") == 0) {
- continue;
- }
- if (zone->automatic) {
- count++;
- }
- }
- break;
default:
UNREACHABLE();
}
@@ -808,29 +693,3 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state) {
return count;
}
-
-isc_result_t
-dns_zonemgr_next_zone(dns_zone_t *zone, dns_zone_t **next) {
- REQUIRE(DNS_ZONE_VALID(zone));
- REQUIRE(next != NULL && *next == NULL);
-
- *next = ISC_LIST_NEXT(zone, link);
- if (*next == NULL) {
- return ISC_R_NOMORE;
- } else {
- return ISC_R_SUCCESS;
- }
-}
-
-isc_result_t
-dns_zonemgr_first_zone(dns_zonemgr_t *zmgr, dns_zone_t **first) {
- REQUIRE(DNS_ZONEMGR_VALID(zmgr));
- REQUIRE(first != NULL && *first == NULL);
-
- *first = ISC_LIST_HEAD(zmgr->zones);
- if (*first == NULL) {
- return ISC_R_NOMORE;
- } else {
- return ISC_R_SUCCESS;
- }
-}
diff --git a/lib/dns/zoneproperties.c b/lib/dns/zoneproperties.c
index 292adbf28f..279ceebe30 100644
--- a/lib/dns/zoneproperties.c
+++ b/lib/dns/zoneproperties.c
@@ -24,6 +24,7 @@
#include <dns/stats.h>
#include <dns/view.h>
#include <dns/zone.h>
+#include <dns/zonemgr.h>
#include <dns/zoneproperties.h>
#include "zone_p.h"
@@ -590,13 +591,6 @@ dns_zone_getmctx(dns_zone_t *zone) {
return zone->mctx;
}
-dns_zonemgr_t *
-dns_zone_getmgr(dns_zone_t *zone) {
- REQUIRE(DNS_ZONE_VALID(zone));
-
- return zone->zmgr;
-}
-
void
dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
REQUIRE(DNS_ZONE_VALID(zone));
@@ -2123,7 +2117,8 @@ dns_zone_getrequesttransporttype(dns_zone_t *zone) {
dns_keystorelist_t *
dns_zone_getkeystores(dns_zone_t *zone) {
- return zone->zmgr->keystores;
+ REQUIRE(DNS_ZONE_VALID(zone));
+ return dns_g_zonemgr->keystores;
}
isc_stats_t *
diff --git a/tests/dns/update_test.c b/tests/dns/update_test.c
index 14c6f6be36..973b019600 100644
--- a/tests/dns/update_test.c
+++ b/tests/dns/update_test.c
@@ -397,8 +397,6 @@ ISC_LOOP_TEST_IMPL(find_zone_keys_overflow) {
dns_zonemgr_create(isc_g_mctx, &mgr);
result = dns_test_makezone("example", &zone, NULL, false);
assert_int_equal(result, ISC_R_SUCCESS);
- result = dns_zonemgr_managezone(mgr, zone);
- assert_int_equal(result, ISC_R_SUCCESS);
dns_zone_setkeydirectory(zone, keydir);
result = find_zone_keys(zone, isc_g_mctx, DNS_MAXZONEKEYS, keys,
@@ -415,10 +413,8 @@ ISC_LOOP_TEST_IMPL(find_zone_keys_overflow) {
dst_key_free(&keys[i]);
}
- dns_zonemgr_releasezone(mgr, zone);
dns_zone_detach(&zone);
dns_zonemgr_shutdown(mgr);
- dns_zonemgr_detach(&mgr);
cleanup_keydir(keydir);
@@ -427,6 +423,13 @@ ISC_LOOP_TEST_IMPL(find_zone_keys_overflow) {
isc_loopmgr_shutdown();
}
+static int
+teardown_zone_services(void **state) {
+ teardown_managers(state);
+ dns_zonemgr_destroy(&dns_g_zonemgr);
+ return 0;
+}
+
ISC_TEST_LIST_START
ISC_TEST_ENTRY_CUSTOM(increment, setup_test, NULL)
ISC_TEST_ENTRY_CUSTOM(increment_past_zero, setup_test, NULL)
@@ -441,7 +444,7 @@ ISC_TEST_ENTRY_CUSTOM(past_to_date, setup_test, NULL)
ISC_TEST_ENTRY_CUSTOM(now_to_date, setup_test, NULL)
ISC_TEST_ENTRY_CUSTOM(future_to_date, setup_test, NULL)
ISC_TEST_ENTRY_CUSTOM(find_zone_keys_overflow, setup_managers,
- teardown_managers)
+ teardown_zone_services)
ISC_TEST_LIST_END
ISC_TEST_MAIN
diff --git a/tests/dns/zonemgr_test.c b/tests/dns/zonemgr_test.c
index 26594e67b9..d6ed24fcf1 100644
--- a/tests/dns/zonemgr_test.c
+++ b/tests/dns/zonemgr_test.c
@@ -37,6 +37,8 @@
#include <tests/dns.h>
+static dns_zonemgr_t *mgr = NULL;
+
static int
setup_test(void **state) {
setup_loopmgr(state);
@@ -49,88 +51,80 @@ static int
teardown_test(void **state) {
teardown_netmgr(state);
teardown_loopmgr(state);
+ assert_ptr_equal(dns_g_zonemgr, mgr);
+ dns_zonemgr_destroy(&mgr);
+ assert_null(mgr);
+ assert_null(dns_g_zonemgr);
return 0;
}
/* create zone manager */
ISC_LOOP_TEST_IMPL(zonemgr_create) {
- dns_zonemgr_t *myzonemgr = NULL;
-
UNUSED(arg);
- dns_zonemgr_create(isc_g_mctx, &myzonemgr);
+ dns_zonemgr_create(isc_g_mctx, &mgr);
- dns_zonemgr_shutdown(myzonemgr);
- dns_zonemgr_detach(&myzonemgr);
- assert_null(myzonemgr);
+ dns_zonemgr_shutdown(mgr);
+ assert_ptr_equal(dns_g_zonemgr, mgr);
isc_loopmgr_shutdown();
}
-/* manage and release a zone */
-ISC_LOOP_TEST_IMPL(zonemgr_managezone) {
- dns_zonemgr_t *myzonemgr = NULL;
+/* create and release a zone */
+ISC_LOOP_TEST_IMPL(zonemgr_createzone) {
dns_zone_t *zone = NULL;
isc_result_t result;
UNUSED(arg);
- dns_zonemgr_create(isc_g_mctx, &myzonemgr);
+ dns_zonemgr_create(isc_g_mctx, &mgr);
- result = dns_test_makezone("foo", &zone, NULL, false);
- assert_int_equal(result, ISC_R_SUCCESS);
-
- assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0);
-
- /* Now it should succeed */
- result = dns_zonemgr_managezone(myzonemgr, zone);
+ result = dns_zonemgr_createzone(mgr, &zone);
assert_int_equal(result, ISC_R_SUCCESS);
+ assert_non_null(zone);
- assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 1);
+ assert_non_null(dns_zone_getloop(zone));
- dns_zonemgr_releasezone(myzonemgr, zone);
dns_zone_detach(&zone);
- assert_int_equal(dns_zonemgr_getcount(myzonemgr, DNS_ZONESTATE_ANY), 0);
-
- dns_zonemgr_shutdown(myzonemgr);
- dns_zonemgr_detach(&myzonemgr);
- assert_null(myzonemgr);
+ dns_zonemgr_shutdown(mgr);
+ assert_ptr_equal(dns_g_zonemgr, mgr);
isc_loopmgr_shutdown();
}
-/* create and release a zone */
-ISC_LOOP_TEST_IMPL(zonemgr_createzone) {
- dns_zonemgr_t *myzonemgr = NULL;
- dns_zone_t *zone = NULL;
- isc_result_t result;
-
+/* Both raw-zone construction paths must finish cleanup before destruction. */
+ISC_LOOP_TEST_IMPL(zonemgr_inline) {
+ dns_zone_t *zone = NULL, *raw = NULL;
UNUSED(arg);
+ dns_zonemgr_create(isc_g_mctx, &mgr);
- dns_zonemgr_create(isc_g_mctx, &myzonemgr);
-
- result = dns_zonemgr_createzone(myzonemgr, &zone);
- assert_int_equal(result, ISC_R_SUCCESS);
- assert_non_null(zone);
-
- result = dns_zonemgr_managezone(myzonemgr, zone);
- assert_int_equal(result, ISC_R_SUCCESS);
-
+ assert_int_equal(dns_zonemgr_createzone(mgr, &zone), ISC_R_SUCCESS);
+ dns_zone_create(&raw, isc_g_mctx, 0);
+ assert_int_equal(dns_zone_link(zone, raw), ISC_R_SUCCESS);
+ assert_ptr_equal(dns_zone_getloop(zone), dns_zone_getloop(raw));
+ dns_zone_detach(&raw);
dns_zone_detach(&zone);
- dns_zonemgr_shutdown(myzonemgr);
- dns_zonemgr_detach(&myzonemgr);
- assert_null(myzonemgr);
+ assert_int_equal(dns_zonemgr_createzone(mgr, &zone), ISC_R_SUCCESS);
+ assert_int_equal(dns_zonemgr_createzone(mgr, &raw), ISC_R_SUCCESS);
+ assert_int_equal(dns_zone_link(zone, raw), ISC_R_SUCCESS);
+ assert_ptr_equal(dns_zone_getloop(zone), dns_zone_getloop(raw));
+ dns_zonemgr_shutdown(mgr);
+ /* Shutdown leaves shared services allocated while zones finish cleanup.
+ */
+ assert_non_null(dns_g_zonemgr);
+ dns_zone_detach(&raw);
+ dns_zone_detach(&zone);
isc_loopmgr_shutdown();
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY_CUSTOM(zonemgr_create, setup_test, teardown_test)
-ISC_TEST_ENTRY_CUSTOM(zonemgr_managezone, setup_test, teardown_test)
ISC_TEST_ENTRY_CUSTOM(zonemgr_createzone, setup_test, teardown_test)
+ISC_TEST_ENTRY_CUSTOM(zonemgr_inline, setup_test, teardown_test)
ISC_TEST_LIST_END
ISC_TEST_MAIN
diff --git a/tests/dns/zt_test.c b/tests/dns/zt_test.c
index 539ad0ced6..26d994c3b2 100644
--- a/tests/dns/zt_test.c
+++ b/tests/dns/zt_test.c
@@ -46,6 +46,13 @@ static dns_db_t *db = NULL;
static FILE *zonefile, *origfile;
static dns_view_t *view = NULL;
+static int
+teardown_test(void **state) {
+ teardown_managers(state);
+ dns_test_destroyzonemgr();
+ return 0;
+}
+
static isc_result_t
count_zone(dns_zone_t *zone, void *uap) {
int *nzones = (int *)uap;
@@ -78,13 +85,6 @@ ISC_LOOP_TEST_IMPL(apply) {
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(nzones, 1);
- /* These steps are necessary so the zone can be detached properly */
- dns_test_setupzonemgr();
- result = dns_test_managezone(zone);
- assert_int_equal(result, ISC_R_SUCCESS);
- dns_test_releasezone(zone);
- dns_test_closezonemgr();
-
/* The view was left attached in dns_test_makezone() */
dns_view_detach(&view);
dns_zone_detach(&zone);
@@ -105,7 +105,6 @@ load_done_last(void *uap) {
dns_db_detach(&db);
}
- dns_test_releasezone(zone);
dns_test_closezonemgr();
dns_zone_detach(&zone);
@@ -156,6 +155,7 @@ load_done_first(void *uap) {
/* asynchronous zone load */
ISC_LOOP_TEST_IMPL(asyncload_zone) {
+ dns_test_setupzonemgr();
isc_result_t result;
int n;
dns_zone_t *zone = NULL;
@@ -165,10 +165,6 @@ ISC_LOOP_TEST_IMPL(asyncload_zone) {
result = dns_test_makezone("foo", &zone, NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
- dns_test_setupzonemgr();
- result = dns_test_managezone(zone);
- assert_int_equal(result, ISC_R_SUCCESS);
-
view = dns_zone_getview(zone);
rcu_read_lock();
zt = rcu_dereference(view->zonetable);
@@ -212,9 +208,6 @@ all_done(void *arg ISC_ATTR_UNUSED) {
dns_db_detach(&db);
}
- dns_test_releasezone(zone3);
- dns_test_releasezone(zone2);
- dns_test_releasezone(zone1);
dns_test_closezonemgr();
dns_zone_detach(&zone1);
@@ -232,6 +225,7 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
dns_zt_t *zt = NULL;
atomic_bool done;
+ dns_test_setupzonemgr();
atomic_init(&done, false);
result = dns_test_makezone("foo", &zone1, NULL, true);
@@ -256,14 +250,6 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
rcu_read_unlock();
assert_non_null(zt);
- dns_test_setupzonemgr();
- result = dns_test_managezone(zone1);
- assert_int_equal(result, ISC_R_SUCCESS);
- result = dns_test_managezone(zone2);
- assert_int_equal(result, ISC_R_SUCCESS);
- result = dns_test_managezone(zone3);
- assert_int_equal(result, ISC_R_SUCCESS);
-
assert_false(dns__zone_loadpending(zone1));
assert_false(dns__zone_loadpending(zone2));
assert_false(atomic_load(&done));
@@ -275,9 +261,9 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
}
ISC_TEST_LIST_START
-ISC_TEST_ENTRY_CUSTOM(apply, setup_managers, teardown_managers)
-ISC_TEST_ENTRY_CUSTOM(asyncload_zone, setup_managers, teardown_managers)
-ISC_TEST_ENTRY_CUSTOM(asyncload_zt, setup_managers, teardown_managers)
+ISC_TEST_ENTRY_CUSTOM(apply, setup_managers, teardown_test)
+ISC_TEST_ENTRY_CUSTOM(asyncload_zone, setup_managers, teardown_test)
+ISC_TEST_ENTRY_CUSTOM(asyncload_zt, setup_managers, teardown_test)
ISC_TEST_LIST_END
ISC_TEST_MAIN
diff --git a/tests/include/tests/dns.h b/tests/include/tests/dns.h
index 2ce75fcc96..7ff9a0fab7 100644
--- a/tests/include/tests/dns.h
+++ b/tests/include/tests/dns.h
@@ -73,14 +73,13 @@ dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view,
void
dns_test_setupzonemgr(void);
-isc_result_t
-dns_test_managezone(dns_zone_t *zone);
-
+/* Stop services while the event loops are running. */
void
-dns_test_releasezone(dns_zone_t *zone);
+dns_test_closezonemgr(void);
+/* Destroy services after the event loops have drained. */
void
-dns_test_closezonemgr(void);
+dns_test_destroyzonemgr(void);
void
dns_test_nap(uint32_t usec);
diff --git a/tests/libtest/dns.c b/tests/libtest/dns.c
index e98b0e15b1..098b68445a 100644
--- a/tests/libtest/dns.c
+++ b/tests/libtest/dns.c
@@ -112,7 +112,11 @@ dns_test_makezone(const char *name, dns_zone_t **zonep, dns_view_t *view,
/*
* Create the zone structure.
*/
- dns_zone_create(&zone, isc_g_mctx, 0);
+ if (zonemgr != NULL) {
+ RETERR(dns_zonemgr_createzone(zonemgr, &zone));
+ } else {
+ dns_zone_create(&zone, isc_g_mctx, 0);
+ }
/*
* Set zone type and origin.
@@ -164,27 +168,18 @@ dns_test_setupzonemgr(void) {
dns_zonemgr_create(isc_g_mctx, &zonemgr);
}
-isc_result_t
-dns_test_managezone(dns_zone_t *zone) {
- isc_result_t result;
- REQUIRE(zonemgr != NULL);
-
- result = dns_zonemgr_managezone(zonemgr, zone);
- return result;
-}
-
-void
-dns_test_releasezone(dns_zone_t *zone) {
- REQUIRE(zonemgr != NULL);
- dns_zonemgr_releasezone(zonemgr, zone);
-}
-
void
dns_test_closezonemgr(void) {
REQUIRE(zonemgr != NULL);
dns_zonemgr_shutdown(zonemgr);
- dns_zonemgr_detach(&zonemgr);
+}
+
+void
+dns_test_destroyzonemgr(void) {
+ if (zonemgr != NULL) {
+ dns_zonemgr_destroy(&zonemgr);
+ }
}
/*
diff --git a/tests/libtest/ns.c b/tests/libtest/ns.c
index 8b2ace5959..fb149c19a0 100644
--- a/tests/libtest/ns.c
+++ b/tests/libtest/ns.c
@@ -87,6 +87,16 @@ scan_interfaces(void *arg) {
ns_interfacemgr_scan(interfacemgr, true, false);
}
+static void
+setup_zone_services(void *arg ISC_ATTR_UNUSED) {
+ dns_test_setupzonemgr();
+}
+
+static void
+shutdown_zone_services(void *arg ISC_ATTR_UNUSED) {
+ dns_test_closezonemgr();
+}
+
int
setup_server(void **state) {
isc_result_t result;
@@ -99,7 +109,9 @@ setup_server(void **state) {
CHECK(ns_interfacemgr_create(isc_g_mctx, sctx, dispatchmgr, NULL,
&interfacemgr));
+ isc_loop_setup(isc_loop_main(), setup_zone_services, NULL);
isc_loop_setup(isc_loop_main(), scan_interfaces, NULL);
+ isc_loop_teardown(isc_loop_main(), shutdown_zone_services, NULL);
return 0;
@@ -129,15 +141,22 @@ teardown_server(void **state) {
}
teardown_managers(state);
+ dns_test_destroyzonemgr();
return 0;
}
static dns_zone_t *served_zone = NULL;
+static void
+free_test_zone_hooks(isc_mem_t *mctx ISC_ATTR_UNUSED, void **tablep) {
+ /* Test hook tables are allocated from isc_g_mctx, not the zone pool. */
+ ns_hooktable_free(isc_g_mctx, tablep);
+}
+
void
ns_test_serve_zone_sethooktab(ns_hooktable_t *hooktab) {
static const dns_zone_ops_t ops = {
- .hooktable_free = ns_hooktable_free,
+ .hooktable_free = free_test_zone_hooks,
};
dns_zone_setops(served_zone, &ops);
@@ -150,24 +169,8 @@ ns_test_serve_zone(const char *zonename, const char *filename,
isc_result_t result;
dns_db_t *db = NULL;
- /*
- * Prepare zone structure for further processing.
- */
RETERR(dns_test_makezone(zonename, &served_zone, view, false));
- /*
- * Start zone manager.
- */
- dns_test_setupzonemgr();
-
- /*
- * Add the zone to the zone manager.
- */
- result = dns_test_managezone(served_zone);
- if (result != ISC_R_SUCCESS) {
- goto close_zonemgr;
- }
-
view->nocookieudp = 512;
/*
@@ -194,19 +197,15 @@ ns_test_serve_zone(const char *zonename, const char *filename,
return ISC_R_SUCCESS;
release_zone:
- dns_test_releasezone(served_zone);
-close_zonemgr:
- dns_test_closezonemgr();
- dns_zone_detach(&served_zone);
+ if (served_zone != NULL) {
+ dns_zone_detach(&served_zone);
+ }
return result;
}
void
ns_test_cleanup_zone(void) {
- dns_test_releasezone(served_zone);
- dns_test_closezonemgr();
-
dns_zone_detach(&served_zone);
}