]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Split NZD functions into a separate compilation unit
authorOndřej Surý <ondrej@isc.org>
Sun, 15 Mar 2026 04:05:09 +0000 (05:05 +0100)
committerOndřej Surý <ondrej@sury.org>
Wed, 18 Mar 2026 10:02:33 +0000 (11:02 +0100)
Move all LMDB-based new zone database functions from server.c into
nzd.c to reduce the size of server.c and isolate the NZD/LMDB
interface. Rename load_nzf() to nzd_load_nzf() to match the nzd_
namespace.

bin/named/include/named/nzd.h [new file with mode: 0644]
bin/named/meson.build
bin/named/nzd.c [new file with mode: 0644]
bin/named/server.c

diff --git a/bin/named/include/named/nzd.h b/bin/named/include/named/nzd.h
new file mode 100644 (file)
index 0000000..a796369
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <lmdb.h>
+
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/result.h>
+
+#include <dns/view.h>
+
+#define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r')
+
+typedef struct {
+       unsigned int  magic;
+       isc_buffer_t *text;
+       isc_result_t  result;
+} ns_dzarg_t;
+
+isc_result_t
+nzd_writable(dns_view_t *view);
+
+isc_result_t
+nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);
+
+isc_result_t
+nzd_env_reopen(dns_view_t *view);
+
+void
+nzd_env_close(dns_view_t *view);
+
+isc_result_t
+nzd_close(MDB_txn **txnp, bool commit);
+
+isc_result_t
+nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
+        const cfg_obj_t *zconfig);
+
+isc_result_t
+nzd_load_nzf(dns_view_t *view);
+
+void
+nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen);
index bf9e8f9dbf3d42d46db3d963235997c2e112cd49..18b221ab62072b0469b744881da61007ebb30a72 100644 (file)
@@ -32,6 +32,7 @@ named_srcset.add(
         'log.c',
         'logconf.c',
         'main.c',
+        'nzd.c',
         'os.c',
         'server.c',
         'statschannel.c',
diff --git a/bin/named/nzd.c b/bin/named/nzd.c
new file mode 100644 (file)
index 0000000..f3707e4
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * 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.
+ */
+
+#include <lmdb.h>
+
+#include <isc/file.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/zone.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/namedconf.h>
+
+#include <named/nzd.h>
+#include <named/os.h>
+
+void
+nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) {
+       dns_fixedname_t fixed;
+
+       dns_fixedname_init(&fixed);
+       dns_name_downcase(name, dns_fixedname_name(&fixed));
+       dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen);
+
+       key->mv_data = namebuf;
+       key->mv_size = strlen(namebuf);
+}
+
+static void
+dumpzone(void *arg, const char *buf, int len) {
+       ns_dzarg_t *dzarg = arg;
+       isc_result_t result;
+
+       REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC));
+
+       result = isc_buffer_reserve(dzarg->text, (unsigned int)len);
+       if (result == ISC_R_SUCCESS) {
+               isc_buffer_putmem(dzarg->text, (const unsigned char *)buf, len);
+       } else if (dzarg->result == ISC_R_SUCCESS) {
+               dzarg->result = result;
+       }
+}
+
+isc_result_t
+nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
+        const cfg_obj_t *zconfig) {
+       isc_result_t result;
+       int status;
+       dns_view_t *view;
+       bool commit = false;
+       isc_buffer_t *text = NULL;
+       char namebuf[1024];
+       MDB_val key, data;
+       ns_dzarg_t dzarg;
+
+       view = dns_zone_getview(zone);
+
+       nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf));
+
+       if (zconfig == NULL) {
+               /* We're deleting the zone from the database */
+               status = mdb_del(*txnp, dbi, &key, NULL);
+               if (status != MDB_SUCCESS && status != MDB_NOTFOUND) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error deleting zone %s "
+                                     "from NZD database: %s",
+                                     namebuf, mdb_strerror(status));
+                       CLEANUP(ISC_R_FAILURE);
+               } else if (status != MDB_NOTFOUND) {
+                       commit = true;
+               }
+       } else {
+               /* We're creating or overwriting the zone */
+               const cfg_obj_t *zoptions = cfg_tuple_get(zconfig, "options");
+
+               isc_buffer_allocate(view->mctx, &text, 256);
+               if (zoptions == NULL) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Unable to get options from config in "
+                                     "nzd_save()");
+                       CLEANUP(ISC_R_FAILURE);
+               }
+
+               dzarg.magic = DZARG_MAGIC;
+               dzarg.text = text;
+               dzarg.result = ISC_R_SUCCESS;
+               cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
+               if (dzarg.result != ISC_R_SUCCESS) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error writing zone config to "
+                                     "buffer in nzd_save(): %s",
+                                     isc_result_totext(dzarg.result));
+                       CHECK(dzarg.result);
+               }
+
+               data.mv_data = isc_buffer_base(text);
+               data.mv_size = isc_buffer_usedlength(text);
+
+               status = mdb_put(*txnp, dbi, &key, &data, 0);
+               if (status != MDB_SUCCESS) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error inserting zone in "
+                                     "NZD database: %s",
+                                     mdb_strerror(status));
+                       CLEANUP(ISC_R_FAILURE);
+               }
+
+               commit = true;
+       }
+
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       if (!commit || result != ISC_R_SUCCESS) {
+               (void)mdb_txn_abort(*txnp);
+       } else {
+               status = mdb_txn_commit(*txnp);
+               if (status != MDB_SUCCESS) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error committing "
+                                     "NZD database: %s",
+                                     mdb_strerror(status));
+                       result = ISC_R_FAILURE;
+               }
+       }
+       *txnp = NULL;
+
+       if (text != NULL) {
+               isc_buffer_free(&text);
+       }
+
+       return result;
+}
+
+/*
+ * Check whether the new zone database for 'view' can be opened for writing.
+ *
+ * Caller must hold 'view->newzone.lock'.
+ */
+isc_result_t
+nzd_writable(dns_view_t *view) {
+       isc_result_t result = ISC_R_SUCCESS;
+       int status;
+       MDB_dbi dbi;
+       MDB_txn *txn = NULL;
+
+       REQUIRE(view != NULL);
+
+       status = mdb_txn_begin(view->newzone.dbenv, 0, 0, &txn);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                             ISC_LOG_WARNING, "mdb_txn_begin: %s",
+                             mdb_strerror(status));
+               return ISC_R_FAILURE;
+       }
+
+       status = mdb_dbi_open(txn, NULL, 0, &dbi);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                             ISC_LOG_WARNING, "mdb_dbi_open: %s",
+                             mdb_strerror(status));
+               result = ISC_R_FAILURE;
+       }
+
+       mdb_txn_abort(txn);
+       return result;
+}
+
+/*
+ * Open the new zone database for 'view' and start a transaction for it.
+ *
+ * Caller must hold 'view->newzone.lock'.
+ */
+isc_result_t
+nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
+       int status;
+       MDB_txn *txn = NULL;
+
+       REQUIRE(view != NULL);
+       REQUIRE(txnp != NULL && *txnp == NULL);
+       REQUIRE(dbi != NULL);
+
+       status = mdb_txn_begin(view->newzone.dbenv, 0, flags, &txn);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                             ISC_LOG_WARNING, "mdb_txn_begin: %s",
+                             mdb_strerror(status));
+               goto cleanup;
+       }
+
+       status = mdb_dbi_open(txn, NULL, 0, dbi);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                             ISC_LOG_WARNING, "mdb_dbi_open: %s",
+                             mdb_strerror(status));
+               goto cleanup;
+       }
+
+       *txnp = txn;
+
+cleanup:
+       if (status != MDB_SUCCESS) {
+               if (txn != NULL) {
+                       mdb_txn_abort(txn);
+               }
+               return ISC_R_FAILURE;
+       }
+
+       return ISC_R_SUCCESS;
+}
+
+/*
+ * nzd_env_close() and nzd_env_reopen() are a kluge to address the
+ * problem of an NZD file possibly being created before we drop
+ * root privileges.
+ */
+void
+nzd_env_close(dns_view_t *view) {
+       const char *dbpath = NULL;
+       char dbpath_copy[PATH_MAX];
+       char lockpath[PATH_MAX];
+       int status, ret;
+
+       if (view->newzone.dbenv == NULL) {
+               return;
+       }
+
+       status = mdb_env_get_path(view->newzone.dbenv, &dbpath);
+       INSIST(status == MDB_SUCCESS);
+       snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath);
+       strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy));
+       mdb_env_close(view->newzone.dbenv);
+
+       /*
+        * Database files must be owned by the eventual user, not by root.
+        */
+       ret = chown(dbpath_copy, named_os_uid(), -1);
+       UNUSED(ret);
+
+       /*
+        * Some platforms need the lockfile not to exist when we reopen the
+        * environment.
+        */
+       (void)isc_file_remove(lockpath);
+
+       view->newzone.dbenv = NULL;
+}
+
+isc_result_t
+nzd_env_reopen(dns_view_t *view) {
+       isc_result_t result;
+       MDB_env *env = NULL;
+       int status;
+
+       if (view->newzone.db == NULL) {
+               return ISC_R_SUCCESS;
+       }
+
+       nzd_env_close(view);
+
+       status = mdb_env_create(&env);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER,
+                             ISC_LOG_ERROR, "mdb_env_create failed: %s",
+                             mdb_strerror(status));
+               CLEANUP(ISC_R_FAILURE);
+       }
+
+       if (view->newzone.mapsize != 0ULL) {
+               status = mdb_env_set_mapsize(env, view->newzone.mapsize);
+               if (status != MDB_SUCCESS) {
+                       isc_log_write(DNS_LOGCATEGORY_GENERAL,
+                                     ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
+                                     "mdb_env_set_mapsize failed: %s",
+                                     mdb_strerror(status));
+                       CLEANUP(ISC_R_FAILURE);
+               }
+       }
+
+       status = mdb_env_open(env, view->newzone.db, DNS_LMDB_FLAGS, 0600);
+       if (status != MDB_SUCCESS) {
+               isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER,
+                             ISC_LOG_ERROR, "mdb_env_open of '%s' failed: %s",
+                             view->newzone.db, mdb_strerror(status));
+               CLEANUP(ISC_R_FAILURE);
+       }
+
+       view->newzone.dbenv = env;
+       env = NULL;
+       result = ISC_R_SUCCESS;
+
+cleanup:
+       if (env != NULL) {
+               mdb_env_close(env);
+       }
+       return result;
+}
+
+/*
+ * If 'commit' is true, commit the new zone database transaction pointed to by
+ * 'txnp'; otherwise, abort that transaction.
+ *
+ * Caller must hold 'view->newzone.lock' for the view that the transaction
+ * pointed to by 'txnp' was started for.
+ */
+isc_result_t
+nzd_close(MDB_txn **txnp, bool commit) {
+       isc_result_t result = ISC_R_SUCCESS;
+       int status;
+
+       REQUIRE(txnp != NULL);
+
+       if (*txnp != NULL) {
+               if (commit) {
+                       status = mdb_txn_commit(*txnp);
+                       if (status != MDB_SUCCESS) {
+                               result = ISC_R_FAILURE;
+                       }
+               } else {
+                       mdb_txn_abort(*txnp);
+               }
+               *txnp = NULL;
+       }
+
+       return result;
+}
+
+/*
+ * If there's an existing NZF file, load it and migrate its data
+ * to the NZD.
+ *
+ * Caller must hold view->newzone.lock.
+ */
+isc_result_t
+nzd_load_nzf(dns_view_t *view) {
+       isc_result_t result;
+       cfg_obj_t *nzf_config = NULL;
+       int status;
+       isc_buffer_t *text = NULL;
+       bool commit = false;
+       const cfg_obj_t *zonelist = NULL;
+       char tempname[PATH_MAX];
+       MDB_txn *txn = NULL;
+       MDB_dbi dbi;
+       MDB_val key, data;
+       ns_dzarg_t dzarg;
+
+       /*
+        * If NZF file doesn't exist, or NZD DB exists and already
+        * has data, return without attempting migration.
+        */
+       if (!isc_file_exists(view->newzone.file)) {
+               result = ISC_R_SUCCESS;
+               goto cleanup;
+       }
+
+       isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                     ISC_LOG_INFO,
+                     "Migrating zones from NZF file '%s' to "
+                     "NZD database '%s'",
+                     view->newzone.file, view->newzone.db);
+       /*
+        * Instead of blindly copying lines, we parse the NZF file using
+        * the configuration parser, because it validates it against the
+        * config type, giving us a guarantee that valid configuration
+        * will be written to DB.
+        */
+       result = cfg_parse_file(view->newzone.file, &cfg_type_addzoneconf, 0,
+                               &nzf_config);
+       if (result != ISC_R_SUCCESS) {
+               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
+                             ISC_LOG_ERROR, "Error parsing NZF file '%s': %s",
+                             view->newzone.file, isc_result_totext(result));
+               goto cleanup;
+       }
+
+       zonelist = NULL;
+       CHECK(cfg_map_get(nzf_config, "zone", &zonelist));
+       if (!cfg_obj_islist(zonelist)) {
+               CLEANUP(ISC_R_FAILURE);
+       }
+
+       CHECK(nzd_open(view, 0, &txn, &dbi));
+
+       isc_buffer_allocate(view->mctx, &text, 256);
+
+       CFG_LIST_FOREACH(zonelist, element) {
+               const cfg_obj_t *zconfig = cfg_listelt_value(element);
+               const cfg_obj_t *zoptions;
+               char zname[DNS_NAME_FORMATSIZE];
+               dns_fixedname_t fname;
+               dns_name_t *name = NULL;
+               const char *origin = NULL;
+               isc_buffer_t b;
+
+               origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+               if (origin == NULL) {
+                       CLEANUP(ISC_R_FAILURE);
+               }
+
+               /* Normalize zone name */
+               isc_buffer_constinit(&b, origin, strlen(origin));
+               isc_buffer_add(&b, strlen(origin));
+               name = dns_fixedname_initname(&fname);
+               CHECK(dns_name_fromtext(name, &b, dns_rootname,
+                                       DNS_NAME_DOWNCASE));
+               dns_name_format(name, zname, sizeof(zname));
+
+               key.mv_data = zname;
+               key.mv_size = strlen(zname);
+
+               zoptions = cfg_tuple_get(zconfig, "options");
+               if (zoptions == NULL) {
+                       CLEANUP(ISC_R_FAILURE);
+               }
+
+               isc_buffer_clear(text);
+               dzarg.magic = DZARG_MAGIC;
+               dzarg.text = text;
+               dzarg.result = ISC_R_SUCCESS;
+               cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
+               if (dzarg.result != ISC_R_SUCCESS) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error writing zone config to "
+                                     "buffer in load_nzf(): %s",
+                                     isc_result_totext(result));
+                       CHECK(dzarg.result);
+               }
+
+               data.mv_data = isc_buffer_base(text);
+               data.mv_size = isc_buffer_usedlength(text);
+
+               status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
+               if (status != MDB_SUCCESS) {
+                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
+                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
+                                     "Error inserting zone in "
+                                     "NZD database: %s",
+                                     mdb_strerror(status));
+                       CLEANUP(ISC_R_FAILURE);
+               }
+
+               commit = true;
+       }
+
+       result = ISC_R_SUCCESS;
+
+       /*
+        * Leaving the NZF file in place is harmless as we won't use it
+        * if an NZD database is found for the view. But we rename NZF file
+        * to a backup name here.
+        */
+       strlcpy(tempname, view->newzone.file, sizeof(tempname));
+       if (strlen(tempname) < sizeof(tempname) - 1) {
+               strlcat(tempname, "~", sizeof(tempname));
+               isc_file_rename(view->newzone.file, tempname);
+       }
+
+cleanup:
+       if (result != ISC_R_SUCCESS) {
+               (void)nzd_close(&txn, false);
+       } else {
+               result = nzd_close(&txn, commit);
+       }
+
+       if (text != NULL) {
+               isc_buffer_free(&text);
+       }
+
+       if (nzf_config != NULL) {
+               cfg_obj_detach(&nzf_config);
+       }
+
+       return result;
+}
index 24432cdfac2c26f221c4ab188c8de822ad78e668..14c8d48bc39e238f800e509b3808e7c5f01e6fab 100644 (file)
 
 #include <named/config.h>
 #include <named/control.h>
+#include <named/nzd.h>
 #if defined(HAVE_GEOIP2)
 #include <named/geoip.h>
 #endif /* HAVE_GEOIP2 */
 #define JEMALLOC_API_SUPPORTED 1
 #endif
 
-#include <lmdb.h>
-
 #ifndef SIZE_MAX
 #define SIZE_MAX ((size_t)(-1))
 #endif /* ifndef SIZE_MAX */
@@ -326,13 +325,6 @@ typedef enum {
        CATZ_DELZONE,
 } catz_type_t;
 
-typedef struct {
-       unsigned int magic;
-#define DZARG_MAGIC ISC_MAGIC('D', 'z', 'a', 'r')
-       isc_buffer_t *text;
-       isc_result_t result;
-} ns_dzarg_t;
-
 typedef enum {
        MEMPROF_UNSUPPORTED = 0x00,
        MEMPROF_INACTIVE = 0x01,
@@ -492,24 +484,6 @@ putuint8(isc_buffer_t *b, uint8_t val);
 static isc_result_t
 putnull(isc_buffer_t *b);
 
-static isc_result_t
-nzd_writable(dns_view_t *view);
-
-static isc_result_t
-nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi);
-
-static isc_result_t
-nzd_env_reopen(dns_view_t *view);
-
-static void
-nzd_env_close(dns_view_t *view);
-
-static isc_result_t
-nzd_close(MDB_txn **txnp, bool commit);
-
-static isc_result_t
-load_nzf(dns_view_t *view);
-
 /*%
  * Configure a single view ACL at '*aclp'.  Get its configuration from
  * 'vconfig' (for per-view configuration) and maybe from 'config'
@@ -7155,7 +7129,7 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig) {
        }
 
        if (view->newzone.allowed) {
-               result = load_nzf(view);
+               result = nzd_load_nzf(view);
        }
        return result;
 
@@ -11915,470 +11889,6 @@ named_smf_add_message(isc_buffer_t *text) {
 }
 #endif /* HAVE_LIBSCF */
 
