Commit 6ead3cd71a for bind

commit 6ead3cd71ae53a3324e99a07f6e97adc208d4721
Author: Alessio Podda <alessio@isc.org>
Date:   Thu Sep 10 17:02:42 2026 +0200

    Revert "fix: dev: Save configuration as text"

    This reverts commit 09bcacbd3689b3208a5f51d281c85375bd7fb265, reversing
    changes made to 2affdbce199715835a2c84f25fd9c61318985883.

diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
index 57ce35a1d4..62e3da1268 100644
--- a/bin/named/include/named/server.h
+++ b/bin/named/include/named/server.h
@@ -107,8 +107,7 @@ struct named_server {
 	isc_signal_t *sigusr1;

 	cfg_aclconfctx_t *aclctx;
-	isc_buffer_t	 *userconftext;
-	isc_buffer_t	 *effectivetext;
+	isc_buffer_t	 *userconf;
 	cfg_obj_t	 *effectiveconfig;
 };

diff --git a/bin/named/server.c b/bin/named/server.c
index 3e61c2a8c7..011dbee480 100644
--- a/bin/named/server.c
+++ b/bin/named/server.c
@@ -5934,40 +5934,6 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
 	return ISC_R_SUCCESS;
 }

-static void
-emit_text(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
-save_zoneconfig(dns_zone_t *zone, const cfg_obj_t *zconfig) {
-	isc_result_t result;
-	isc_buffer_t *text = NULL;
-
-	isc_buffer_allocate(isc_g_mctx, &text, 256);
-
-	ns_dzarg_t dzarg = {
-		.magic = DZARG_MAGIC,
-		.text = text,
-	};
-
-	cfg_printx(zconfig, CFG_PRINTER_ONELINE, emit_text, &dzarg);
-	CHECK(putnull(text));
-
-	dns_zone_setcfg(zone, isc_buffer_base(text));
-
-cleanup:
-	isc_buffer_free(&text);
-	return result;
-}
-
 /*
  * Configure or reconfigure a zone.
  */
@@ -6168,7 +6134,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
 		}
 		CHECK(named_zone_configure(config, vconfig, zconfig, aclctx,
 					   kasplist, zone, NULL));
-		CHECK(save_zoneconfig(zone, zconfig));
 		dns_zone_attach(zone, &view->redirect);
 		goto cleanup;
 	}
@@ -6346,7 +6311,6 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
 	 */
 	CHECK(named_zone_configure(config, vconfig, zconfig, aclctx, kasplist,
 				   zone, raw));
-	CHECK(save_zoneconfig(zone, zconfig));

 	/*
 	 * Add the zone to its view in the new view list.
@@ -7585,7 +7549,7 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
 		      ISC_LOG_DEBUG(1), "apply_configuration: %s", __func__);

 static isc_result_t
-create_views(cfg_obj_t *config, dns_viewlist_t *viewlist, bool *nzp) {
+create_views(cfg_obj_t *config, dns_viewlist_t *viewlist) {
 	isc_result_t result = ISC_R_SUCCESS;
 	const cfg_obj_t *bindview = NULL;
 	const cfg_obj_t *views = NULL;
@@ -7619,9 +7583,6 @@ create_views(cfg_obj_t *config, dns_viewlist_t *viewlist, bool *nzp) {

 		CHECK(setup_newzones(view, config, vconfig));
 		explicitviews = true;
-		if (view->newzone.allowed) {
-			*nzp = true;
-		}
 		dns_view_detach(&view);
 	}

@@ -7634,9 +7595,6 @@ create_views(cfg_obj_t *config, dns_viewlist_t *viewlist, bool *nzp) {
 		INSIST(view != NULL);

 		CHECK(setup_newzones(view, config, NULL));
-		if (view->newzone.allowed) {
-			*nzp = true;
-		}
 		dns_view_detach(&view);
 	}

@@ -7810,8 +7768,7 @@ configure_kasplist(const cfg_obj_t *config, dns_kasplist_t *kasplist,

 static isc_result_t
 apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
-		    named_server_t *server, bool first_time,
-		    bool *newzones_allowed) {
+		    named_server_t *server, bool first_time) {
 	const cfg_obj_t *maps[3];
 	const cfg_obj_t *obj = NULL;
 	const cfg_obj_t *options = NULL;
@@ -7885,7 +7842,7 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
 		goto cleanup_kasplist;
 	}

-	result = create_views(effectiveconfig, &viewlist, newzones_allowed);
+	result = create_views(effectiveconfig, &viewlist);
 	if (result != ISC_R_SUCCESS) {
 		goto cleanup_viewlist;
 	}
@@ -8849,6 +8806,14 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
 	 */
 	named_g_defaultconfigtime = isc_time_now();

