save effective configuration as text

the effective configuration tree is now detached if allow-new-zones
or catalog-zones aren't enabled in any views. this reduces memory
consumption while still allowing "rndc showconf -effective" to work.
This commit is contained in:
Evan Hunt 2025-11-11 18:50:23 -08:00 committed by Colin Vidal
parent 6a57c6e8f6
commit f9922eb65a
2 changed files with 84 additions and 59 deletions

View file

@ -110,7 +110,8 @@ struct named_server {
isc_signal_t *sigusr1;
cfg_aclconfctx_t *aclctx;
isc_buffer_t *userconf;
isc_buffer_t *userconftext;
isc_buffer_t *effectivetext;
cfg_obj_t *effectiveconfig;
};

View file

@ -7690,7 +7690,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) {
create_views(cfg_obj_t *config, dns_viewlist_t *viewlist, bool *nzp) {
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *bindview = NULL;
const cfg_obj_t *views = NULL;
@ -7724,6 +7724,9 @@ create_views(cfg_obj_t *config, dns_viewlist_t *viewlist) {
CHECK(setup_newzones(view, config, vconfig));
explicitviews = true;
if (view->newzone.allowed) {
*nzp = true;
}
dns_view_detach(&view);
}
@ -7736,6 +7739,9 @@ create_views(cfg_obj_t *config, dns_viewlist_t *viewlist) {
INSIST(view != NULL);
CHECK(setup_newzones(view, config, NULL));
if (view->newzone.allowed) {
*nzp = true;
}
dns_view_detach(&view);
}
@ -7925,7 +7931,8 @@ 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) {
named_server_t *server, bool first_time,
bool *newzones_allowed) {
const cfg_obj_t *maps[3];
const cfg_obj_t *obj = NULL;
const cfg_obj_t *options = NULL;
@ -8000,7 +8007,7 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
goto cleanup_kasplist;
}
result = create_views(effectiveconfig, &viewlist);
result = create_views(effectiveconfig, &viewlist, newzones_allowed);
if (result != ISC_R_SUCCESS) {
goto cleanup_viewlist;
}
@ -8986,14 +8993,6 @@ 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;
@ -9003,8 +9002,8 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
}
/* Configure the statistics channel(s) */
result = named_statschannels_configure(
named_g_server, server->effectiveconfig, server->aclctx);
result = named_statschannels_configure(named_g_server, effectiveconfig,
server->aclctx);
if (result != ISC_R_SUCCESS) {
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
ISC_LOG_ERROR,
@ -9017,8 +9016,7 @@ apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *bindkeys,
* Bind the control port(s).
*/
result = named_controls_configure(named_g_server->controls,
server->effectiveconfig,
server->aclctx);
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",
@ -9108,7 +9106,6 @@ cleanup_aclctx:
ISC_LOG_DEBUG(1), "apply_configuration: %s",
isc_result_totext(result));
cfg_obj_detach(&effectiveconfig);
return result;
}
@ -9117,11 +9114,8 @@ 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 = {
.magic = DZARG_MAGIC,
.result = ISC_R_SUCCESS,
.text = &server->userconf,
};
ns_dzarg_t dzarg;
bool newzones_allowed = false;
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
ISC_LOG_DEBUG(1), "load_configuration");
@ -9163,17 +9157,51 @@ load_configuration(named_server_t *server, bool first_time) {
effective = cfg_effective_config(config, builtin);
/*
* 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.
* 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.
*/
if (server->userconf != NULL) {
isc_buffer_free(&server->userconf);
if (server->effectiveconfig != NULL) {
cfg_obj_detach(&server->effectiveconfig);
}
isc_buffer_allocate(isc_g_mctx, &server->userconf, BUFSIZ);
if (server->effectivetext != NULL) {
isc_buffer_free(&server->effectivetext);
}
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,
};
cfg_printx(config, 0, emit_text, &dzarg);
result = apply_configuration(effective, bindkeys, server, first_time);
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;
}
cleanup:
if (bindkeys != NULL) {
@ -9185,6 +9213,9 @@ cleanup:
if (builtin != NULL) {
cfg_obj_detach(&builtin);
}
if (effective != NULL) {
cfg_obj_detach(&effective);
}
return result;
}
@ -9807,8 +9838,12 @@ named_server_destroy(named_server_t **serverp) {
isc_tlsctx_cache_detach(&server->tlsctx_client_cache);
}
if (server->userconf != NULL) {
isc_buffer_free(&server->userconf);
if (server->userconftext != NULL) {
isc_buffer_free(&server->userconftext);
}
if (server->effectivetext != NULL) {
isc_buffer_free(&server->effectivetext);
}
if (server->effectiveconfig != NULL) {
@ -13902,14 +13937,8 @@ cleanup:
isc_result_t
named_server_showconf(named_server_t *server, isc_lex_t *lex,
isc_buffer_t **text) {
isc_result_t result, tresult;
isc_result_t result = ISC_R_SUCCESS;
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 && *text != NULL);
@ -13920,37 +13949,32 @@ named_server_showconf(named_server_t *server, isc_lex_t *lex,
if (arg == NULL) {
return ISC_R_UNEXPECTEDEND;
}
if (strcasecmp(arg, "-user") == 0) {
putmem(text, isc_buffer_base(server->userconf),
isc_buffer_usedlength(server->userconf));
result = ISC_R_SUCCESS;
goto cleanup;
} else if (strcasecmp(arg, "-builtin") == 0) {
named_config_parsedefaults(&config);
result = putmem(text, isc_buffer_base(server->userconftext),
isc_buffer_usedlength(server->userconftext));
} else if (strcasecmp(arg, "-effective") == 0) {
cfg_obj_attach(server->effectiveconfig, &config);
result = putmem(text, isc_buffer_base(server->effectivetext),
isc_buffer_usedlength(server->effectivetext));
} 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;
} else {
CHECK(DNS_R_SYNTAX);
result = 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;
}