-static void
-nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) {
-       dns_fixedname_t fixed;
-
-       dns_fixedname_init(&fixed);
-       dns_name_downcase(name, dns_fixedname_name(&fixed));
-       dns_name_format(dns_fixedname_name(&fixed), namebuf, buflen);
-
-       key->mv_data = namebuf;
-       key->mv_size = strlen(namebuf);
-}
-
-static void
-dumpzone(void *arg, const char *buf, int len) {
-       ns_dzarg_t *dzarg = arg;
-       isc_result_t result;
-
-       REQUIRE(dzarg != NULL && ISC_MAGIC_VALID(dzarg, DZARG_MAGIC));
-
-       result = putmem(dzarg->text, buf, len);
-       if (result != ISC_R_SUCCESS && dzarg->result == ISC_R_SUCCESS) {
-               dzarg->result = result;
-       }
-}
-
-static isc_result_t
-nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
-        const cfg_obj_t *zconfig) {
-       isc_result_t result;
-       int status;
-       dns_view_t *view;
-       bool commit = false;
-       isc_buffer_t *text = NULL;
-       char namebuf[1024];
-       MDB_val key, data;
-       ns_dzarg_t dzarg;
-
-       view = dns_zone_getview(zone);
-
-       nzd_setkey(&key, dns_zone_getorigin(zone), namebuf, sizeof(namebuf));
-
-       if (zconfig == NULL) {
-               /* We're deleting the zone from the database */
-               status = mdb_del(*txnp, dbi, &key, NULL);
-               if (status != MDB_SUCCESS && status != MDB_NOTFOUND) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error deleting zone %s "
-                                     "from NZD database: %s",
-                                     namebuf, mdb_strerror(status));
-                       CLEANUP(ISC_R_FAILURE);
-               } else if (status != MDB_NOTFOUND) {
-                       commit = true;
-               }
-       } else {
-               /* We're creating or overwriting the zone */
-               const cfg_obj_t *zoptions = cfg_tuple_get(zconfig, "options");
-
-               isc_buffer_allocate(view->mctx, &text, 256);
-               if (zoptions == NULL) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Unable to get options from config in "
-                                     "nzd_save()");
-                       CLEANUP(ISC_R_FAILURE);
-               }
-
-               dzarg.magic = DZARG_MAGIC;
-               dzarg.text = text;
-               dzarg.result = ISC_R_SUCCESS;
-               cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
-               if (dzarg.result != ISC_R_SUCCESS) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error writing zone config to "
-                                     "buffer in nzd_save(): %s",
-                                     isc_result_totext(dzarg.result));
-                       CHECK(dzarg.result);
-               }
-
-               data.mv_data = isc_buffer_base(text);
-               data.mv_size = isc_buffer_usedlength(text);
-
-               status = mdb_put(*txnp, dbi, &key, &data, 0);
-               if (status != MDB_SUCCESS) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error inserting zone in "
-                                     "NZD database: %s",
-                                     mdb_strerror(status));
-                       CLEANUP(ISC_R_FAILURE);
-               }
-
-               commit = true;
-       }
-
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       if (!commit || result != ISC_R_SUCCESS) {
-               (void)mdb_txn_abort(*txnp);
-       } else {
-               status = mdb_txn_commit(*txnp);
-               if (status != MDB_SUCCESS) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error committing "
-                                     "NZD database: %s",
-                                     mdb_strerror(status));
-                       result = ISC_R_FAILURE;
-               }
-       }
-       *txnp = NULL;
-
-       if (text != NULL) {
-               isc_buffer_free(&text);
-       }
-
-       return result;
-}
-
-/*
- * Check whether the new zone database for 'view' can be opened for writing.
- *
- * Caller must hold 'view->newzone.lock'.
- */
-static isc_result_t
-nzd_writable(dns_view_t *view) {
-       isc_result_t result = ISC_R_SUCCESS;
-       int status;
-       MDB_dbi dbi;
-       MDB_txn *txn = NULL;
-
-       REQUIRE(view != NULL);
-
-       status = mdb_txn_begin(view->newzone.dbenv, 0, 0, &txn);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_WARNING, "mdb_txn_begin: %s",
-                             mdb_strerror(status));
-               return ISC_R_FAILURE;
-       }
-
-       status = mdb_dbi_open(txn, NULL, 0, &dbi);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_WARNING, "mdb_dbi_open: %s",
-                             mdb_strerror(status));
-               result = ISC_R_FAILURE;
-       }
-
-       mdb_txn_abort(txn);
-       return result;
-}
-
-/*
- * Open the new zone database for 'view' and start a transaction for it.
- *
- * Caller must hold 'view->newzone.lock'.
- */
-static isc_result_t
-nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) {
-       int status;
-       MDB_txn *txn = NULL;
-
-       REQUIRE(view != NULL);
-       REQUIRE(txnp != NULL && *txnp == NULL);
-       REQUIRE(dbi != NULL);
-
-       status = mdb_txn_begin(view->newzone.dbenv, 0, flags, &txn);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_WARNING, "mdb_txn_begin: %s",
-                             mdb_strerror(status));
-               goto cleanup;
-       }
-
-       status = mdb_dbi_open(txn, NULL, 0, dbi);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_WARNING, "mdb_dbi_open: %s",
-                             mdb_strerror(status));
-               goto cleanup;
-       }
-
-       *txnp = txn;
-
-cleanup:
-       if (status != MDB_SUCCESS) {
-               if (txn != NULL) {
-                       mdb_txn_abort(txn);
-               }
-               return ISC_R_FAILURE;
-       }
-
-       return ISC_R_SUCCESS;
-}
-
-/*
- * nzd_env_close() and nzd_env_reopen() are a kluge to address the
- * problem of an NZD file possibly being created before we drop
- * root privileges.
- */
-static void
-nzd_env_close(dns_view_t *view) {
-       const char *dbpath = NULL;
-       char dbpath_copy[PATH_MAX];
-       char lockpath[PATH_MAX];
-       int status, ret;
-
-       if (view->newzone.dbenv == NULL) {
-               return;
-       }
-
-       status = mdb_env_get_path(view->newzone.dbenv, &dbpath);
-       INSIST(status == MDB_SUCCESS);
-       snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath);
-       strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy));
-       mdb_env_close(view->newzone.dbenv);
-
-       /*
-        * Database files must be owned by the eventual user, not by root.
-        */
-       ret = chown(dbpath_copy, named_os_uid(), -1);
-       UNUSED(ret);
-
-       /*
-        * Some platforms need the lockfile not to exist when we reopen the
-        * environment.
-        */
-       (void)isc_file_remove(lockpath);
-
-       view->newzone.dbenv = NULL;
-}
-
-static isc_result_t
-nzd_env_reopen(dns_view_t *view) {
-       isc_result_t result;
-       MDB_env *env = NULL;
-       int status;
-
-       if (view->newzone.db == NULL) {
-               return ISC_R_SUCCESS;
-       }
-
-       nzd_env_close(view);
-
-       status = mdb_env_create(&env);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER,
-                             ISC_LOG_ERROR, "mdb_env_create failed: %s",
-                             mdb_strerror(status));
-               CLEANUP(ISC_R_FAILURE);
-       }
-
-       if (view->newzone.mapsize != 0ULL) {
-               status = mdb_env_set_mapsize(env, view->newzone.mapsize);
-               if (status != MDB_SUCCESS) {
-                       isc_log_write(DNS_LOGCATEGORY_GENERAL,
-                                     ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
-                                     "mdb_env_set_mapsize failed: %s",
-                                     mdb_strerror(status));
-                       CLEANUP(ISC_R_FAILURE);
-               }
-       }
-
-       status = mdb_env_open(env, view->newzone.db, DNS_LMDB_FLAGS, 0600);
-       if (status != MDB_SUCCESS) {
-               isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER,
-                             ISC_LOG_ERROR, "mdb_env_open of '%s' failed: %s",
-                             view->newzone.db, mdb_strerror(status));
-               CLEANUP(ISC_R_FAILURE);
-       }
-
-       view->newzone.dbenv = env;
-       env = NULL;
-       result = ISC_R_SUCCESS;
-
-cleanup:
-       if (env != NULL) {
-               mdb_env_close(env);
-       }
-       return result;
-}
-
-/*
- * If 'commit' is true, commit the new zone database transaction pointed to by
- * 'txnp'; otherwise, abort that transaction.
- *
- * Caller must hold 'view->newzone.lock' for the view that the transaction
- * pointed to by 'txnp' was started for.
- */
-static isc_result_t
-nzd_close(MDB_txn **txnp, bool commit) {
-       isc_result_t result = ISC_R_SUCCESS;
-       int status;
-
-       REQUIRE(txnp != NULL);
-
-       if (*txnp != NULL) {
-               if (commit) {
-                       status = mdb_txn_commit(*txnp);
-                       if (status != MDB_SUCCESS) {
-                               result = ISC_R_FAILURE;
-                       }
-               } else {
-                       mdb_txn_abort(*txnp);
-               }
-               *txnp = NULL;
-       }
-
-       return result;
-}
-
-/*
- * If there's an existing NZF file, load it and migrate its data
- * to the NZD.
- *
- * Caller must hold view->newzone.lock.
- */
-static isc_result_t
-load_nzf(dns_view_t *view) {
-       isc_result_t result;
-       cfg_obj_t *nzf_config = NULL;
-       int status;
-       isc_buffer_t *text = NULL;
-       bool commit = false;
-       const cfg_obj_t *zonelist = NULL;
-       char tempname[PATH_MAX];
-       MDB_txn *txn = NULL;
-       MDB_dbi dbi;
-       MDB_val key, data;
-       ns_dzarg_t dzarg;
-
-       /*
-        * If NZF file doesn't exist, or NZD DB exists and already
-        * has data, return without attempting migration.
-        */
-       if (!isc_file_exists(view->newzone.file)) {
-               result = ISC_R_SUCCESS;
-               goto cleanup;
-       }
-
-       isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                     ISC_LOG_INFO,
-                     "Migrating zones from NZF file '%s' to "
-                     "NZD database '%s'",
-                     view->newzone.file, view->newzone.db);
-       /*
-        * Instead of blindly copying lines, we parse the NZF file using
-        * the configuration parser, because it validates it against the
-        * config type, giving us a guarantee that valid configuration
-        * will be written to DB.
-        */
-       result = cfg_parse_file(view->newzone.file, &cfg_type_addzoneconf, 0,
-                               &nzf_config);
-       if (result != ISC_R_SUCCESS) {
-               isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
-                             ISC_LOG_ERROR, "Error parsing NZF file '%s': %s",
-                             view->newzone.file, isc_result_totext(result));
-               goto cleanup;
-       }
-
-       zonelist = NULL;
-       CHECK(cfg_map_get(nzf_config, "zone", &zonelist));
-       if (!cfg_obj_islist(zonelist)) {
-               CLEANUP(ISC_R_FAILURE);
-       }
-
-       CHECK(nzd_open(view, 0, &txn, &dbi));
-
-       isc_buffer_allocate(view->mctx, &text, 256);
-
-       CFG_LIST_FOREACH(zonelist, element) {
-               const cfg_obj_t *zconfig = cfg_listelt_value(element);
-               const cfg_obj_t *zoptions;
-               char zname[DNS_NAME_FORMATSIZE];
-               dns_fixedname_t fname;
-               dns_name_t *name = NULL;
-               const char *origin = NULL;
-               isc_buffer_t b;
-
-               origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
-               if (origin == NULL) {
-                       CLEANUP(ISC_R_FAILURE);
-               }
-
-               /* Normalize zone name */
-               isc_buffer_constinit(&b, origin, strlen(origin));
-               isc_buffer_add(&b, strlen(origin));
-               name = dns_fixedname_initname(&fname);
-               CHECK(dns_name_fromtext(name, &b, dns_rootname,
-                                       DNS_NAME_DOWNCASE));
-               dns_name_format(name, zname, sizeof(zname));
-
-               key.mv_data = zname;
-               key.mv_size = strlen(zname);
-
-               zoptions = cfg_tuple_get(zconfig, "options");
-               if (zoptions == NULL) {
-                       CLEANUP(ISC_R_FAILURE);
-               }
-
-               isc_buffer_clear(text);
-               dzarg.magic = DZARG_MAGIC;
-               dzarg.text = text;
-               dzarg.result = ISC_R_SUCCESS;
-               cfg_printx(zoptions, CFG_PRINTER_ONELINE, dumpzone, &dzarg);
-               if (dzarg.result != ISC_R_SUCCESS) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error writing zone config to "
-                                     "buffer in load_nzf(): %s",
-                                     isc_result_totext(result));
-                       CHECK(dzarg.result);
-               }
-
-               data.mv_data = isc_buffer_base(text);
-               data.mv_size = isc_buffer_usedlength(text);
-
-               status = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE);
-               if (status != MDB_SUCCESS) {
-                       isc_log_write(NAMED_LOGCATEGORY_GENERAL,
-                                     NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
-                                     "Error inserting zone in "
-                                     "NZD database: %s",
-                                     mdb_strerror(status));
-                       CLEANUP(ISC_R_FAILURE);
-               }
-
-               commit = true;
-       }
-
-       result = ISC_R_SUCCESS;
-
-       /*
-        * Leaving the NZF file in place is harmless as we won't use it
-        * if an NZD database is found for the view. But we rename NZF file
-        * to a backup name here.
-        */
-       strlcpy(tempname, view->newzone.file, sizeof(tempname));
-       if (strlen(tempname) < sizeof(tempname) - 1) {
-               strlcat(tempname, "~", sizeof(tempname));
-               isc_file_rename(view->newzone.file, tempname);
-       }
-
-cleanup:
-       if (result != ISC_R_SUCCESS) {
-               (void)nzd_close(&txn, false);
-       } else {
-               result = nzd_close(&txn, commit);
-       }
-
-       if (text != NULL) {
-               isc_buffer_free(&text);
-       }
-
-       if (nzf_config != NULL) {
-               cfg_obj_detach(&nzf_config);
-       }
-
-       return result;
-}
-
 static isc_result_t
 newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
              cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp,