From 7f8b972a3df68ed2df101e39d8e9434b1ca4237b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Sun, 15 Mar 2026 04:25:12 +0100 Subject: [PATCH 1/5] Remove NZF support, make LMDB required for new zone storage Drop the NZF (New Zone File) fallback for persisting runtime zone configurations, making LMDB (NZD) the only storage backend. This removes all #ifdef HAVE_LMDB conditionals, the meson 'lmdb' option, and the NZF-related functions. LMDB is now a mandatory build dependency. The named-nzd2nzf tool is now always built. --- .gitlab-ci.yml | 3 +- bin/include/defaultconfig.h | 8 +- bin/named/server.c | 344 +------------------------------- bin/tests/system/feature-test.c | 4 - bin/tools/meson.build | 1 - bin/tools/named-nzd2nzf.c | 4 - doc/man/meson.build | 4 +- lib/dns/include/dns/view.h | 2 - lib/dns/view.c | 7 +- lib/isccfg/namedconf.c | 5 - meson.build | 35 ++-- meson.options | 7 - 12 files changed, 21 insertions(+), 403 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43dc6bf398..02d3d03675 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1424,7 +1424,6 @@ unit:gcc:ossl3:amd64: artifacts: true # Jobs for regular GCC builds on Debian "sid" (amd64) -# Also tests configration option: -Dlmdb=disabled gcc:sid:amd64: <<: *debian_sid_amd64_image @@ -1432,7 +1431,7 @@ gcc:sid:amd64: variables: CC: gcc CFLAGS: "${CFLAGS_COMMON}" - EXTRA_CONFIGURE: "-Doptimization=3 -Didn=enabled -Dlmdb=disabled" + EXTRA_CONFIGURE: "-Doptimization=3 -Didn=enabled" system:gcc:sid:amd64: <<: *debian_sid_amd64_image diff --git a/bin/include/defaultconfig.h b/bin/include/defaultconfig.h index 8df5172bd7..d40b584d41 100644 --- a/bin/include/defaultconfig.h +++ b/bin/include/defaultconfig.h @@ -138,11 +138,9 @@ options {\n\ fetch-quota-params 100 0.1 0.3 0.7;\n\ fetches-per-server 0;\n\ fetches-per-zone 0;\n\ - lame-ttl 0;\n" -#ifdef HAVE_LMDB - " lmdb-mapsize 32M;\n" -#endif /* ifdef HAVE_LMDB */ - " max-cache-size default;\n\ + lame-ttl 0;\n\ + lmdb-mapsize 32M;\n\ + max-cache-size default;\n\ max-cache-ttl 604800; /* 1 week */\n\ max-clients-per-query 100;\n\ max-delegation-servers 13;\n\ diff --git a/bin/named/server.c b/bin/named/server.c index dcc2cfe40f..1207e8e033 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -145,14 +145,7 @@ #define JEMALLOC_API_SUPPORTED 1 #endif -#ifdef HAVE_LMDB #include -#define configure_newzones configure_newzones_db -#define dumpzone dumpzone_db -#else /* HAVE_LMDB */ -#define configure_newzones configure_newzones_file -#define dumpzone dumpzone_file -#endif /* HAVE_LMDB */ #ifndef SIZE_MAX #define SIZE_MAX ((size_t)(-1)) @@ -505,7 +498,6 @@ putuint8(isc_buffer_t *b, uint8_t val); static isc_result_t putnull(isc_buffer_t *b); -#ifdef HAVE_LMDB static isc_result_t nzd_writable(dns_view_t *view); @@ -520,10 +512,6 @@ nzd_env_close(dns_view_t *view); static isc_result_t nzd_close(MDB_txn **txnp, bool commit); -#else /* ifdef HAVE_LMDB */ -static isc_result_t -nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); -#endif /* ifdef HAVE_LMDB */ static isc_result_t load_nzf(dns_view_t *view); @@ -6984,12 +6972,10 @@ newzone_cleanup(dns_view_t *view) { cfg_obj_detach(&view->newzone.nzconfig); } -#ifdef HAVE_LMDB if (view->newzone.dbenv != NULL) { mdb_env_close(view->newzone.dbenv); view->newzone.dbenv = NULL; } -#endif /* ifdef HAVE_LMDB */ if (view->newzone.file != NULL) { isc_mem_free(view->mctx, view->newzone.file); @@ -7109,7 +7095,6 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig) { CHECK(nz_filename(view, "nzf", buffer, sizeof(buffer))); view->newzone.file = isc_mem_strdup(view->mctx, buffer); -#ifdef HAVE_LMDB uint64_t mapsize = 0ULL; obj = NULL; @@ -7169,7 +7154,6 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig) { view->newzone.dbenv = env; env = NULL; } -#endif /* HAVE_LMDB */ view->newzone.cleanup = newzone_cleanup; if (vconfig != NULL) { @@ -7226,46 +7210,6 @@ configure_zone_setviewcommit(isc_result_t result, const cfg_obj_t *zconfig, dns_view_detach(&pview); } -#ifndef HAVE_LMDB - -static isc_result_t -configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - cfg_aclconfctx_t *aclctx, dns_kasplist_t *kasplist) { - isc_result_t result; - const cfg_obj_t *zonelist = NULL; - - if (!view->newzone.allowed || view->newzone.nzconfig == NULL) { - /* New zones are disallowed, or the NZF file is empty */ - return ISC_R_SUCCESS; - } - - isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, - ISC_LOG_INFO, "loading additional zones for view '%s'", - view->name); - - zonelist = NULL; - cfg_map_get(view->newzone.nzconfig, "zone", &zonelist); - - CFG_LIST_FOREACH(zonelist, element) { - const cfg_obj_t *zconfig = cfg_listelt_value(element); - CHECK(configure_zone(config, zconfig, vconfig, view, - &named_g_server->viewlist, kasplist, - aclctx, true, false, false, false)); - } - - result = ISC_R_SUCCESS; - -cleanup: - CFG_LIST_FOREACH(zonelist, element) { - const cfg_obj_t *zconfig = cfg_listelt_value(element); - configure_zone_setviewcommit(result, zconfig, view); - } - - return result; -} - -#else /* HAVE_LMDB */ - static isc_result_t data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t *text, cfg_obj_t **zoneconfig) { @@ -7494,7 +7438,6 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, return result; } -#endif /* HAVE_LMDB */ #define APPLY_CONFIGURATION_SUBROUTINE_LOG \ isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, \ @@ -8378,7 +8321,6 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys, server->sctx->tkeyctx = tkeyctx; } -#ifdef HAVE_LMDB /* * If we're using LMDB, we may have created newzones databases * as root, making it impossible to reopen them later after @@ -8390,7 +8332,6 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys, nzd_env_close(view); } } -#endif /* HAVE_LMDB */ /* * Switch to the effective UID for setting up files. @@ -8412,7 +8353,6 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys, goto cleanup_cachelist; } -#ifdef HAVE_LMDB /* * Reopen NZD databases. */ @@ -8421,7 +8361,6 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys, nzd_env_reopen(view); } } -#endif /* HAVE_LMDB */ /* * Configure the logging system. @@ -11982,156 +11921,6 @@ named_smf_add_message(isc_buffer_t *text) { } #endif /* HAVE_LIBSCF */ -#ifndef HAVE_LMDB - -/* - * Emit a comment at the top of the nzf file containing the viewname - * Expects the fp to already be open for writing - */ -#define HEADER1 "# New zone file for view: " -#define HEADER2 \ - "\n# This file contains configuration for zones added by\n" \ - "# the 'rndc addzone' command. DO NOT EDIT BY HAND.\n" -static isc_result_t -add_comment(FILE *fp, const char *viewname) { - isc_result_t result; - CHECK(isc_stdio_write(HEADER1, sizeof(HEADER1) - 1, 1, fp, NULL)); - CHECK(isc_stdio_write(viewname, strlen(viewname), 1, fp, NULL)); - CHECK(isc_stdio_write(HEADER2, sizeof(HEADER2) - 1, 1, fp, NULL)); -cleanup: - return result; -} - -static void -dumpzone(void *arg, const char *buf, int len) { - FILE *fp = arg; - - (void)isc_stdio_write(buf, len, 1, fp, NULL); -} - -static isc_result_t -nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { - isc_result_t result; - off_t offset; - FILE *fp = NULL; - bool offsetok = false; - - LOCK(&view->newzone.lock); - - CHECK(isc_stdio_open(view->newzone.file, "a", &fp)); - CHECK(isc_stdio_seek(fp, 0, SEEK_END)); - - CHECK(isc_stdio_tell(fp, &offset)); - offsetok = true; - if (offset == 0) { - CHECK(add_comment(fp, view->name)); - } - - CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); - cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); - CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); - CHECK(isc_stdio_flush(fp)); - result = isc_stdio_close(fp); - fp = NULL; - -cleanup: - if (fp != NULL) { - (void)isc_stdio_close(fp); - if (offsetok) { - isc_result_t result2; - - result2 = isc_file_truncate(view->newzone.file, offset); - if (result2 != ISC_R_SUCCESS) { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_SERVER, - ISC_LOG_ERROR, - "Error truncating NZF file '%s' " - "during rollback from append: " - "%s", - view->newzone.file, - isc_result_totext(result2)); - } - } - } - UNLOCK(&view->newzone.lock); - return result; -} - -static isc_result_t -nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { - const cfg_obj_t *zl = NULL; - cfg_list_t *list; - FILE *fp = NULL; - char tmp[1024]; - isc_result_t result; - - result = isc_file_template(view->newzone.file, "nzf-XXXXXXXX", tmp, - sizeof(tmp)); - if (result == ISC_R_SUCCESS) { - result = isc_file_openunique(tmp, &fp); - } - if (result != ISC_R_SUCCESS) { - return result; - } - - cfg_map_get(config, "zone", &zl); - if (!cfg_obj_islist(zl)) { - CLEANUP(ISC_R_FAILURE); - } - - list = UNCONST(zl->value.list); - - CHECK(add_comment(fp, view->name)); /* force a comment */ - - ISC_LIST_FOREACH(*list, elt, link) { - const cfg_obj_t *zconfig = cfg_listelt_value(elt); - - CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL)); - cfg_printx(zconfig, CFG_PRINTER_ONELINE, dumpzone, fp); - CHECK(isc_stdio_write(";\n", 2, 1, fp, NULL)); - } - - CHECK(isc_stdio_flush(fp)); - result = isc_stdio_close(fp); - fp = NULL; - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - CHECK(isc_file_rename(tmp, view->newzone.file)); - return result; - -cleanup: - if (fp != NULL) { - (void)isc_stdio_close(fp); - } - (void)isc_file_remove(tmp); - return result; -} - -static isc_result_t -load_nzf(dns_view_t *view) { - isc_result_t result; - - /* The new zone file may not exist. That is OK. */ - if (!isc_file_exists(view->newzone.file)) { - return ISC_R_SUCCESS; - } - - /* - * Parse the configuration in the NZF file. - */ - result = cfg_parse_file(view->newzone.file, &cfg_type_addzoneconf, 0, - &view->newzone.nzconfig); - 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)); - } - - return result; -} -#else /* HAVE_LMDB */ - static void nzd_setkey(MDB_val *key, dns_name_t *name, char *namebuf, size_t buflen) { dns_fixedname_t fixed; @@ -12595,7 +12384,6 @@ cleanup: return result; } -#endif /* HAVE_LMDB */ static isc_result_t newzone_parse(named_server_t *server, char *command, dns_view_t **viewp, @@ -12784,15 +12572,10 @@ do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, dns_zone_t *zone = NULL; const cfg_obj_t *voptions = NULL; bool locked = false; -#ifndef HAVE_LMDB - FILE *fp = NULL; - bool cleanup_config = false; -#else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; UNUSED(zoneconf); -#endif if (!view->newzone.allowed) { result = ISC_R_NOPERM; @@ -12816,23 +12599,6 @@ do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, isc_loopmgr_pause(); -#ifndef HAVE_LMDB - /* - * Make sure we can open the configuration save file - */ - result = isc_stdio_open(view->newzone.file, "a", &fp); - if (result != ISC_R_SUCCESS) { - isc_loopmgr_resume(); - TCHECK(putstr(text, "unable to create '")); - TCHECK(putstr(text, view->newzone.file)); - TCHECK(putstr(text, "': ")); - TCHECK(putstr(text, isc_result_totext(result))); - goto cleanup; - } - - (void)isc_stdio_close(fp); - fp = NULL; -#else /* HAVE_LMDB */ LOCK(&view->newzone.lock); locked = true; /* Make sure we can open the NZD database */ @@ -12844,7 +12610,6 @@ do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, TCHECK(putstr(text, "'")); CLEANUP(ISC_R_FAILURE); } -#endif /* HAVE_LMDB */ /* Check zone syntax */ if (view->newzone.vconfig != NULL) { @@ -12892,21 +12657,6 @@ do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, } } -#ifndef HAVE_LMDB - /* - * If there wasn't a previous newzone config, just save the one - * we've created. If there was a previous one, merge the new - * zone into it. - */ - if (view->newzone.nzconfig == NULL) { - cfg_obj_attach(zoneconf, &view->newzone.nzconfig); - } else { - cfg_obj_t *z = UNCONST(zoneobj); - CHECK(cfg_map_add(view->newzone.nzconfig, z, "zone")); - } - cleanup_config = true; -#endif /* HAVE_LMDB */ - /* * Load the zone from the master file. If this fails, we'll * need to undo the configuration we've done already. @@ -12935,34 +12685,18 @@ do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, /* Flag the zone as having been added at runtime */ dns_zone_setadded(zone, true); -#ifdef HAVE_LMDB /* Save the new zone configuration into the NZD */ CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); -#else /* ifdef HAVE_LMDB */ - /* Append the zone configuration to the NZF */ - result = nzf_append(view, zoneobj); -#endif /* HAVE_LMDB */ cleanup: -#ifndef HAVE_LMDB - if (fp != NULL) { - (void)isc_stdio_close(fp); - } - if (result != ISC_R_SUCCESS && cleanup_config) { - tresult = delete_zoneconf(view, view->newzone.nzconfig, name, - NULL, locked); - RUNTIME_CHECK(tresult == ISC_R_SUCCESS); - } -#else /* HAVE_LMDB */ if (txn != NULL) { (void)nzd_close(&txn, false); } if (locked) { UNLOCK(&view->newzone.lock); } -#endif /* HAVE_LMDB */ if (zone != NULL) { dns_zone_detach(&zone); @@ -12980,13 +12714,8 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, const cfg_obj_t *voptions = NULL; bool added; bool locked = false; -#ifndef HAVE_LMDB - FILE *fp = NULL; - cfg_obj_t *z; -#else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; -#endif /* HAVE_LMDB */ if (!view->newzone.allowed) { result = ISC_R_NOPERM; @@ -13014,20 +12743,6 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, isc_loopmgr_pause(); -#ifndef HAVE_LMDB - /* Make sure we can open the configuration save file */ - result = isc_stdio_open(view->newzone.file, "a", &fp); - if (result != ISC_R_SUCCESS) { - TCHECK(putstr(text, "unable to open '")); - TCHECK(putstr(text, view->newzone.file)); - TCHECK(putstr(text, "': ")); - TCHECK(putstr(text, isc_result_totext(result))); - isc_loopmgr_resume(); - goto cleanup; - } - (void)isc_stdio_close(fp); - fp = NULL; -#else /* HAVE_LMDB */ LOCK(&view->newzone.lock); locked = true; /* Make sure we can open the NZD database */ @@ -13040,7 +12755,6 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, isc_loopmgr_resume(); goto cleanup; } -#endif /* HAVE_LMDB */ /* Check zone syntax */ if (view->newzone.vconfig != NULL) { @@ -13081,21 +12795,6 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); } -#ifndef HAVE_LMDB - /* Remove old zone from configuration (and NZF file if applicable) */ - if (added) { - result = delete_zoneconf(view, view->newzone.nzconfig, - dns_zone_getorigin(zone), - nzf_writeconf, locked); - if (result != ISC_R_SUCCESS) { - TCHECK(putstr(text, "former zone configuration " - "not deleted: ")); - TCHECK(putstr(text, isc_result_totext(result))); - goto cleanup; - } - } -#endif /* HAVE_LMDB */ - if (!added) { if (view->newzone.vconfig == NULL) { result = delete_zoneconf(view, server->effectiveconfig, @@ -13152,24 +12851,9 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, goto cleanup; } -#ifndef HAVE_LMDB - /* Store the new zone configuration; also in NZF if applicable */ - z = UNCONST(zoneobj); - CHECK(cfg_map_add(view->newzone.nzconfig, z, "zone")); -#endif /* HAVE_LMDB */ - if (added) { -#ifdef HAVE_LMDB CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); -#else /* ifdef HAVE_LMDB */ - result = nzf_append(view, zoneobj); - if (result != ISC_R_SUCCESS) { - TCHECK(putstr(text, "\nNew zone config not saved: ")); - TCHECK(putstr(text, isc_result_totext(result))); - goto cleanup; - } -#endif /* HAVE_LMDB */ TCHECK(putstr(text, "zone '")); TCHECK(putstr(text, zname)); @@ -13182,19 +12866,12 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, } cleanup: -#ifndef HAVE_LMDB - if (fp != NULL) { - (void)isc_stdio_close(fp); - } -#else /* HAVE_LMDB */ if (txn != NULL) { (void)nzd_close(&txn, false); } if (locked) { UNLOCK(&view->newzone.lock); } -#endif /* HAVE_LMDB */ - if (zone != NULL) { dns_zone_detach(&zone); } @@ -13232,12 +12909,7 @@ named_server_changezone(named_server_t *server, char *command, &redirect, text)); /* Are we accepting new zones in this view? */ -#ifdef HAVE_LMDB - if (view->newzone.db == NULL) -#else /* ifdef HAVE_LMDB */ - if (view->newzone.file == NULL) -#endif /* HAVE_LMDB */ - { + if (view->newzone.db == NULL) { (void)putstr(text, "Not allowing new zones in view '"); (void)putstr(text, view->name); (void)putstr(text, "'"); @@ -13325,10 +12997,8 @@ rmzone(void *arg) { bool added; bool locked = false; isc_result_t result; -#ifdef HAVE_LMDB MDB_txn *txn = NULL; MDB_dbi dbi; -#endif /* ifdef HAVE_LMDB */ REQUIRE(dz != NULL); @@ -13349,7 +13019,6 @@ rmzone(void *arg) { catz = dns_zone_get_parentcatz(zone); if (added && catz == NULL) { -#ifdef HAVE_LMDB /* Make sure we can open the NZD database */ LOCK(&view->newzone.lock); locked = true; @@ -13375,17 +13044,6 @@ rmzone(void *arg) { } UNLOCK(&view->newzone.lock); locked = false; -#else /* ifdef HAVE_LMDB */ - result = delete_zoneconf(view, view->newzone.nzconfig, - dns_zone_getorigin(zone), - nzf_writeconf, locked); - if (result != ISC_R_SUCCESS) { - isc_log_write(NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, - "unable to delete zone configuration: %s", - isc_result_totext(result)); - } -#endif /* HAVE_LMDB */ } if (!added) { diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c index 98fb219f2f..b0527c5fd7 100644 --- a/bin/tests/system/feature-test.c +++ b/bin/tests/system/feature-test.c @@ -222,11 +222,7 @@ main(int argc, char **argv) { } if (strcmp(argv[1], "--with-lmdb") == 0) { -#ifdef HAVE_LMDB return 0; -#else /* ifdef HAVE_LMDB */ - return 1; -#endif /* ifdef HAVE_LMDB */ } if (strcmp(argv[1], "--with-libnghttp2") == 0) { diff --git a/bin/tools/meson.build b/bin/tools/meson.build index 8e520850dd..5909cc2d35 100644 --- a/bin/tools/meson.build +++ b/bin/tools/meson.build @@ -19,7 +19,6 @@ named_rrchecker_src += files('named-rrchecker.c') nsec3hash_src += files('nsec3hash.c') manrst_srcset.add(when: 'HAVE_DNSTAP', if_true: files('dnstap-read.rst')) -manrst_srcset.add(when: 'HAVE_LMDB', if_true: files('named-nzd2nzf.rst')) manrst_srcset.add( files( 'arpaname.rst', diff --git a/bin/tools/named-nzd2nzf.c b/bin/tools/named-nzd2nzf.c index 18a5791ea8..d18b4cce73 100644 --- a/bin/tools/named-nzd2nzf.c +++ b/bin/tools/named-nzd2nzf.c @@ -11,10 +11,6 @@ * information regarding copyright ownership. */ -#ifndef HAVE_LMDB -#error This program requires the LMDB library. -#endif /* ifndef HAVE_LMDB */ - #include #include #include diff --git a/doc/man/meson.build b/doc/man/meson.build index 27dff028fb..b915f80bd4 100644 --- a/doc/man/meson.build +++ b/doc/man/meson.build @@ -10,7 +10,6 @@ # information regarding copyright ownership. manrst_srcset.add(when: 'HAVE_DNSTAP', if_true: files('dnstap-read.rst')) -manrst_srcset.add(when: 'HAVE_LMDB', if_true: files('named-nzd2nzf.rst')) manrst_srcset.add( files('conf.py'), @@ -39,6 +38,7 @@ manrst_srcset.add( 'named-compilezone.rst', 'named-journalprint.rst', 'named-makejournal.rst', + 'named-nzd2nzf.rst', 'named-rrchecker.rst', 'named.conf.rst', 'named.rst', @@ -55,7 +55,6 @@ manrst_srcset.add( if fs.is_file('arpaname.1.in') man_srcset.add(when: 'HAVE_DNSTAP', if_true: files('dnstap-read.1.in')) - man_srcset.add(when: 'HAVE_LMDB', if_true: files('named-nzd2nzf.1.in')) man_srcset.add( files( @@ -82,6 +81,7 @@ if fs.is_file('arpaname.1.in') 'named-compilezone.1.in', 'named-journalprint.1.in', 'named-makejournal.1.in', + 'named-nzd2nzf.1.in', 'named-rrchecker.1.in', 'named.8.in', 'named.conf.5.in', diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index b7a3f1b0db..296a3ce273 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -261,7 +261,6 @@ struct dns_view { */ #define MAX_DELEGATION_SERVERS 100 -#ifdef HAVE_LMDB #define DNS_LMDB_COMMON_FLAGS (MDB_CREATE | MDB_NOSUBDIR | MDB_NOLOCK) #ifndef __OpenBSD__ #define DNS_LMDB_FLAGS (DNS_LMDB_COMMON_FLAGS) @@ -272,7 +271,6 @@ struct dns_view { */ #define DNS_LMDB_FLAGS (DNS_LMDB_COMMON_FLAGS | MDB_WRITEMAP) #endif /* __OpenBSD__ */ -#endif /* HAVE_LMDB */ void dns_view_create(isc_mem_t *mctx, dns_dispatchmgr_t *dispmgr, diff --git a/lib/dns/view.c b/lib/dns/view.c index 5ec7269d52..906c5bb549 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,11 +15,8 @@ #include #include -#include - -#ifdef HAVE_LMDB #include -#endif /* ifdef HAVE_LMDB */ +#include #include #include @@ -341,7 +338,6 @@ destroy(dns_view_t *view) { if (view->newzone.cleanup != NULL) { view->newzone.cleanup(view); } -#ifdef HAVE_LMDB if (view->newzone.dbenv != NULL) { mdb_env_close((MDB_env *)view->newzone.dbenv); view->newzone.dbenv = NULL; @@ -349,7 +345,6 @@ destroy(dns_view_t *view) { if (view->newzone.db != NULL) { isc_mem_free(view->mctx, view->newzone.db); } -#endif /* HAVE_LMDB */ dns_fwdtable_destroy(&view->fwdtable); dns_aclenv_detach(&view->aclenv); if (view->failcache != NULL) { diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index e6c9d5ce23..fbccca2643 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2388,12 +2388,7 @@ static cfg_clausedef_t view_clauses[] = { { "ipv4only-server", &cfg_type_astring, 0, NULL }, { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0, NULL }, { "lame-ttl", &cfg_type_duration, 0, NULL }, -#ifdef HAVE_LMDB { "lmdb-mapsize", &cfg_type_sizeval, CFG_CLAUSEFLAG_OPTIONAL, NULL }, -#else /* ifdef HAVE_LMDB */ - { "lmdb-mapsize", &cfg_type_sizeval, CFG_CLAUSEFLAG_NOTCONFIGURED, - NULL }, -#endif /* ifdef HAVE_LMDB */ { "max-acache-size", NULL, CFG_CLAUSEFLAG_ANCIENT, NULL }, { "max-cache-size", &cfg_type_maxcachesize, 0, NULL }, { "max-cache-ttl", &cfg_type_duration, 0, NULL }, diff --git a/meson.build b/meson.build index e7cf42da67..60b4e4b991 100644 --- a/meson.build +++ b/meson.build @@ -63,7 +63,6 @@ idn_opt = get_option('idn') jemalloc_opt = get_option('jemalloc').disable_auto_if(sanitizer != 'none') leak_opt = get_option('leak-detection') line_opt = get_option('line') -lmdb_opt = get_option('lmdb') locktype_opt = get_option('locktype') named_lto_opt = get_option('named-lto') oss_fuzz_args_opt = get_option('oss-fuzz-args') @@ -875,13 +874,7 @@ if idn_opt.allowed() endif ## LMDB -lmdb_dep = null_dep -if lmdb_opt.allowed() - lmdb_dep = dependency('lmdb', required: lmdb_opt) - if lmdb_dep.found() - config.set('HAVE_LMDB', 1) - endif -endif +lmdb_dep = dependency('lmdb') ## zlib @@ -1578,21 +1571,19 @@ executable( ], ) -if config.has('HAVE_LMDB') - executable( - 'named-nzd2nzf', - named_nzd2nzf_src, - export_dynamic: true, - implicit_include_directories: false, - install: true, - dependencies: [ - libdns_dep, - libisc_dep, +executable( + 'named-nzd2nzf', + named_nzd2nzf_src, + export_dynamic: true, + implicit_include_directories: false, + install: true, + dependencies: [ + libdns_dep, + libisc_dep, - lmdb_dep, - ], - ) -endif + lmdb_dep, + ], +) executable( 'named-rrchecker', diff --git a/meson.options b/meson.options index ca0d2fc6e1..afc76367bd 100644 --- a/meson.options +++ b/meson.options @@ -66,13 +66,6 @@ option( description: 'Enable line editing in nsupdate and nslookup, requires libedit', ) -option( - 'lmdb', - type: 'feature', - value: 'auto', - description: 'LMDB database to store configuration for "addzone" zones', -) - option( 'stats-json', type: 'feature', From f203f6e77ab29f8d53956cf2186030fa7488b3ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Sun, 15 Mar 2026 04:42:45 +0100 Subject: [PATCH 2/5] Remove dead NZF writer parameter and simplify newzone locking Now that NZF write support is gone, remove the unused nzfwriter_t typedef and nzfwriter parameter from delete_zoneconf(). Remove the bool locked parameter and simplify the locking in do_modzone() and rmzone() to unconditional lock/unlock pairs. --- bin/named/server.c | 63 +++++++++++++--------------------------------- 1 file changed, 17 insertions(+), 46 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 1207e8e033..24432cdfac 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -288,12 +288,6 @@ typedef struct matching_view_ctx { dns_view_t *view; } matching_view_ctx_t; -/*% - * A function to write out added-zone configuration to the new_zone_file - * specified in 'view'. Maybe called by delete_zoneconf(). - */ -typedef isc_result_t (*nzfwriter_t)(const cfg_obj_t *config, dns_view_t *view); - /*% * Holds state information for the initial zone loading process. * Uses the isc_refcount structure to count the number of views @@ -12513,26 +12507,22 @@ cleanup: static isc_result_t delete_zoneconf(dns_view_t *view, const cfg_obj_t *config, - const dns_name_t *zname, nzfwriter_t nzfwriter, bool locked) { - isc_result_t result = ISC_R_NOTFOUND; + const dns_name_t *zname) { const cfg_obj_t *zl = NULL; REQUIRE(view != NULL); REQUIRE(config != NULL); REQUIRE(zname != NULL); - if (!locked) { - LOCK(&view->newzone.lock); - } - cfg_map_get(config, "zone", &zl); if (!cfg_obj_islist(zl)) { - CLEANUP(ISC_R_FAILURE); + return ISC_R_FAILURE; } cfg_list_t *list = UNCONST(zl->value.list); ISC_LIST_FOREACH(*list, elt, link) { + isc_result_t result; dns_fixedname_t myfixed; dns_name_t *myname = dns_fixedname_initname(&myfixed); const cfg_obj_t *zconf = cfg_listelt_value(elt); @@ -12546,22 +12536,10 @@ delete_zoneconf(dns_view_t *view, const cfg_obj_t *config, cfg_obj_t *zones = UNCONST(zl); cfg_list_unlink(zones, elt); - result = ISC_R_SUCCESS; - break; + return ISC_R_SUCCESS; } - /* - * Write config to NZF file if appropriate - */ - if (nzfwriter != NULL && view->newzone.file != NULL) { - result = nzfwriter(config, view); - } - -cleanup: - if (!locked) { - UNLOCK(&view->newzone.lock); - } - return result; + return ISC_R_NOTFOUND; } static isc_result_t @@ -12713,7 +12691,6 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, dns_zone_t *zone = NULL; const cfg_obj_t *voptions = NULL; bool added; - bool locked = false; MDB_txn *txn = NULL; MDB_dbi dbi; @@ -12744,7 +12721,6 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, isc_loopmgr_pause(); LOCK(&view->newzone.lock); - locked = true; /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { @@ -12798,14 +12774,12 @@ do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, if (!added) { if (view->newzone.vconfig == NULL) { result = delete_zoneconf(view, server->effectiveconfig, - dns_zone_getorigin(zone), NULL, - locked); + dns_zone_getorigin(zone)); } else { voptions = cfg_tuple_get(server->effectiveconfig, "options"); result = delete_zoneconf(view, voptions, - dns_zone_getorigin(zone), NULL, - locked); + dns_zone_getorigin(zone)); } if (result != ISC_R_SUCCESS) { @@ -12869,9 +12843,8 @@ cleanup: if (txn != NULL) { (void)nzd_close(&txn, false); } - if (locked) { - UNLOCK(&view->newzone.lock); - } + + UNLOCK(&view->newzone.lock); if (zone != NULL) { dns_zone_detach(&zone); } @@ -12995,7 +12968,6 @@ rmzone(void *arg) { dns_view_t *view = NULL; dns_db_t *dbp = NULL; bool added; - bool locked = false; isc_result_t result; MDB_txn *txn = NULL; MDB_dbi dbi; @@ -13018,10 +12990,10 @@ rmzone(void *arg) { added = dns_zone_getadded(zone); catz = dns_zone_get_parentcatz(zone); + LOCK(&view->newzone.lock); + if (added && catz == NULL) { /* Make sure we can open the NZD database */ - LOCK(&view->newzone.lock); - locked = true; result = nzd_open(view, 0, &txn, &dbi); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, @@ -13042,8 +13014,6 @@ rmzone(void *arg) { if (txn != NULL) { (void)nzd_close(&txn, false); } - UNLOCK(&view->newzone.lock); - locked = false; } if (!added) { @@ -13051,12 +13021,11 @@ rmzone(void *arg) { const cfg_obj_t *voptions = cfg_tuple_get(view->newzone.vconfig, "options"); result = delete_zoneconf(view, voptions, - dns_zone_getorigin(zone), NULL, - locked); + dns_zone_getorigin(zone)); } else { - result = delete_zoneconf( - view, dz->server->effectiveconfig, - dns_zone_getorigin(zone), NULL, locked); + result = delete_zoneconf(view, + dz->server->effectiveconfig, + dns_zone_getorigin(zone)); } if (result != ISC_R_SUCCESS) { @@ -13067,6 +13036,8 @@ rmzone(void *arg) { } } + UNLOCK(&view->newzone.lock); + /* Unload zone database */ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) { dns_db_detach(&dbp); From 8ae0828e15993fb3d813ba955c7b800d93bd8416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Sun, 15 Mar 2026 05:05:09 +0100 Subject: [PATCH 3/5] Split NZD functions into a separate compilation unit 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 | 55 ++++ bin/named/meson.build | 1 + bin/named/nzd.c | 492 +++++++++++++++++++++++++++++++++ bin/named/server.c | 494 +--------------------------------- 4 files changed, 550 insertions(+), 492 deletions(-) create mode 100644 bin/named/include/named/nzd.h create mode 100644 bin/named/nzd.c diff --git a/bin/named/include/named/nzd.h b/bin/named/include/named/nzd.h new file mode 100644 index 0000000000..a79636935a --- /dev/null +++ b/bin/named/include/named/nzd.h @@ -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 + +#include +#include +#include + +#include + +#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); diff --git a/bin/named/meson.build b/bin/named/meson.build index bf9e8f9dbf..18b221ab62 100644 --- a/bin/named/meson.build +++ b/bin/named/meson.build @@ -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 index 0000000000..f3707e497e --- /dev/null +++ b/bin/named/nzd.c @@ -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 + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +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; +} diff --git a/bin/named/server.c b/bin/named/server.c index 24432cdfac..14c8d48bc3 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -117,6 +117,7 @@ #include #include +#include #if defined(HAVE_GEOIP2) #include #endif /* HAVE_GEOIP2 */ @@ -145,8 +146,6 @@ #define JEMALLOC_API_SUPPORTED 1 #endif -#include - #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, From 81dca80877fb2b065e51bceecde9547d123a14d1 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 18 Mar 2026 10:33:09 +0100 Subject: [PATCH 4/5] Update documentation now that LMDB is required Remove references to viewname.nzf, and no longer use "if LMDB is used". --- bin/named/server.c | 6 +++--- bin/rndc/rndc.rst | 3 +-- doc/arm/reference.rst | 27 +++++++++++---------------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 14c8d48bc3..0408cfc92f 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -8290,9 +8290,9 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys, } /* - * If we're using LMDB, we may have created newzones databases - * as root, making it impossible to reopen them later after - * switching to a new userid. We close them now, and reopen + * We are using LMDB. This means we may have created newzones + * databases as root, making it impossible to reopen them later + * after switching to a new userid. We close them now, and reopen * after relinquishing privileges them. */ if (first_time) { diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst index c19fcfd410..6b45366e23 100644 --- a/bin/rndc/rndc.rst +++ b/bin/rndc/rndc.rst @@ -133,8 +133,7 @@ Currently supported commands are: string specified on the command line is the zone configuration text that would ordinarily be placed in :iscman:`named.conf`. - The configuration is saved in a file called ``viewname.nzf`` (or, if - :iscman:`named` is compiled with liblmdb, an LMDB database file called + The configuration is saved in an LMDB database file called ``viewname.nzd``). ``viewname`` is the name of the view, unless the view name contains characters that are incompatible with use as a file name, in which case a cryptographic hash of the view name is used diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index b3d746d5b1..96aafadd82 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -1364,12 +1364,11 @@ default is used. :tags: server :short: Sets a maximum size for the memory map of the new-zone database in LMDB database format. - When :iscman:`named` is built with liblmdb, this option sets a maximum size - for the memory map of the new-zone database (NZD) in LMDB database - format. This database is used to store configuration information for - zones added using :option:`rndc addzone`. Note that this is not the NZD - database file size, but the largest size that the database may grow - to. + This option sets a maximum size for the memory map of the new-zone database + (NZD) in LMDB database format. This database is used to store configuration + information for zones added using :option:`rndc addzone`. Note that this is + not the NZD database file size, but the largest size that the database may + grow to. Because the database file is memory-mapped, its size is limited by the address space of the :iscman:`named` process. The default of 32 megabytes @@ -1960,17 +1959,13 @@ Boolean Options Newly added zones' configuration parameters are stored so that they can persist after the server is restarted. The configuration - information is saved in a file called ``viewname.nzf`` (or, if - :iscman:`named` is compiled with liblmdb, in an LMDB database file called - ``viewname.nzd``). "viewname" is the name of the view, unless the view - name contains characters that are incompatible with use as a file - name, in which case a cryptographic hash of the view name is used - instead. + information is saved in an LMDB database file called ``viewname.nzd``. + "viewname" is the name of the view, unless the view name contains + characters that are incompatible with use as a file name, in which case a + cryptographic hash of the view name is used instead. - Configurations for zones added at runtime are stored either in - a new-zone file (NZF) or a new-zone database (NZD), depending on - whether :iscman:`named` was linked with liblmdb at compile time. See - :ref:`man_rndc` for further details about :option:`rndc addzone`. + Configurations for zones added at runtime are stored in a new-zone database + (NZD). See :ref:`man_rndc` for further details about :option:`rndc addzone`. .. namedconf:statement:: auth-nxdomain :tags: query From 46e98295bbc03e06a7d2b9e9c8284977a79c234d Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 18 Mar 2026 10:42:57 +0100 Subject: [PATCH 5/5] Remove LDMB checks from system tests Now that LMDB is required, there is no need to check if the feature is enabled in the system tests. --- bin/tests/system/addzone/tests.sh | 106 +++++----------------- bin/tests/system/checkconf/tests.sh | 28 ++---- bin/tests/system/feature-test.c | 5 - bin/tests/system/isctest/vars/features.py | 1 - 4 files changed, 31 insertions(+), 109 deletions(-) diff --git a/bin/tests/system/addzone/tests.sh b/bin/tests/system/addzone/tests.sh index 0cf8be2a75..9634bd5777 100755 --- a/bin/tests/system/addzone/tests.sh +++ b/bin/tests/system/addzone/tests.sh @@ -67,13 +67,11 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if $FEATURETEST --with-lmdb; then - echo_i "checking that existing NZF file was renamed after migration ($n)" - [ -e ns2/3bf305731dd26307.nzf~ ] || ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi +echo_i "checking that existing NZF file was renamed after migration ($n)" +[ -e ns2/3bf305731dd26307.nzf~ ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) echo_i "adding new zone ($n)" ret=0 @@ -146,16 +144,6 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if ! $FEATURETEST --with-lmdb; then - echo_i "verifying no comments in NZF file ($n)" - ret=0 - hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l) - [ $hcount -eq 0 ] || ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi - echo_i "checking rndc showzone with previously added zone ($n)" ret=0 $RNDCCMD 10.53.0.2 showzone previous.example >rndc.out.ns2.$n @@ -165,13 +153,11 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if $FEATURETEST --with-lmdb; then - echo_i "checking zone is present in NZD ($n)" - ret=0 - $NZD2NZF ns2/_default.nzd | grep previous.example >/dev/null || ret=1 - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi +echo_i "checking zone is present in NZD ($n)" +ret=0 +$NZD2NZF ns2/_default.nzd | grep previous.example >/dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) echo_i "deleting previously added zone ($n)" ret=0 @@ -191,22 +177,10 @@ check_nzd2nzf() ( && ! grep previous.example nzd2nzf.out.$n >/dev/null ) -if $FEATURETEST --with-lmdb; then - echo_i "checking zone was deleted from NZD ($n)" - retry_quiet 10 check_nzd2nzf || ret=1 - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi - -if ! $FEATURETEST --with-lmdb; then - echo_i "checking NZF file now has comment ($n)" - ret=0 - hcount=$(grep "^# New zone file for view: _default" ns2/3bf305731dd26307.nzf | wc -l) - [ $hcount -eq 1 ] || ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi +echo_i "checking zone was deleted from NZD ($n)" +retry_quiet 10 check_nzd2nzf || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) echo_i "deleting newly added zone added.example ($n)" ret=0 @@ -526,24 +500,12 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if ! $FEATURETEST --with-lmdb; then - echo_i "checking new NZF file has comment ($n)" - ret=0 - hcount=$(grep "^# New zone file for view: external" ns2/external.nzf | wc -l) - [ $hcount -eq 1 ] || ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi - -if $FEATURETEST --with-lmdb; then - echo_i "verifying added.example in external view created an external.nzd DB ($n)" - ret=0 - [ -e ns2/external.nzd ] || ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi +echo_i "verifying added.example in external view created an external.nzd DB ($n)" +ret=0 +[ -e ns2/external.nzd ] || ret=1 +n=$((n + 1)) +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) echo_i "checking rndc reload causes named to reload the external view's new zone config ($n)" ret=0 @@ -562,11 +524,7 @@ status=$((status + ret)) echo_i "checking rndc showzone with newly added zone ($n)" _check_rndc_showzone_newly_added() ( - if ! $FEATURETEST --with-lmdb; then - expected='zone "added.example" in external { type primary; file "added.db"; };' - else - expected='zone "added.example" { type primary; file "added.db"; };' - fi + expected='zone "added.example" { type primary; file "added.db"; };' $RNDCCMD 10.53.0.2 showzone added.example in external >rndc.out.ns2.$n 2>/dev/null \ && [ "$(cat rndc.out.ns2.$n)" = "$expected" ] ) @@ -668,13 +626,8 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if $FEATURETEST --with-lmdb; then - echo_i "checking NZD file was created in new-zones-directory ($n)" - expect=ns2/new-zones/directory.nzd -else - echo_i "checking NZF file was created in new-zones-directory ($n)" - expect=ns2/new-zones/directory.nzf -fi +echo_i "checking NZD file was created in new-zones-directory ($n)" +expect=ns2/new-zones/directory.nzd $RNDCCMD 10.53.0.2 sync 'added.example IN directory' 2>&1 | sed 's/^/I:ns2 /' sleep 2 [ -e "$expect" ] || ret=1 @@ -710,19 +663,6 @@ n=$((n + 1)) if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) -if ! $FEATURETEST --with-lmdb; then - echo_i "check that addzone is fully reversed on failure (--with-lmdb=no) ($n)" - ret=0 - $RNDCCMD 10.53.0.3 addzone "test1.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 - $RNDCCMD 10.53.0.3 addzone "test2.baz" '{ type primary; file "dne.db"; };' >/dev/null 2>&1 && ret=1 - $RNDCCMD 10.53.0.3 addzone "test3.baz" '{ type primary; file "e.db"; };' >/dev/null 2>&1 || ret=1 - $RNDCCMD 10.53.0.3 delzone "test3.baz" >/dev/null 2>&1 || ret=1 - grep test2.baz ns3/_default.nzf >/dev/null && ret=1 - n=$((n + 1)) - if [ $ret != 0 ]; then echo_i "failed"; fi - status=$((status + ret)) -fi - _check_version_bind() ( $DIG $DIGOPTS @10.53.0.3 version.bind txt ch >dig.out.test$n \ && grep "status: NOERROR" dig.out.test$n >/dev/null diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index a1f6a7430f..69d96b7ea8 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -109,26 +109,14 @@ for lmdb in lmdb-*.conf; do n=$((n + 1)) ret=0 - if $FEATURETEST --with-lmdb; then - echo_i "checking that named-checkconf detects no error in $lmdb ($n)" - { - $CHECKCONF $lmdb >checkconf.out$n 2>&1 - rc=$? - } || true - if [ $rc -ne 0 ]; then - echo_i "failed" - ret=1 - fi - else - echo_i "checking that named-checkconf detects error in $lmdb ($n)" - { - $CHECKCONF $lmdb >checkconf.out$n 2>&1 - rc=$? - } || true - if [ $rc -eq 0 ]; then - echo_i "failed" - ret=1 - fi + echo_i "checking that named-checkconf detects no error in $lmdb ($n)" + { + $CHECKCONF $lmdb >checkconf.out$n 2>&1 + rc=$? + } || true + if [ $rc -ne 0 ]; then + echo_i "failed" + ret=1 fi status=$((status + ret)) done diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c index b0527c5fd7..feebe0315d 100644 --- a/bin/tests/system/feature-test.c +++ b/bin/tests/system/feature-test.c @@ -56,7 +56,6 @@ usage(void) { fprintf(stderr, "\t--rsasha1\n"); fprintf(stderr, "\t--tsan\n"); fprintf(stderr, "\t--with-libidn2\n"); - fprintf(stderr, "\t--with-lmdb\n"); fprintf(stderr, "\t--with-libnghttp2\n"); fprintf(stderr, "\t--with-zlib\n"); } @@ -221,10 +220,6 @@ main(int argc, char **argv) { #endif /* ifdef HAVE_LIBIDN2 */ } - if (strcmp(argv[1], "--with-lmdb") == 0) { - return 0; - } - if (strcmp(argv[1], "--with-libnghttp2") == 0) { #ifdef HAVE_LIBNGHTTP2 return 0; diff --git a/bin/tests/system/isctest/vars/features.py b/bin/tests/system/isctest/vars/features.py index 4c47efa00d..3ebb0863a8 100644 --- a/bin/tests/system/isctest/vars/features.py +++ b/bin/tests/system/isctest/vars/features.py @@ -26,7 +26,6 @@ FEATURES = { "LIBIDN2": "--with-libidn2", "LIBNGHTTP2": "--with-libnghttp2", "LIBXML2": "--have-libxml2", - "LMDB": "--with-lmdb", "MD5": "--md5", "QUERYTRACE": "--enable-querytrace", "RSASHA1": "--rsasha1",