save zone configuration as text

as previously mentioned in commit c65b2868ab, a cfg_obj_t
configuration tree structure takes up considerably more space than
the canonical text. since the zone configuration saved in the zone
object using dns_zone_setcfg() is only currently used for "rndc
showzone", it can be saved as text more efficiently than as an
object tree. (and, if a tree were needed, the text could be
re-parsed quickly; zone configuration text is generally small.)
This commit is contained in:
Evan Hunt 2025-11-11 15:46:23 -08:00 committed by Colin Vidal
parent 2affdbce19
commit 6a57c6e8f6
4 changed files with 53 additions and 47 deletions

View file

@ -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.
@ -9077,18 +9112,6 @@ cleanup_aclctx:
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;
@ -13842,10 +13865,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 +13886,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;

View file

@ -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:

View file

@ -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.

View file

@ -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));