mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-25 02:47:54 -04:00
fix: dev: Save configuration as text
A `cfg_obj_t` object tree structure takes up considerably more space than the equivalent canonical text. If `allow-new-zones` is disabled and catalog zones are not in use, then we don't need the object tree. By storing the configuration in text format, we can use less memory, and `rndc showconf` and `rndc showzone` still work. Merge branch 'each-cfg-as-text' into 'main' See merge request isc-projects/bind9!11236
This commit is contained in:
commit
09bcacbd36
5 changed files with 137 additions and 106 deletions
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6040,6 +6040,39 @@ 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;
|
||||
ns_dzarg_t dzarg = {
|
||||
.magic = DZARG_MAGIC,
|
||||
.text = &text,
|
||||
};
|
||||
|
||||
isc_buffer_allocate(isc_g_mctx, &text, 256);
|
||||
|
||||
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.
|
||||
*/
|
||||
|
|
@ -6249,6 +6282,7 @@ 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;
|
||||
}
|
||||
|
|
@ -6425,6 +6459,7 @@ 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.
|
||||
|
|
@ -7655,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;
|
||||
|
|
@ -7689,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);
|
||||
}
|
||||
|
||||
|
|
@ -7701,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);
|
||||
}
|
||||
|
||||
|
|
@ -7890,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;
|
||||
|
|
@ -7965,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;
|
||||
}
|
||||
|
|
@ -8951,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;
|
||||
|
||||
|
|
@ -8968,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,
|
||||
|
|
@ -8982,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",
|
||||
|
|
@ -9073,32 +9106,16 @@ 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 = {
|
||||
.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");
|
||||
|
|
@ -9140,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) {
|
||||
|
|
@ -9162,6 +9213,9 @@ cleanup:
|
|||
if (builtin != NULL) {
|
||||
cfg_obj_detach(&builtin);
|
||||
}
|
||||
if (effective != NULL) {
|
||||
cfg_obj_detach(&effective);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -9784,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) {
|
||||
|
|
@ -13842,10 +13900,9 @@ 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;
|
||||
ns_dzarg_t dzarg;
|
||||
const char *zconfig = NULL;
|
||||
|
||||
REQUIRE(text != NULL);
|
||||
|
||||
|
|
@ -13864,12 +13921,7 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex,
|
|||
}
|
||||
|
||||
CHECK(putstr(text, "zone "));
|
||||
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, zconfig));
|
||||
CHECK(putstr(text, ";"));
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
|
|
@ -13885,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);
|
||||
|
||||
|
|
@ -13903,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -869,12 +869,6 @@ process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
|
|||
return dns_notifytype_explicit;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -1913,11 +1907,6 @@ 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:
|
||||
|
|
|
|||
|
|
@ -2763,19 +2763,20 @@ dns_zone_unloadplugins(dns_zone_t *zone);
|
|||
*/
|
||||
|
||||
void
|
||||
dns_zone_setcfg(dns_zone_t *zone, void *cfg, void (*cfg_detach)(void *));
|
||||
dns_zone_setcfg(dns_zone_t *zone, const char *cfg);
|
||||
/*%<
|
||||
* Set a pointer to the configuration object for 'zone', which can be
|
||||
* Save a copy of the configuration text for 'zone', which can be
|
||||
* used later to dump the configuration status.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'zone' to be a valid zone.
|
||||
*/
|
||||
void *
|
||||
|
||||
const char *
|
||||
dns_zone_getcfg(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Return a pointer to the configuration object for 'zone', that was
|
||||
* previously set using _setcfg().
|
||||
* Return a pointer to the configuration text for 'zone', that was
|
||||
* previously saved using _setcfg().
|
||||
*
|
||||
* Requires:
|
||||
* \li 'zone' to be a valid zone.
|
||||
|
|
|
|||
|
|
@ -528,9 +528,8 @@ struct dns_zone {
|
|||
void *hooktable;
|
||||
void (*hooktable_free)(isc_mem_t *, void **);
|
||||
|
||||
/* Configuration object */
|
||||
void *cfg;
|
||||
void (*cfg_detach)(void *);
|
||||
/* Configuration text */
|
||||
char *cfg;
|
||||
};
|
||||
|
||||
#define zonediff_init(z, d) \
|
||||
|
|
@ -14718,7 +14717,7 @@ zone_shutdown(void *arg) {
|
|||
}
|
||||
|
||||
/* Detach the zone configuration pointer */
|
||||
dns_zone_setcfg(zone, NULL, NULL);
|
||||
dns_zone_setcfg(zone, NULL);
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
INSIST(zone != zone->raw);
|
||||
|
|
@ -24058,18 +24057,18 @@ dns_zone_unloadplugins(dns_zone_t *zone) {
|
|||
}
|
||||
|
||||
void
|
||||
dns_zone_setcfg(dns_zone_t *zone, void *cfg, void (*cfg_detach)(void *)) {
|
||||
dns_zone_setcfg(dns_zone_t *zone, const char *cfg) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
if (zone->cfg != NULL && zone->cfg_detach != NULL) {
|
||||
zone->cfg_detach(zone->cfg);
|
||||
zone->cfg = NULL;
|
||||
if (zone->cfg != NULL) {
|
||||
isc_mem_free(zone->mctx, zone->cfg);
|
||||
}
|
||||
if (cfg != NULL) {
|
||||
zone->cfg = isc_mem_strdup(zone->mctx, cfg);
|
||||
}
|
||||
zone->cfg = cfg;
|
||||
zone->cfg_detach = cfg_detach;
|
||||
}
|
||||
|
||||
void *
|
||||
const char *
|
||||
dns_zone_getcfg(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue