diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 8e866f1bc8..a716110e83 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -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; }; diff --git a/bin/named/server.c b/bin/named/server.c index 52b79a2154..5b1bba785d 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -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; } diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index bfe72665b9..15a1a8c71a 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -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: diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index e6cbb76372..d9821e7213 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -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. diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 546de131e3..d0667e7dd8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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));