+	/*
+	 * Save the current effective configuration
+	 */
+	if (server->effectiveconfig != NULL) {
+		cfg_obj_detach(&server->effectiveconfig);
+	}
+	cfg_obj_attach(effectiveconfig, &server->effectiveconfig);
+
 	isc_loopmgr_resume();
 	exclusive = false;

@@ -8858,8 +8823,8 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
 	}

 	/* Configure the statistics channel(s) */
-	result = named_statschannels_configure(named_g_server, effectiveconfig,
-					       server->aclctx);
+	result = named_statschannels_configure(
+		named_g_server, server->effectiveconfig, server->aclctx);
 	if (result != ISC_R_SUCCESS) {
 		isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
 			      ISC_LOG_ERROR,
@@ -8872,7 +8837,8 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
 	 * Bind the control port(s).
 	 */
 	result = named_controls_configure(named_g_server->controls,
-					  effectiveconfig, server->aclctx);
+					  server->effectiveconfig,
+					  server->aclctx);
 	if (result != ISC_R_SUCCESS) {
 		isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
 			      ISC_LOG_ERROR, "binding control channel(s): %s",
@@ -8962,16 +8928,32 @@ cleanup_aclctx:
 		      ISC_LOG_DEBUG(1), "apply_configuration: %s",
 		      isc_result_totext(result));

+	cfg_obj_detach(&effectiveconfig);
 	return result;
 }

+static void
+emit_text(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
 load_configuration(named_server_t *server, bool first_time) {
 	isc_result_t result;
 	cfg_obj_t *config = NULL, *effective = NULL;
 	cfg_obj_t *bindkeys = NULL, *builtin = NULL;
-	ns_dzarg_t dzarg;
-	bool newzones_allowed = false;
+	ns_dzarg_t dzarg = {
+		.magic = DZARG_MAGIC,
+		.result = ISC_R_SUCCESS,
+		.text = server->userconf,
+	};

 	isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
 		      ISC_LOG_DEBUG(1), "load_configuration");
@@ -9013,51 +8995,18 @@ load_configuration(named_server_t *server, bool first_time) {
 	effective = cfg_effective_config(config, builtin);

 	/*
-	 * Save the user and effective configurations in text format,
-	 * to display with "rndc showconf". (Text takes up less memory
-	 * than an object tree.)
-	 *
-	 * Also save the effective configuration as an object tree, if
-	 * "allow-new-zones" or catalog zones are in use. That takes
-	 * more memory but avoids the need to re-parse the configuration
-	 * when zone changes are made.
+	 * Save the user configuration for later reference.
+	 * We keep it in text format to save space; we won't need
+	 * to access it as a tree again after this.
 	 */
-
-	if (server->effectiveconfig != NULL) {
-		cfg_obj_detach(&server->effectiveconfig);
-	}
-
-	if (server->effectivetext != NULL) {
-		isc_buffer_free(&server->effectivetext);
+	if (server->userconf != NULL) {
+		isc_buffer_free(&server->userconf);
 	}
-	isc_buffer_allocate(isc_g_mctx, &server->effectivetext, BUFSIZ);
-
-	if (server->userconftext != NULL) {
-		isc_buffer_free(&server->userconftext);
-	}
-	isc_buffer_allocate(isc_g_mctx, &server->userconftext, BUFSIZ);
-
-	dzarg = (ns_dzarg_t){
-		.magic = DZARG_MAGIC,
-		.text = server->userconftext,
-	};
+	isc_buffer_allocate(isc_g_mctx, &server->userconf, BUFSIZ);
+	dzarg.text = server->userconf;
 	cfg_printx(config, 0, emit_text, &dzarg);

-	dzarg = (ns_dzarg_t){
-		.magic = DZARG_MAGIC,
-		.text = &server->effectivetext,
-	};
-	cfg_printx(effective, 0, emit_text, &dzarg);
-
-	/*
-	 * And finally we apply the effective configuration.
-	 */
-	result = apply_configuration(effective, bindkeys, server, first_time,
-				     &newzones_allowed);
-	if (newzones_allowed) {
-		server->effectiveconfig = effective;
-		effective = NULL;
-	}
+	result = apply_configuration(effective, bindkeys, server, first_time);

 cleanup:
 	if (bindkeys != NULL) {
@@ -9069,9 +9018,6 @@ cleanup:
 	if (builtin != NULL) {
 		cfg_obj_detach(&builtin);
 	}
-	if (effective != NULL) {
-		cfg_obj_detach(&effective);
-	}

 	return result;
 }
@@ -9670,12 +9616,8 @@ named_server_destroy(named_server_t **serverp) {
 		isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
 	}

-	if (server->userconftext != NULL) {
-		isc_buffer_free(&server->userconftext);
-	}
-
-	if (server->effectivetext != NULL) {
-		isc_buffer_free(&server->effectivetext);
+	if (server->userconf != NULL) {
+		isc_buffer_free(&server->userconf);
 	}

 	if (server->effectiveconfig != NULL) {
@@ -13015,9 +12957,10 @@ isc_result_t
 named_server_showzone(named_server_t *server, isc_lex_t *lex,
 		      isc_buffer_t *text) {
 	isc_result_t result;
+	const cfg_obj_t *zconfig = NULL;
 	char zonename[DNS_NAME_FORMATSIZE];
 	dns_zone_t *zone = NULL;
-	const char *zconfig = NULL;
+	ns_dzarg_t dzarg;

 	REQUIRE(text != NULL);

@@ -13035,7 +12978,12 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex,
 	}

 	CHECK(putstr(text, "zone "));
-	CHECK(putstr(text, zconfig));
+	dzarg.magic = DZARG_MAGIC;
+	dzarg.text = text;
+	dzarg.result = ISC_R_SUCCESS;
+	cfg_printx(zconfig, CFG_PRINTER_ONELINE, emit_text, &dzarg);
+	CHECK(dzarg.result);
+
 	CHECK(putstr(text, ";"));

 	result = ISC_R_SUCCESS;
@@ -13051,8 +12999,14 @@ cleanup:
 isc_result_t
 named_server_showconf(named_server_t *server, isc_lex_t *lex,
 		      isc_buffer_t *text) {
-	isc_result_t result = ISC_R_SUCCESS;
+	isc_result_t result;
 	const char *arg = NULL;
+	cfg_obj_t *config = NULL;
+	ns_dzarg_t dzarg = {
+		.magic = DZARG_MAGIC,
+		.result = ISC_R_SUCCESS,
+		.text = text,
+	};

 	REQUIRE(text != NULL);

@@ -13063,32 +13017,37 @@ named_server_showconf(named_server_t *server, isc_lex_t *lex,
 	if (arg == NULL) {
 		return ISC_R_UNEXPECTEDEND;
 	}
-
 	if (strcasecmp(arg, "-user") == 0) {
-		result = putmem(text, isc_buffer_base(server->userconftext),
-				isc_buffer_usedlength(server->userconftext));
-	} else if (strcasecmp(arg, "-effective") == 0) {
-		result = putmem(text, isc_buffer_base(server->effectivetext),
-				isc_buffer_usedlength(server->effectivetext));
+		putmem(text, isc_buffer_base(server->userconf),
+		       isc_buffer_usedlength(server->userconf));
+		result = ISC_R_SUCCESS;
+		goto cleanup;
 	} else if (strcasecmp(arg, "-builtin") == 0) {
-		cfg_obj_t *config = NULL;
-		ns_dzarg_t dzarg = {
-			.magic = DZARG_MAGIC,
-			.text = text,
-		};
-		CHECK(named_config_parsedefaults(&config));
-		cfg_printx(config, 0, emit_text, &dzarg);
-		cfg_obj_detach(&config);
-		result = dzarg.result;
+		named_config_parsedefaults(&config);
+	} else if (strcasecmp(arg, "-effective") == 0) {
+		cfg_obj_attach(server->effectiveconfig, &config);
 	} else {
-		result = DNS_R_SYNTAX;
+		CHECK(DNS_R_SYNTAX);
+	}
+
+	if (config == NULL) {
+		result = ISC_R_NOTFOUND;
+		TCHECK(putstr(text, "configuration data not found.\n"));
+		goto cleanup;
 	}

+	cfg_printx(config, 0, emit_text, &dzarg);
+	result = dzarg.result;
+
 cleanup:
 	if (isc_buffer_usedlength(text) > 0) {
 		(void)putnull(text);
 	}

+	if (config != NULL) {
+		cfg_obj_detach(&config);
+	}
+
 	return result;
 }

diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
index b67db5c153..df401e00a9 100644
--- a/bin/named/zoneconf.c
+++ b/bin/named/zoneconf.c
@@ -955,6 +955,12 @@ process_notify_cfg(const cfg_obj_t **maps, dns_zone_t *zone, dns_zone_t *raw) {
 	return ISC_R_SUCCESS;
 }

+static void
+detach_cfg(void *arg) {
+	cfg_obj_t *cfg = (cfg_obj_t *)arg;
+	cfg_obj_detach(&cfg);
+}
+
 isc_result_t
 named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
 		     const cfg_obj_t *zconfig, cfg_aclconfctx_t *aclctx,
@@ -1985,6 +1991,11 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
 		break;
 	}

+	/* Save the configuration for later use */
+	cfg_obj_t *cfg = UNCONST(zconfig);
+	cfg_obj_ref(cfg);
+	dns_zone_setcfg(zone, (void *)cfg, detach_cfg);
+
 	result = ISC_R_SUCCESS;

 cleanup:
diff --git a/lib/dns/include/dns/zoneproperties.h b/lib/dns/include/dns/zoneproperties.h
index e509c658de..1404a84f45 100644
--- a/lib/dns/include/dns/zoneproperties.h
+++ b/lib/dns/include/dns/zoneproperties.h
@@ -1507,20 +1507,20 @@ dns_zone_sethooktable(dns_zone_t *zone, void *hooktable,
  */

 void
-dns_zone_setcfg(dns_zone_t *zone, const char *cfg);
+dns_zone_setcfg(dns_zone_t *zone, void *cfg, void (*cfg_detach)(void *));
 /*%<
- * Save a copy of the configuration text for 'zone', which can be
+ * Set a pointer to the configuration object for 'zone', which can be
  * used later to dump the configuration status.
  *
  * Requires:
  * \li	'zone' to be a valid zone.
  */

-const char *
+void *
 dns_zone_getcfg(dns_zone_t *zone);
 /*%<
- * Return a pointer to the configuration text for 'zone', that was
- * previously saved using _setcfg().
+ * Return a pointer to the configuration object for 'zone', that was
+ * previously set using _setcfg().
  *
  * Requires:
  * \li	'zone' to be a valid zone.
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index 2434fc5355..84843ad3db 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -13103,7 +13103,7 @@ zone_shutdown(void *arg) {
 	}

 	/* Detach the zone configuration pointer */
-	dns_zone_setcfg(zone, NULL);
+	dns_zone_setcfg(zone, NULL, NULL);

 	zone_clear_inline_sync(zone);

diff --git a/lib/dns/zone_p.h b/lib/dns/zone_p.h
index 2cc6d4d693..84f9655e1f 100644
--- a/lib/dns/zone_p.h
+++ b/lib/dns/zone_p.h
@@ -622,8 +622,9 @@ struct dns_zone {
 	void *hooktable;
 	void (*hooktable_free)(isc_mem_t *, void **);

-	/* Configuration text */
-	char *cfg;
+	/* Configuration object */
+	void *cfg;
+	void (*cfg_detach)(void *);
 };

 typedef struct {
diff --git a/lib/dns/zoneproperties.c b/lib/dns/zoneproperties.c
index b2589db398..56a6a3f99c 100644
--- a/lib/dns/zoneproperties.c
+++ b/lib/dns/zoneproperties.c
@@ -2040,18 +2040,17 @@ dns_zone_sethooktable(dns_zone_t *zone, void *hooktable,
 }

 void
-dns_zone_setcfg(dns_zone_t *zone, const char *cfg) {
+dns_zone_setcfg(dns_zone_t *zone, void *cfg, void (*cfg_detach)(void *)) {
 	REQUIRE(DNS_ZONE_VALID(zone));

-	if (zone->cfg != NULL) {
-		isc_mem_free(zone->mctx, zone->cfg);
-	}
-	if (cfg != NULL) {
-		zone->cfg = isc_mem_strdup(zone->mctx, cfg);
+	if (zone->cfg != NULL && zone->cfg_detach != NULL) {
+		zone->cfg_detach(zone->cfg);
 	}
+	zone->cfg = cfg;
+	zone->cfg_detach = cfg_detach;
 }

-const char *
+void *
 dns_zone_getcfg(dns_zone_t *zone) {
 	REQUIRE(DNS_ZONE_VALID(zone));