diff --git a/bin/named/control.c b/bin/named/control.c index aa2b9d3930..ba6001bac8 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -276,6 +276,8 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly, result = named_server_dumpsecroots(named_g_server, lex, text); } else if (command_compare(command, NAMED_COMMAND_SERVESTALE)) { result = named_server_servestale(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_SHOWCONF)) { + result = named_server_showconf(named_g_server, lex, text); } else if (command_compare(command, NAMED_COMMAND_SHOWZONE)) { result = named_server_showzone(named_g_server, lex, text); } else if (command_compare(command, NAMED_COMMAND_SIGNING)) { diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h index 343d41a272..82e9d4621e 100644 --- a/bin/named/include/named/control.h +++ b/bin/named/include/named/control.h @@ -61,6 +61,7 @@ #define NAMED_COMMAND_SCAN "scan" #define NAMED_COMMAND_SECROOTS "secroots" #define NAMED_COMMAND_SERVESTALE "serve-stale" +#define NAMED_COMMAND_SHOWCONF "showconf" #define NAMED_COMMAND_SHOWZONE "showzone" #define NAMED_COMMAND_SIGN "sign" #define NAMED_COMMAND_SIGNING "signing" diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index da28b0cf5b..8da065e4b9 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -110,6 +110,8 @@ struct named_server { isc_signal_t *sigusr1; cfg_aclconfctx_t *aclctx; + cfg_obj_t *userconfig; + cfg_obj_t *effectiveconfig; }; #define NAMED_SERVER_MAGIC ISC_MAGIC('S', 'V', 'E', 'R') @@ -324,6 +326,13 @@ isc_result_t named_server_showzone(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); +/*% + * Show the full current user configuration. + */ +isc_result_t +named_server_showconf(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); + /*% * Lists the status of the signing records for a given zone. */ diff --git a/bin/named/server.c b/bin/named/server.c index 61cc44cca3..2be9f4f999 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -301,18 +301,6 @@ typedef struct matching_view_ctx { dns_view_t *view; } matching_view_ctx_t; -/*% - * Configuration context to retain for each view that allows - * new zones to be added at runtime. - */ -typedef struct ns_cfgctx { - isc_mem_t *mctx; - cfg_obj_t *config; - cfg_obj_t *vconfig; - cfg_obj_t *nzf_config; - cfg_aclconfctx_t *aclctx; -} ns_cfgctx_t; - /*% * A function to write out added-zone configuration to the new_zone_file * specified in 'view'. Maybe called by delete_zoneconf(). @@ -509,9 +497,6 @@ find_maplist(const cfg_obj_t *config, const char *listname, const char *name); static isc_result_t add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); -static void -newzone_cfgctx_destroy(void **cfgp); - static isc_result_t putstr(isc_buffer_t **b, const char *str); @@ -545,7 +530,7 @@ nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); #endif /* ifdef HAVE_LMDB */ static isc_result_t -load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg); +load_nzf(dns_view_t *view); /*% * Configure a single view ACL at '*aclp'. Get its configuration from @@ -2339,29 +2324,20 @@ catz_addmodzone_cb(void *arg) { const cfg_obj_t *zlist = NULL; cfg_obj_t *zoneconf = NULL; cfg_obj_t *zoneobj = NULL; - ns_cfgctx_t *cfg = NULL; dns_zone_t *zone = NULL; + dns_view_t *view = cz->view; if (isc_loop_shuttingdown(isc_loop_get(isc_tid()))) { goto cleanup; } - /* - * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' - * is true, so this is expected to be non-NULL. - */ - cfg = (ns_cfgctx_t *)cz->view->new_zone_config; - if (cfg == NULL) { - CHECK(ISC_R_FAILURE); - } - name = dns_catz_entry_getname(cz->entry); isc_buffer_init(&namebuf, nameb, DNS_NAME_FORMATSIZE); dns_name_totext(name, DNS_NAME_OMITFINALDOT, &namebuf); isc_buffer_putuint8(&namebuf, 0); - result = dns_fwdtable_find(cz->view->fwdtable, name, &dnsforwarders); + result = dns_fwdtable_find(view->fwdtable, name, &dnsforwarders); if (result == ISC_R_SUCCESS && dnsforwarders->fwdpolicy == dns_fwdpolicy_only) { @@ -2374,7 +2350,7 @@ catz_addmodzone_cb(void *arg) { goto cleanup; } - result = dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone); + result = dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone); if (cz->mod) { dns_catz_zone_t *parentcatz; @@ -2455,7 +2431,7 @@ catz_addmodzone_cb(void *arg) { confbuf = NULL; result = dns_catz_generate_zonecfg(cz->origin, cz->entry, &confbuf); if (result == ISC_R_SUCCESS) { - result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0, + result = cfg_parse_buffer(isc_g_mctx, confbuf, "catz", 0, &cfg_type_addzoneconf, 0, &zoneconf); isc_buffer_free(&confbuf); } @@ -2481,12 +2457,13 @@ catz_addmodzone_cb(void *arg) { /* Mark view unfrozen so that zone can be added */ isc_loopmgr_pause(); - dns_view_thaw(cz->view); - result = configure_zone(cfg->config, zoneobj, cfg->vconfig, cz->view, - &cz->cbd->server->viewlist, - &cz->cbd->server->kasplist, cfg->aclctx, true, - false, true, cz->mod); - dns_view_freeze(cz->view); + dns_view_thaw(view); + result = configure_zone( + cz->cbd->server->effectiveconfig, zoneobj, + view->newzone.vconfig, view, &cz->cbd->server->viewlist, + &cz->cbd->server->kasplist, cz->cbd->server->aclctx, true, + false, true, cz->mod); + dns_view_freeze(view); isc_loopmgr_resume(); if (result != ISC_R_SUCCESS) { @@ -2498,7 +2475,7 @@ catz_addmodzone_cb(void *arg) { } /* Is it there yet? */ - CHECK(dns_view_findzone(cz->view, name, DNS_ZTFIND_EXACT, &zone)); + CHECK(dns_view_findzone(view, name, DNS_ZTFIND_EXACT, &zone)); /* * Load the zone from the master file. If this fails, we'll @@ -2520,7 +2497,7 @@ catz_addmodzone_cb(void *arg) { } /* Remove the zone from the zone table */ - dns_view_delzone(cz->view, zone); + dns_view_delzone(view, zone); goto cleanup; } @@ -2540,7 +2517,7 @@ cleanup: } dns_catz_entry_detach(cz->origin, &cz->entry); dns_catz_zone_detach(&cz->origin); - dns_view_weakdetach(&cz->view); + dns_view_weakdetach(&view); isc_mem_putanddetach(&cz->mctx, cz, sizeof(*cz)); } @@ -2707,7 +2684,6 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { char nameb[DNS_NAME_FORMATSIZE]; cfg_obj_t *zoneconf = NULL; cfg_obj_t *zoneobj = NULL; - ns_cfgctx_t *cfg = NULL; dns_zone_t *zone = NULL; isc_result_t result; @@ -2722,18 +2698,9 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { return; } - /* - * A non-empty 'catalog-zones' statement implies that 'allow-new-zones' - * is true, so this is expected to be non-NULL. - */ - cfg = (ns_cfgctx_t *)view->new_zone_config; - if (cfg == NULL) { - CHECK(ISC_R_FAILURE); - } - result = dns_catz_generate_zonecfg(data->catz, entry, &confbuf); if (result == ISC_R_SUCCESS) { - result = cfg_parse_buffer(cfg->mctx, confbuf, "catz", 0, + result = cfg_parse_buffer(isc_g_mctx, confbuf, "catz", 0, &cfg_type_addzoneconf, 0, &zoneconf); isc_buffer_free(&confbuf); } @@ -2756,10 +2723,10 @@ catz_reconfigure(dns_catz_entry_t *entry, void *arg1, void *arg2) { } zoneobj = cfg_listelt_value(cfg_list_first(zlist)); - result = configure_zone(data->config, zoneobj, cfg->vconfig, view, - &data->cbd->server->viewlist, - &data->cbd->server->kasplist, cfg->aclctx, true, - false, true, true); + result = configure_zone( + data->config, zoneobj, view->newzone.vconfig, view, + &data->cbd->server->viewlist, &data->cbd->server->kasplist, + data->cbd->server->aclctx, true, false, true, true); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, @@ -7156,23 +7123,83 @@ cleanup: return result; } +static void +newzone_cleanup(dns_view_t *view) { + if (view->newzone.vconfig != NULL) { + cfg_obj_detach(&view->newzone.vconfig); + } + if (view->newzone.nzconfig != NULL) { + cfg_obj_detach(&view->newzone.nzconfig); + } + +#ifdef HAVE_LMDB + if (view->newzone.dbenv != NULL) { + mdb_env_close(view->newzone.dbenv); + view->newzone.dbenv = NULL; + } +#endif /* ifdef HAVE_LMDB */ + + if (view->newzone.file != NULL) { + isc_mem_free(view->mctx, view->newzone.file); + } + if (view->newzone.dir != NULL) { + isc_mem_free(view->mctx, view->newzone.dir); + } + if (view->newzone.db != NULL) { + isc_mem_free(view->mctx, view->newzone.db); + } + + view->newzone.allowed = false; +} + static isc_result_t -setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, - cfg_aclconfctx_t *aclctx) { +nz_filename(dns_view_t *view, const char *suffix, char *buffer, size_t buflen) { + isc_result_t result; + char newbuf[PATH_MAX]; + + result = isc_file_sanitize(view->newzone.dir, view->name, suffix, + buffer, buflen); + if (result != ISC_R_SUCCESS) { + return result; + } else if (view->newzone.dir == NULL || isc_file_exists(buffer)) { + return ISC_R_SUCCESS; + } else { + /* Save buffer */ + strlcpy(newbuf, buffer, sizeof(newbuf)); + } + + /* + * It isn't in the specified directory; check CWD. + */ + result = isc_file_sanitize(NULL, view->name, suffix, buffer, buflen); + if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) { + return result; + } + + /* + * File does not exist in either 'directory' or CWD, + * so use the path in 'directory'. + */ + strlcpy(buffer, newbuf, buflen); + return ISC_R_SUCCESS; +} + +static isc_result_t +setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig) { isc_result_t result = ISC_R_SUCCESS; - bool allow = false; - ns_cfgctx_t *nzcfg = NULL; const cfg_obj_t *maps[4]; const cfg_obj_t *options = NULL, *voptions = NULL; const cfg_obj_t *nz = NULL; - const cfg_obj_t *nzdir = NULL; const char *dir = NULL; const cfg_obj_t *obj = NULL; + char buffer[1024]; int i = 0; - uint64_t mapsize = 0ULL; REQUIRE(config != NULL); + /* Unnecessary but harmless */ + newzone_cleanup(view); + if (vconfig != NULL) { voptions = cfg_tuple_get(vconfig, "options"); } @@ -7187,11 +7214,26 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, result = named_config_get(maps, "allow-new-zones", &nz); if (result == ISC_R_SUCCESS) { - allow = cfg_obj_asboolean(nz); + view->newzone.allowed = cfg_obj_asboolean(nz); } - result = named_config_get(maps, "new-zones-directory", &nzdir); + if (!view->newzone.allowed) { + /* + * A non-empty catalog-zones statement implies allow-new-zones + */ + const cfg_obj_t *cz = NULL; + result = named_config_get(maps, "catalog-zones", &cz); + if (result == ISC_R_SUCCESS) { + const cfg_listelt_t *e = + cfg_list_first(cfg_tuple_get(cz, "zone list")); + if (e != NULL) { + view->newzone.allowed = true; + } + } + } + + result = named_config_get(maps, "new-zones-directory", &obj); if (result == ISC_R_SUCCESS) { - dir = cfg_obj_asstring(nzdir); + dir = cfg_obj_asstring(obj); result = isc_file_isdirectory(dir); if (result != ISC_R_SUCCESS) { isc_log_write(DNS_LOGCATEGORY_SECURITY, @@ -7209,78 +7251,86 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, return ISC_R_NOPERM; } - dns_view_setnewzonedir(view, dir); + view->newzone.dir = isc_mem_strdup(view->mctx, dir); } + CHECK(nz_filename(view, "nzf", buffer, sizeof(buffer))); + view->newzone.file = isc_mem_strdup(view->mctx, buffer); + #ifdef HAVE_LMDB + uint64_t mapsize = 0ULL; + + obj = NULL; result = named_config_get(maps, "lmdb-mapsize", &obj); if (result == ISC_R_SUCCESS && obj != NULL) { mapsize = cfg_obj_asuint64(obj); if (mapsize < (1ULL << 20)) { /* 1 megabyte */ cfg_obj_log(obj, ISC_LOG_ERROR, - "'lmdb-mapsize " - "%" PRId64 "' " - "is too small", + "'lmdb-mapsize %" PRId64 "' is too small", mapsize); return ISC_R_FAILURE; } else if (mapsize > (1ULL << 40)) { /* 1 terabyte */ cfg_obj_log(obj, ISC_LOG_ERROR, - "'lmdb-mapsize " - "%" PRId64 "' " - "is too large", + "'lmdb-mapsize %" PRId64 "' is too large", mapsize); return ISC_R_FAILURE; } } -#else /* ifdef HAVE_LMDB */ - UNUSED(obj); + + if (view->newzone.allowed) { + CHECK(nz_filename(view, "nzd", buffer, sizeof(buffer))); + view->newzone.db = isc_mem_strdup(view->mctx, buffer); + + MDB_env *env = NULL; + int status = mdb_env_create(&env); + if (status != MDB_SUCCESS) { + isc_log_write(DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, + "mdb_env_create failed: %s", + mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + + if (mapsize != 0ULL) { + status = mdb_env_set_mapsize(env, mapsize); + if (status != MDB_SUCCESS) { + isc_log_write(DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, + ISC_LOG_ERROR, + "mdb_env_set_mapsize failed: %s", + mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + view->newzone.mapsize = mapsize; + } + + status = mdb_env_open(env, view->newzone.db, DNS_LMDB_FLAGS, + 0600); + if (status != MDB_SUCCESS) { + isc_log_write(DNS_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, + "mdb_env_open of '%s' failed: %s", + view->newzone.db, mdb_strerror(status)); + CHECK(ISC_R_FAILURE); + } + + view->newzone.dbenv = env; + env = NULL; + } #endif /* HAVE_LMDB */ - /* - * A non-empty catalog-zones statement implies allow-new-zones - */ - if (!allow) { - const cfg_obj_t *cz = NULL; - result = named_config_get(maps, "catalog-zones", &cz); - if (result == ISC_R_SUCCESS) { - const cfg_listelt_t *e = - cfg_list_first(cfg_tuple_get(cz, "zone list")); - if (e != NULL) { - allow = true; - } - } - } - - if (!allow) { - dns_view_setnewzones(view, false, NULL, NULL, 0ULL); - return ISC_R_SUCCESS; - } - - nzcfg = isc_mem_get(view->mctx, sizeof(*nzcfg)); - *nzcfg = (ns_cfgctx_t){ 0 }; - - /* - * We attach the parser that will be used for added zones to avoid - * a shutdown race later. - */ - isc_mem_attach(view->mctx, &nzcfg->mctx); - cfg_aclconfctx_attach(aclctx, &nzcfg->aclctx); - - result = dns_view_setnewzones(view, true, nzcfg, newzone_cfgctx_destroy, - mapsize); - if (result != ISC_R_SUCCESS) { - cfg_aclconfctx_detach(&nzcfg->aclctx); - isc_mem_putanddetach(&nzcfg->mctx, nzcfg, sizeof(*nzcfg)); - dns_view_setnewzones(view, false, NULL, NULL, 0ULL); - return result; - } - - cfg_obj_attach(config, &nzcfg->config); + view->newzone.cleanup = newzone_cleanup; if (vconfig != NULL) { - cfg_obj_attach(vconfig, &nzcfg->vconfig); + cfg_obj_attach(vconfig, &view->newzone.vconfig); } - result = load_nzf(view, nzcfg); + if (view->newzone.allowed) { + result = load_nzf(view); + } + return result; + +cleanup: + newzone_cleanup(view); return result; } @@ -7330,11 +7380,10 @@ static isc_result_t configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, cfg_aclconfctx_t *aclctx, dns_kasplist_t *kasplist) { isc_result_t result; - ns_cfgctx_t *nzctx = NULL; const cfg_obj_t *zonelist = NULL; - nzctx = view->new_zone_config; - if (nzctx == NULL || nzctx->nzf_config == NULL) { + if (!view->newzone.allowed || view->newzone.nzconfig == NULL) { + /* New zones are disallowed, or the NZF file is empty */ return ISC_R_SUCCESS; } @@ -7343,7 +7392,7 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, view->name); zonelist = NULL; - cfg_map_get(nzctx->nzf_config, "zone", &zonelist); + cfg_map_get(view->newzone.nzconfig, "zone", &zonelist); CFG_LIST_FOREACH(zonelist, element) { const cfg_obj_t *zconfig = cfg_listelt_value(element); @@ -7412,14 +7461,14 @@ data_to_cfg(dns_view_t *view, MDB_val *key, MDB_val *data, isc_buffer_t **text, snprintf(bufname, sizeof(bufname), "%.*s", (int)zone_name_len, zone_name); - result = cfg_parse_buffer(view->mctx, *text, bufname, 0, + result = cfg_parse_buffer(isc_g_mctx, *text, bufname, 0, &cfg_type_addzoneconf, 0, &zoneconf); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "parsing config for zone '%.*s' in " "NZD database '%s' failed", - (int)zone_name_len, zone_name, view->new_zone_db); + (int)zone_name_len, zone_name, view->newzone.db); goto cleanup; } @@ -7453,7 +7502,7 @@ typedef isc_result_t (*newzone_cfg_cb_t)(const cfg_obj_t *zconfig, * transforming NZD data into a zone configuration object or if "callback" * returns an error. * - * Caller must hold 'view->new_zone_lock'. + * Caller must hold 'view->newzone.lock'. */ static isc_result_t for_all_newzone_cfgs(newzone_cfg_cb_t callback, cfg_obj_t *config, @@ -7560,23 +7609,22 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, MDB_txn *txn = NULL; MDB_dbi dbi; - if (view->new_zone_config == NULL) { + if (!view->newzone.allowed) { return ISC_R_SUCCESS; } - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); result = nzd_open(view, MDB_RDONLY, &txn, &dbi); if (result != ISC_R_SUCCESS) { - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); return ISC_R_SUCCESS; } isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, - "loading NZD configs from '%s' " - "for view '%s'", - view->new_zone_db, view->name); + "loading NZD configs from '%s' for view '%s'", + view->newzone.db, view->name); result = for_all_newzone_cfgs(configure_newzone, config, vconfig, view, aclctx, kasplist, txn, dbi); @@ -7596,7 +7644,7 @@ configure_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, (void)nzd_close(&txn, false); - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); return result; } @@ -7607,8 +7655,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, cfg_aclconfctx_t *aclctx, - dns_viewlist_t *viewlist) { +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; @@ -7640,9 +7687,8 @@ create_views(cfg_obj_t *config, cfg_aclconfctx_t *aclctx, CHECK(create_view(vconfig, viewlist, &view)); INSIST(view != NULL); - result = setup_newzones(view, config, vconfig, aclctx); + CHECK(setup_newzones(view, config, vconfig)); explicitviews = true; - dns_view_detach(&view); } @@ -7654,7 +7700,7 @@ create_views(cfg_obj_t *config, cfg_aclconfctx_t *aclctx, CHECK(create_view(NULL, viewlist, &view)); INSIST(view != NULL); - CHECK(setup_newzones(view, config, NULL, aclctx)); + CHECK(setup_newzones(view, config, NULL)); dns_view_detach(&view); } @@ -7843,8 +7889,9 @@ configure_kasplist(const cfg_obj_t *config, dns_kasplist_t *kasplist, } static isc_result_t -apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, - named_server_t *server, bool first_time) { +apply_configuration(cfg_obj_t *effectiveconfig, cfg_obj_t *userconfig, + cfg_obj_t *bindkeys, 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; @@ -7897,7 +7944,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, */ i = 0; options = NULL; - result = cfg_map_get(config, "options", &options); + result = cfg_map_get(effectiveconfig, "options", &options); if (result == ISC_R_SUCCESS) { maps[i++] = options; } @@ -7909,17 +7956,17 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, goto cleanup_aclctx; } - result = configure_keystores(config, &keystorelist); + result = configure_keystores(effectiveconfig, &keystorelist); if (result != ISC_R_SUCCESS) { goto cleanup_keystorelist; } - result = configure_kasplist(config, &kasplist, &keystorelist); + result = configure_kasplist(effectiveconfig, &kasplist, &keystorelist); if (result != ISC_R_SUCCESS) { goto cleanup_kasplist; } - result = create_views(config, aclctx, &viewlist); + result = create_views(effectiveconfig, &viewlist); if (result != ISC_R_SUCCESS) { goto cleanup_viewlist; } @@ -8034,7 +8081,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, result = named_config_get(maps, "sig0checks-quota-exempt", &obj); if (result == ISC_R_SUCCESS) { result = cfg_acl_fromconfig( - obj, config, aclctx, isc_g_mctx, 0, + obj, effectiveconfig, aclctx, isc_g_mctx, 0, &server->sctx->sig0checksquota_exempt); INSIST(result == ISC_R_SUCCESS); } @@ -8043,8 +8090,9 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, * Set "blackhole". Only legal at options level; there is * no default. */ - result = configure_view_acl(NULL, config, "blackhole", NULL, aclctx, - isc_g_mctx, &server->sctx->blackholeacl); + result = configure_view_acl(NULL, effectiveconfig, "blackhole", NULL, + aclctx, isc_g_mctx, + &server->sctx->blackholeacl); if (result != ISC_R_SUCCESS) { goto cleanup_tls; } @@ -8296,7 +8344,8 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, if (named_g_port != 0) { listen_port = named_g_port; } else { - result = named_config_getport(config, "port", &listen_port); + result = named_config_getport(effectiveconfig, "port", + &listen_port); if (result != ISC_R_SUCCESS) { goto cleanup_portsets; } @@ -8345,7 +8394,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, goto cleanup_portsets; } result = listenlist_fromconfig( - clistenon, config, aclctx, isc_g_mctx, AF_INET, + clistenon, effectiveconfig, aclctx, isc_g_mctx, AF_INET, server->tlsctx_server_cache, &listenon); if (result != ISC_R_SUCCESS) { goto cleanup_portsets; @@ -8369,8 +8418,8 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, goto cleanup_portsets; } result = listenlist_fromconfig( - clistenon, config, aclctx, isc_g_mctx, AF_INET6, - server->tlsctx_server_cache, &listenon); + clistenon, effectiveconfig, aclctx, isc_g_mctx, + AF_INET6, server->tlsctx_server_cache, &listenon); if (result != ISC_R_SUCCESS) { goto cleanup_portsets; } @@ -8491,9 +8540,9 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, */ (void)configure_session_key(maps, server, isc_g_mctx, first_time); - result = configure_views(config, bindkeys, aclctx, tlsctx_client_cache, - &viewlist, &cachelist, &kasplist, server, - first_time); + result = configure_views(effectiveconfig, bindkeys, aclctx, + tlsctx_client_cache, &viewlist, &cachelist, + &kasplist, server, first_time); if (result != ISC_R_SUCCESS) { goto cleanup_cachelist; } @@ -8575,7 +8624,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, "statement for logging due to " "-g option"); - (void)cfg_map_get(config, "logging", &logobj); + (void)cfg_map_get(effectiveconfig, "logging", &logobj); if (logobj != NULL) { result = named_logconfig(NULL, logobj); if (result != ISC_R_SUCCESS) { @@ -8594,7 +8643,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, isc_logconfig_create(&logc); logobj = NULL; - (void)cfg_map_get(config, "logging", &logobj); + (void)cfg_map_get(effectiveconfig, "logging", &logobj); if (logobj != NULL) { result = named_logconfig(logc, logobj); if (result != ISC_R_SUCCESS) { @@ -8654,7 +8703,7 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, ns_server_setoption(server->sctx, NS_SERVER_LOGQUERIES, cfg_obj_asboolean(obj)); } else { - (void)cfg_map_get(config, "logging", &logobj); + (void)cfg_map_get(effectiveconfig, "logging", &logobj); if (logobj != NULL) { (void)cfg_map_get(logobj, "category", &categories); @@ -8903,6 +8952,19 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, */ named_g_defaultconfigtime = isc_time_now(); + /* + * Set the current effective and user configuration + */ + if (server->effectiveconfig != NULL) { + cfg_obj_detach(&server->effectiveconfig); + } + cfg_obj_attach(effectiveconfig, &server->effectiveconfig); + + if (server->userconfig != NULL) { + cfg_obj_detach(&server->userconfig); + } + cfg_obj_attach(userconfig, &server->userconfig); + isc_loopmgr_resume(); exclusive = false; @@ -8912,8 +8974,8 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, } /* Configure the statistics channel(s) */ - result = named_statschannels_configure(named_g_server, config, - 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, @@ -8925,7 +8987,8 @@ apply_configuration(cfg_obj_t *config, cfg_obj_t *bindkeys, /* * Bind the control port(s). */ - result = named_controls_configure(named_g_server->controls, config, + result = named_controls_configure(named_g_server->controls, + server->effectiveconfig, server->aclctx); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, @@ -9016,7 +9079,7 @@ cleanup_aclctx: ISC_LOG_DEBUG(1), "apply_configuration: %s", isc_result_totext(result)); - cfg_obj_detach(&config); + cfg_obj_detach(&effectiveconfig); return result; } @@ -9060,8 +9123,10 @@ load_configuration(named_server_t *server, bool first_time) { } } + /* Merge and apply */ effective = cfg_effective_config(config, named_g_defaultconfig); - result = apply_configuration(effective, bindkeys, server, first_time); + result = apply_configuration(effective, config, bindkeys, server, + first_time); cleanup: if (bindkeys != NULL) { @@ -9701,6 +9766,14 @@ named_server_destroy(named_server_t **serverp) { isc_tlsctx_cache_detach(&server->tlsctx_client_cache); } + if (server->userconfig != NULL) { + cfg_obj_detach(&server->userconfig); + } + + if (server->effectiveconfig != NULL) { + cfg_obj_detach(&server->effectiveconfig); + } + server->magic = 0; isc_mem_put(server->mctx, server, sizeof(*server)); *serverp = NULL; @@ -12147,9 +12220,9 @@ nzf_append(dns_view_t *view, const cfg_obj_t *zconfig) { FILE *fp = NULL; bool offsetok = false; - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); - CHECK(isc_stdio_open(view->new_zone_file, "a", &fp)); + CHECK(isc_stdio_open(view->newzone.file, "a", &fp)); CHECK(isc_stdio_seek(fp, 0, SEEK_END)); CHECK(isc_stdio_tell(fp, &offset)); @@ -12171,8 +12244,7 @@ cleanup: if (offsetok) { isc_result_t result2; - result2 = isc_file_truncate(view->new_zone_file, - offset); + result2 = isc_file_truncate(view->newzone.file, offset); if (result2 != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, @@ -12180,12 +12252,12 @@ cleanup: "Error truncating NZF file '%s' " "during rollback from append: " "%s", - view->new_zone_file, + view->newzone.file, isc_result_totext(result2)); } } } - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); return result; } @@ -12197,7 +12269,7 @@ nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { char tmp[1024]; isc_result_t result; - result = isc_file_template(view->new_zone_file, "nzf-XXXXXXXX", tmp, + result = isc_file_template(view->newzone.file, "nzf-XXXXXXXX", tmp, sizeof(tmp)); if (result == ISC_R_SUCCESS) { result = isc_file_openunique(tmp, &fp); @@ -12229,7 +12301,7 @@ nzf_writeconf(const cfg_obj_t *config, dns_view_t *view) { if (result != ISC_R_SUCCESS) { goto cleanup; } - CHECK(isc_file_rename(tmp, view->new_zone_file)); + CHECK(isc_file_rename(tmp, view->newzone.file)); return result; cleanup: @@ -12241,24 +12313,24 @@ cleanup: } static isc_result_t -load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { +load_nzf(dns_view_t *view) { isc_result_t result; /* The new zone file may not exist. That is OK. */ - if (!isc_file_exists(view->new_zone_file)) { + if (!isc_file_exists(view->newzone.file)) { return ISC_R_SUCCESS; } /* - * Parse the configuration in the NZF file. This may be called in - * multiple views, so we reset the parser each time. + * Parse the configuration in the NZF file. */ - result = cfg_parse_file(nzcfg->mctx, view->new_zone_file, - &cfg_type_addzoneconf, 0, &nzcfg->nzf_config); + result = cfg_parse_file(view->mctx, view->newzone.file, + &cfg_type_addzoneconf, 0, + &view->newzone.nzconfig); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", - view->new_zone_file, isc_result_totext(result)); + view->newzone.file, isc_result_totext(result)); } return result; @@ -12393,7 +12465,7 @@ cleanup: /* * Check whether the new zone database for 'view' can be opened for writing. * - * Caller must hold 'view->new_zone_lock'. + * Caller must hold 'view->newzone.lock'. */ static isc_result_t nzd_writable(dns_view_t *view) { @@ -12404,7 +12476,7 @@ nzd_writable(dns_view_t *view) { REQUIRE(view != NULL); - status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, 0, &txn); + status = mdb_txn_begin(view->newzone.dbenv, 0, 0, &txn); if (status != MDB_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_txn_begin: %s", @@ -12427,7 +12499,7 @@ nzd_writable(dns_view_t *view) { /* * Open the new zone database for 'view' and start a transaction for it. * - * Caller must hold 'view->new_zone_lock'. + * Caller must hold 'view->newzone.lock'. */ static isc_result_t nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { @@ -12438,7 +12510,7 @@ nzd_open(dns_view_t *view, unsigned int flags, MDB_txn **txnp, MDB_dbi *dbi) { REQUIRE(txnp != NULL && *txnp == NULL); REQUIRE(dbi != NULL); - status = mdb_txn_begin((MDB_env *)view->new_zone_dbenv, 0, flags, &txn); + status = mdb_txn_begin(view->newzone.dbenv, 0, flags, &txn); if (status != MDB_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING, "mdb_txn_begin: %s", @@ -12468,7 +12540,7 @@ cleanup: } /* - * nzd_env_close() and nzd_env_reopen are a kluge to address the + * nzd_env_close() and nzd_env_reopen() are a kluge to address the * problem of an NZD file possibly being created before we drop * root privileges. */ @@ -12479,15 +12551,15 @@ nzd_env_close(dns_view_t *view) { char lockpath[PATH_MAX]; int status, ret; - if (view->new_zone_dbenv == NULL) { + if (view->newzone.dbenv == NULL) { return; } - status = mdb_env_get_path(view->new_zone_dbenv, &dbpath); + status = mdb_env_get_path(view->newzone.dbenv, &dbpath); INSIST(status == MDB_SUCCESS); snprintf(lockpath, sizeof(lockpath), "%s-lock", dbpath); strlcpy(dbpath_copy, dbpath, sizeof(dbpath_copy)); - mdb_env_close((MDB_env *)view->new_zone_dbenv); + mdb_env_close(view->newzone.dbenv); /* * Database files must be owned by the eventual user, not by root. @@ -12501,7 +12573,7 @@ nzd_env_close(dns_view_t *view) { */ (void)isc_file_remove(lockpath); - view->new_zone_dbenv = NULL; + view->newzone.dbenv = NULL; } static isc_result_t @@ -12510,7 +12582,7 @@ nzd_env_reopen(dns_view_t *view) { MDB_env *env = NULL; int status; - if (view->new_zone_db == NULL) { + if (view->newzone.db == NULL) { return ISC_R_SUCCESS; } @@ -12524,8 +12596,8 @@ nzd_env_reopen(dns_view_t *view) { CHECK(ISC_R_FAILURE); } - if (view->new_zone_mapsize != 0ULL) { - status = mdb_env_set_mapsize(env, view->new_zone_mapsize); + if (view->newzone.mapsize != 0ULL) { + status = mdb_env_set_mapsize(env, view->newzone.mapsize); if (status != MDB_SUCCESS) { isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, @@ -12535,15 +12607,15 @@ nzd_env_reopen(dns_view_t *view) { } } - status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); + status = mdb_env_open(env, view->newzone.db, DNS_LMDB_FLAGS, 0600); if (status != MDB_SUCCESS) { isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, "mdb_env_open of '%s' failed: %s", - view->new_zone_db, mdb_strerror(status)); + view->newzone.db, mdb_strerror(status)); CHECK(ISC_R_FAILURE); } - view->new_zone_dbenv = env; + view->newzone.dbenv = env; env = NULL; result = ISC_R_SUCCESS; @@ -12558,7 +12630,7 @@ cleanup: * If 'commit' is true, commit the new zone database transaction pointed to by * 'txnp'; otherwise, abort that transaction. * - * Caller must hold 'view->new_zone_lock' for the view that the transaction + * Caller must hold 'view->newzone.lock' for the view that the transaction * pointed to by 'txnp' was started for. */ static isc_result_t @@ -12587,10 +12659,10 @@ nzd_close(MDB_txn **txnp, bool commit) { * If there's an existing NZF file, load it and migrate its data * to the NZD. * - * Caller must hold view->new_zone_lock. + * Caller must hold view->newzone.lock. */ static isc_result_t -load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { +load_nzf(dns_view_t *view) { isc_result_t result; cfg_obj_t *nzf_config = NULL; int status; @@ -12603,13 +12675,11 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { MDB_val key, data; ns_dzarg_t dzarg; - UNUSED(nzcfg); - /* * If NZF file doesn't exist, or NZD DB exists and already * has data, return without attempting migration. */ - if (!isc_file_exists(view->new_zone_file)) { + if (!isc_file_exists(view->newzone.file)) { result = ISC_R_SUCCESS; goto cleanup; } @@ -12618,19 +12688,19 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { ISC_LOG_INFO, "Migrating zones from NZF file '%s' to " "NZD database '%s'", - view->new_zone_file, view->new_zone_db); + view->newzone.file, view->newzone.db); /* * Instead of blindly copying lines, we parse the NZF file using * the configuration parser, because it validates it against the * config type, giving us a guarantee that valid configuration * will be written to DB. */ - result = cfg_parse_file(nzcfg->mctx, view->new_zone_file, + result = cfg_parse_file(isc_g_mctx, view->newzone.file, &cfg_type_addzoneconf, 0, &nzf_config); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "Error parsing NZF file '%s': %s", - view->new_zone_file, isc_result_totext(result)); + view->newzone.file, isc_result_totext(result)); goto cleanup; } @@ -12715,10 +12785,10 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) { * if an NZD database is found for the view. But we rename NZF file * to a backup name here. */ - strlcpy(tempname, view->new_zone_file, sizeof(tempname)); + strlcpy(tempname, view->newzone.file, sizeof(tempname)); if (strlen(tempname) < sizeof(tempname) - 1) { strlcat(tempname, "~", sizeof(tempname)); - isc_file_rename(view->new_zone_file, tempname); + isc_file_rename(view->newzone.file, tempname); } cleanup: @@ -12876,7 +12946,7 @@ delete_zoneconf(dns_view_t *view, const cfg_obj_t *config, REQUIRE(config != NULL); REQUIRE(zname != NULL); - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); cfg_map_get(config, "zone", &zl); @@ -12906,19 +12976,19 @@ delete_zoneconf(dns_view_t *view, const cfg_obj_t *config, /* * Write config to NZF file if appropriate */ - if (nzfwriter != NULL && view->new_zone_file != NULL) { + if (nzfwriter != NULL && view->newzone.file != NULL) { result = nzfwriter(config, view); } cleanup: - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); return result; } static isc_result_t -do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, - dns_name_t *name, cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, - bool redirect, isc_buffer_t **text) { +do_addzone(named_server_t *server, dns_view_t *view, dns_name_t *name, + cfg_obj_t *zoneconf, const cfg_obj_t *zoneobj, bool redirect, + isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; const cfg_obj_t *voptions = NULL; @@ -12933,6 +13003,12 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, UNUSED(zoneconf); #endif + if (!view->newzone.allowed) { + result = ISC_R_NOPERM; + TCHECK(putstr(text, "new zone configuration is not allowed")); + goto cleanup; + } + /* Zone shouldn't already exist */ if (redirect) { result = (view->redirect == NULL) ? ISC_R_NOTFOUND @@ -12953,11 +13029,11 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, /* * Make sure we can open the configuration save file */ - result = isc_stdio_open(view->new_zone_file, "a", &fp); + result = isc_stdio_open(view->newzone.file, "a", &fp); if (result != ISC_R_SUCCESS) { isc_loopmgr_resume(); TCHECK(putstr(text, "unable to create '")); - TCHECK(putstr(text, view->new_zone_file)); + TCHECK(putstr(text, view->newzone.file)); TCHECK(putstr(text, "': ")); TCHECK(putstr(text, isc_result_totext(result))); goto cleanup; @@ -12966,14 +13042,14 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, (void)isc_stdio_close(fp); fp = NULL; #else /* HAVE_LMDB */ - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); locked = true; /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { isc_loopmgr_resume(); TCHECK(putstr(text, "unable to open NZD database for '")); - TCHECK(putstr(text, view->new_zone_db)); + TCHECK(putstr(text, view->newzone.db)); TCHECK(putstr(text, "'")); result = ISC_R_FAILURE; goto cleanup; @@ -12981,13 +13057,13 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #endif /* HAVE_LMDB */ /* Check zone syntax */ - if (cfg->vconfig != NULL) { - voptions = cfg_tuple_get(cfg->vconfig, "options"); + if (view->newzone.vconfig != NULL) { + voptions = cfg_tuple_get(view->newzone.vconfig, "options"); } - result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL, - NULL, NULL, NULL, view->name, - view->rdclass, BIND_CHECK_PLUGINS, - cfg->aclctx, cfg->mctx); + result = isccfg_check_zoneconf( + zoneobj, voptions, server->effectiveconfig, NULL, NULL, NULL, + NULL, view->name, view->rdclass, BIND_CHECK_PLUGINS, + server->aclctx, isc_g_mctx); if (result != ISC_R_SUCCESS) { isc_loopmgr_resume(); goto cleanup; @@ -12995,9 +13071,10 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, /* Mark view unfrozen and configure zone */ dns_view_thaw(view); - result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, - &server->viewlist, &server->kasplist, - cfg->aclctx, true, false, false, false); + result = configure_zone(server->effectiveconfig, zoneobj, + view->newzone.vconfig, view, &server->viewlist, + &server->kasplist, server->aclctx, true, false, + false, false); dns_view_freeze(view); isc_loopmgr_resume(); @@ -13031,11 +13108,11 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, * we've created. If there was a previous one, merge the new * zone into it. */ - if (cfg->nzf_config == NULL) { - cfg_obj_attach(zoneconf, &cfg->nzf_config); + if (view->newzone.nzconfig == NULL) { + cfg_obj_attach(zoneconf, &view->newzone.nzconfig); } else { cfg_obj_t *z = UNCONST(zoneobj); - CHECK(cfg_map_add(cfg->nzf_config, z, "zone")); + CHECK(cfg_map_add(view->newzone.nzconfig, z, "zone")); } cleanup_config = true; #endif /* HAVE_LMDB */ @@ -13084,7 +13161,8 @@ cleanup: (void)isc_stdio_close(fp); } if (result != ISC_R_SUCCESS && cleanup_config) { - tresult = delete_zoneconf(view, cfg->nzf_config, name, NULL); + tresult = delete_zoneconf(view, view->newzone.nzconfig, name, + NULL); RUNTIME_CHECK(tresult == ISC_R_SUCCESS); } #else /* HAVE_LMDB */ @@ -13092,7 +13170,7 @@ cleanup: (void)nzd_close(&txn, false); } if (locked) { - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); } #endif /* HAVE_LMDB */ @@ -13104,9 +13182,9 @@ cleanup: } static isc_result_t -do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, - dns_name_t *name, const char *zname, const cfg_obj_t *zoneobj, - bool redirect, isc_buffer_t **text) { +do_modzone(named_server_t *server, dns_view_t *view, dns_name_t *name, + const char *zname, const cfg_obj_t *zoneobj, bool redirect, + isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL; const cfg_obj_t *voptions = NULL; @@ -13120,6 +13198,12 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, bool locked = false; #endif /* HAVE_LMDB */ + if (!view->newzone.allowed) { + result = ISC_R_NOPERM; + TCHECK(putstr(text, "new zone configuration is not allowed")); + goto cleanup; + } + /* Zone must already exist */ if (redirect) { if (view->redirect != NULL) { @@ -13138,22 +13222,14 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, added = dns_zone_getadded(zone); dns_zone_detach(&zone); -#ifndef HAVE_LMDB - cfg = (ns_cfgctx_t *)view->new_zone_config; - if (cfg == NULL) { - TCHECK(putstr(text, "new zone config is not set")); - CHECK(ISC_R_FAILURE); - } -#endif /* ifndef HAVE_LMDB */ - isc_loopmgr_pause(); #ifndef HAVE_LMDB /* Make sure we can open the configuration save file */ - result = isc_stdio_open(view->new_zone_file, "a", &fp); + result = isc_stdio_open(view->newzone.file, "a", &fp); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open '")); - TCHECK(putstr(text, view->new_zone_file)); + TCHECK(putstr(text, view->newzone.file)); TCHECK(putstr(text, "': ")); TCHECK(putstr(text, isc_result_totext(result))); isc_loopmgr_resume(); @@ -13162,13 +13238,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, (void)isc_stdio_close(fp); fp = NULL; #else /* HAVE_LMDB */ - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); locked = true; /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "unable to open NZD database for '")); - TCHECK(putstr(text, view->new_zone_db)); + TCHECK(putstr(text, view->newzone.db)); TCHECK(putstr(text, "'")); result = ISC_R_FAILURE; isc_loopmgr_resume(); @@ -13177,13 +13253,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #endif /* HAVE_LMDB */ /* Check zone syntax */ - if (cfg->vconfig != NULL) { - voptions = cfg_tuple_get(cfg->vconfig, "options"); + if (view->newzone.vconfig != NULL) { + voptions = cfg_tuple_get(view->newzone.vconfig, "options"); } - result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL, - NULL, NULL, NULL, view->name, - view->rdclass, BIND_CHECK_PLUGINS, - cfg->aclctx, cfg->mctx); + result = isccfg_check_zoneconf( + zoneobj, voptions, server->effectiveconfig, NULL, NULL, NULL, + NULL, view->name, view->rdclass, BIND_CHECK_PLUGINS, + server->aclctx, isc_g_mctx); if (result != ISC_R_SUCCESS) { isc_loopmgr_resume(); goto cleanup; @@ -13191,9 +13267,10 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, /* Reconfigure the zone */ dns_view_thaw(view); - result = configure_zone(cfg->config, zoneobj, cfg->vconfig, view, - &server->viewlist, &server->kasplist, - cfg->aclctx, true, false, false, true); + result = configure_zone(server->effectiveconfig, zoneobj, + view->newzone.vconfig, view, &server->viewlist, + &server->kasplist, server->aclctx, true, false, + false, true); dns_view_freeze(view); isc_loopmgr_resume(); @@ -13217,7 +13294,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB /* Remove old zone from configuration (and NZF file if applicable) */ if (added) { - result = delete_zoneconf(view, cfg->nzf_config, + result = delete_zoneconf(view, view->newzone.nzconfig, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { @@ -13230,12 +13307,13 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #endif /* HAVE_LMDB */ if (!added) { - if (cfg->vconfig == NULL) { - result = delete_zoneconf(view, cfg->config, + if (view->newzone.vconfig == NULL) { + result = delete_zoneconf(view, server->effectiveconfig, dns_zone_getorigin(zone), NULL); } else { - voptions = cfg_tuple_get(cfg->vconfig, "options"); + voptions = cfg_tuple_get(server->effectiveconfig, + "options"); result = delete_zoneconf( view, voptions, dns_zone_getorigin(zone), NULL); } @@ -13286,7 +13364,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB /* Store the new zone configuration; also in NZF if applicable */ z = UNCONST(zoneobj); - CHECK(cfg_map_add(cfg->nzf_config, z, "zone")); + CHECK(cfg_map_add(view->newzone.nzconfig, z, "zone")); #endif /* HAVE_LMDB */ if (added) { @@ -13322,7 +13400,7 @@ cleanup: (void)nzd_close(&txn, false); } if (locked) { - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); } #endif /* HAVE_LMDB */ @@ -13342,7 +13420,6 @@ named_server_changezone(named_server_t *server, char *command, isc_result_t result; bool addzone; bool redirect = false; - ns_cfgctx_t *cfg = NULL; cfg_obj_t *zoneconf = NULL; const cfg_obj_t *zoneobj = NULL; const char *zonename; @@ -13365,9 +13442,9 @@ named_server_changezone(named_server_t *server, char *command, /* Are we accepting new zones in this view? */ #ifdef HAVE_LMDB - if (view->new_zone_db == NULL) + if (view->newzone.db == NULL) #else /* ifdef HAVE_LMDB */ - if (view->new_zone_file == NULL) + if (view->newzone.file == NULL) #endif /* HAVE_LMDB */ { (void)putstr(text, "Not allowing new zones in view '"); @@ -13376,11 +13453,6 @@ named_server_changezone(named_server_t *server, char *command, CHECK(ISC_R_NOPERM); } - cfg = (ns_cfgctx_t *)view->new_zone_config; - if (cfg == NULL) { - CHECK(ISC_R_FAILURE); - } - zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name")); isc_buffer_constinit(&buf, zonename, strlen(zonename)); isc_buffer_add(&buf, strlen(zonename)); @@ -13397,10 +13469,10 @@ named_server_changezone(named_server_t *server, char *command, } if (addzone) { - CHECK(do_addzone(server, cfg, view, dnsname, zoneconf, zoneobj, + CHECK(do_addzone(server, view, dnsname, zoneconf, zoneobj, redirect, text)); } else { - CHECK(do_modzone(server, cfg, view, dnsname, zonename, zoneobj, + CHECK(do_modzone(server, view, dnsname, zonename, zoneobj, redirect, text)); } @@ -13444,6 +13516,7 @@ inuse(const char *file, bool first, isc_buffer_t **text) { typedef struct { dns_zone_t *zone; + named_server_t *server; bool cleanup; } ns_dzctx_t; @@ -13457,7 +13530,6 @@ rmzone(void *arg) { dns_catz_zone_t *catz = NULL; char zonename[DNS_NAME_FORMATSIZE]; dns_view_t *view = NULL; - ns_cfgctx_t *cfg = NULL; dns_db_t *dbp = NULL; bool added; isc_result_t result; @@ -13471,7 +13543,6 @@ rmzone(void *arg) { /* Dig out configuration for this zone */ zone = dz->zone; view = dns_zone_getview(zone); - cfg = (ns_cfgctx_t *)view->new_zone_config; dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename)); isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, @@ -13485,16 +13556,16 @@ rmzone(void *arg) { added = dns_zone_getadded(zone); catz = dns_zone_get_parentcatz(zone); - if (added && catz == NULL && cfg != NULL) { + if (added && catz == NULL) { #ifdef HAVE_LMDB /* Make sure we can open the NZD database */ - LOCK(&view->new_zone_lock); + LOCK(&view->newzone.lock); result = nzd_open(view, 0, &txn, &dbi); if (result != ISC_R_SUCCESS) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, "unable to open NZD database for '%s'", - view->new_zone_db); + view->newzone.db); } else { result = nzd_save(&txn, dbi, zone, NULL); } @@ -13509,9 +13580,9 @@ rmzone(void *arg) { if (txn != NULL) { (void)nzd_close(&txn, false); } - UNLOCK(&view->new_zone_lock); + UNLOCK(&view->newzone.lock); #else /* ifdef HAVE_LMDB */ - result = delete_zoneconf(view, cfg->nzf_config, + result = delete_zoneconf(view, view->newzone.nzconfig, dns_zone_getorigin(zone), nzf_writeconf); if (result != ISC_R_SUCCESS) { @@ -13523,16 +13594,16 @@ rmzone(void *arg) { #endif /* HAVE_LMDB */ } - if (!added && cfg != NULL) { - if (cfg->vconfig != NULL) { - const cfg_obj_t *voptions = cfg_tuple_get(cfg->vconfig, - "options"); + if (!added) { + if (view->newzone.vconfig != NULL) { + const cfg_obj_t *voptions = + cfg_tuple_get(view->newzone.vconfig, "options"); result = delete_zoneconf( view, voptions, dns_zone_getorigin(zone), NULL); } else { - result = delete_zoneconf(view, cfg->config, - dns_zone_getorigin(zone), - NULL); + result = delete_zoneconf( + view, dz->server->effectiveconfig, + dns_zone_getorigin(zone), NULL); } if (result != ISC_R_SUCCESS) { @@ -13659,6 +13730,12 @@ named_server_delzone(named_server_t *server, isc_lex_t *lex, } view = dns_zone_getview(zone); + + if (!view->newzone.allowed) { + TCHECK(putstr(text, "new zone configuration is not allowed")); + CHECK(ISC_R_NOPERM); + } + if (dns_zone_gettype(zone) == dns_zone_redirect) { dns_zone_detach(&view->redirect); } else { @@ -13669,6 +13746,7 @@ named_server_delzone(named_server_t *server, isc_lex_t *lex, dz = isc_mem_get(isc_g_mctx, sizeof(*dz)); *dz = (ns_dzctx_t){ .cleanup = cleanup, + .server = server, }; dns_zone_attach(zone, &dz->zone); isc_async_run(dns_zone_getloop(zone), rmzone, dz); @@ -13740,7 +13818,7 @@ cleanup: } static void -emitzone(void *arg, const char *buf, int len) { +emit_text(void *arg, const char *buf, int len) { ns_dzarg_t *dzarg = arg; isc_result_t result; @@ -13783,7 +13861,7 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex, dzarg.magic = DZARG_MAGIC; dzarg.text = text; dzarg.result = ISC_R_SUCCESS; - cfg_printx(zconfig, CFG_PRINTER_ONELINE, emitzone, &dzarg); + cfg_printx(zconfig, CFG_PRINTER_ONELINE, emit_text, &dzarg); CHECK(dzarg.result); CHECK(putstr(text, ";")); @@ -13798,30 +13876,52 @@ cleanup: return result; } -static void -newzone_cfgctx_destroy(void **cfgp) { - ns_cfgctx_t *cfg; +isc_result_t +named_server_showconf(named_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { + isc_result_t result, tresult; + const char *arg = NULL; + const cfg_obj_t *config = NULL; + ns_dzarg_t dzarg = { + .magic = DZARG_MAGIC, + .result = ISC_R_SUCCESS, + .text = text, + }; - REQUIRE(cfgp != NULL && *cfgp != NULL); + REQUIRE(text != NULL && *text != NULL); - cfg = *cfgp; + /* Skip the command name */ + (void)next_token(lex, text); - if (cfg->config != NULL) { - cfg_obj_detach(&cfg->config); + arg = next_token(lex, text); + if (arg == NULL) { + return ISC_R_UNEXPECTEDEND; } - if (cfg->vconfig != NULL) { - cfg_obj_detach(&cfg->vconfig); - } - if (cfg->nzf_config != NULL) { - cfg_obj_detach(&cfg->nzf_config); + if (strcasecmp(arg, "-user") == 0) { + config = server->userconfig; + } else if (strcasecmp(arg, "-builtin") == 0) { + config = named_g_defaultconfig; + } else if (strcasecmp(arg, "-effective") == 0) { + config = server->effectiveconfig; + } else { + CHECK(DNS_R_SYNTAX); } - if (cfg->aclctx != NULL) { - cfg_aclconfctx_detach(&cfg->aclctx); + if (config == NULL) { + result = ISC_R_NOTFOUND; + TCHECK(putstr(text, "configuration data not found.\n")); + goto cleanup; } - isc_mem_putanddetach(&cfg->mctx, cfg, sizeof(*cfg)); - *cfgp = NULL; + cfg_printx(config, 0, emit_text, &dzarg); + result = dzarg.result; + +cleanup: + if (isc_buffer_usedlength(*text) > 0) { + (void)putnull(text); + } + + return result; } isc_result_t diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst index aaaf33e426..53804fef57 100644 --- a/bin/rndc/rndc.rst +++ b/bin/rndc/rndc.rst @@ -545,6 +545,28 @@ Currently supported commands are: answers is currently enabled or disabled. It also reports the values of ``stale-answer-ttl`` and ``max-stale-ttl``. +.. option:: showconf ( -user | -builtin | -effective ) + + This command prints the current running configuration for the server. + There are three modes: + + - ``rndc showconf -user`` prints the contents of :iscman:`named.conf`, + as of the time the server was most recently configured. + - ``rndc showconf -builtin`` prints the built-in default configuration + settings (which may be overridden by :iscman:`named.conf`). + - ``rndc showconf -effective`` prints the effective configuration + of the server. This is the merged combination of the ``-user`` and + ``-builtin`` configurations. + + Note that this information is only set or updated when the server is + loaded or reconfigured. Properties that can be dynamically changed + during runtime, such as the active root trust anchors, the debugging + level (via ``rndc trace``), or DNSSEC validation (via ``rndc + valiation``), are shown as configured, not as currently set, and zones that + are dynamically added using ``rndc addzone`` are not visible. + + See also :option:`rndc showzone`. + .. option:: showzone zone [class [view]] This command prints the configuration of a running zone. diff --git a/bin/tests/system/showconf/ns1/example.db b/bin/tests/system/showconf/ns1/example.db new file mode 100644 index 0000000000..1d7173fea3 --- /dev/null +++ b/bin/tests/system/showconf/ns1/example.db @@ -0,0 +1,21 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.unsigned. hostmaster.ns.unsigned. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + +a A 1.1.1.1 +mx A 2.2.2.2 diff --git a/bin/tests/system/showconf/ns1/named.conf.j2 b/bin/tests/system/showconf/ns1/named.conf.j2 new file mode 100644 index 0000000000..ad42e4bc25 --- /dev/null +++ b/bin/tests/system/showconf/ns1/named.conf.j2 @@ -0,0 +1,39 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + recursion no; + dnssec-validation no; + notify yes; + minimal-responses no; + allow-new-zones yes; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "example.com" { + type primary; + file "example.db"; +}; diff --git a/bin/tests/system/showconf/tests_showconf.py b/bin/tests/system/showconf/tests_showconf.py new file mode 100644 index 0000000000..ae7e3833cc --- /dev/null +++ b/bin/tests/system/showconf/tests_showconf.py @@ -0,0 +1,62 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import dns +import isctest + + +def test_showconf(ns1): + # Basic testing of rndc showconf + msg = isctest.query.create("a.example.com", "A") + res = isctest.query.udp(msg, "10.53.0.1") + isctest.check.rcode(res, dns.rcode.NOERROR) + + effectiveconfig = ns1.rndc("showconf -effective", log=False) + assert 'zone "example.com"' in effectiveconfig + assert 'view "_bind" chaos {' in effectiveconfig + + # builtin-trust-anchors is non documented and internal clause only, it must + # not be visible. + assert "builtin-trust-anchors" not in effectiveconfig + + # Dynamically added zones are not visible from the effectiveconfig + zonedata = '"added.example" { type primary; file "example.db"; };' + ns1.rndc(f"addzone {zonedata}", log=False) + + msg = isctest.query.create("a.added.example", "A") + res = isctest.query.udp(msg, "10.53.0.1") + isctest.check.rcode(res, dns.rcode.NOERROR) + + effectiveconfig = ns1.rndc("showconf -effective", log=False) + assert 'zone "added.example"' not in effectiveconfig + + userconfig = ns1.rndc("showconf -user", log=False) + assert 'zone "example.com"' in userconfig + assert 'view "_bind" chaos {' not in userconfig + + builtinconfig = ns1.rndc("showconf -builtin", log=False) + assert len(userconfig.split()) < len(builtinconfig.split()) + assert len(builtinconfig.split()) < len(effectiveconfig.split()) + + # Errors handling + error_msg = "" + + try: + ns1.rndc("showconf -idontexist", log=False) + except isctest.rndc.RNDCException as e: + error_msg = str(e) + assert error_msg == "rndc: 'showconf' failed: syntax error\n" + + try: + ns1.rndc("showconf", log=False) + except isctest.rndc.RNDCException as e: + error_msg = str(e) + assert error_msg == "rndc: 'showconf' failed: unexpected end of input\n" diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index d536cccbd3..1c3bbdb06e 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -77,6 +77,13 @@ #include #include +/* + * These are opaque types that will be used by named to save + * newzones configuration in the view. + */ +typedef struct cfg_obj cfg_obj_t; +typedef struct MDB_env MDB_env; + struct dns_view { /* Unlocked. */ unsigned int magic; @@ -203,28 +210,26 @@ struct dns_view { ISC_LINK(struct dns_view) link; dns_viewlist_t *viewlist; - dns_zone_t *managed_keys; - dns_zone_t *redirect; - dns_name_t *redirectzone; /* points to - * redirectfixed - * when valid */ + dns_zone_t *managed_keys; + dns_zone_t *redirect; + dns_name_t *redirectzone; /* points to redirectfixed when valid */ dns_fixedname_t redirectfixed; /* - * File and configuration data for zones added at runtime - * (only used in BIND9). - * - * XXX: This should be a pointer to an opaque type that - * named implements. + * File and configuration data for zones added at runtime. */ - char *new_zone_dir; - char *new_zone_file; - char *new_zone_db; - void *new_zone_dbenv; - uint64_t new_zone_mapsize; - void *new_zone_config; - void (*cfg_destroy)(void **); - isc_mutex_t new_zone_lock; + struct { + bool allowed; + char *dir; + char *file; + char *db; + MDB_env *dbenv; + uint64_t mapsize; + cfg_obj_t *vconfig; + cfg_obj_t *nzconfig; + void (*cleanup)(dns_view_t *); + isc_mutex_t lock; + } newzone; unsigned char secret[32]; /* Client secret */ unsigned int v6bias; @@ -1047,44 +1052,6 @@ dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname, * \li 'dnskey' is valid. */ -isc_result_t -dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx, - void (*cfg_destroy)(void **), uint64_t mapsize); -/*%< - * Set whether or not to allow zones to be created or deleted at runtime. - * - * If 'allow' is true, determines the filename into which new zone - * configuration will be written. Preserves the configuration context - * (a pointer to which is passed in 'cfgctx') for use when parsing new - * zone configuration. 'cfg_destroy' points to a callback routine to - * destroy the configuration context when the view is destroyed. (This - * roundabout method is used in order to avoid libdns having a dependency - * on libisccfg and libbind9.) - * - * If 'allow' is false, removes any existing references to - * configuration context and frees any memory. - * - * Requires: - * \li 'view' is valid. - * - * Returns: - * \li ISC_R_SUCCESS - * \li ISC_R_NOSPACE - */ - -void -dns_view_setnewzonedir(dns_view_t *view, const char *dir); -const char * -dns_view_getnewzonedir(dns_view_t *view); -/*%< - * Set/get the path to the directory in which NZF or NZD files should - * be stored. If the path was previously set to a non-NULL value, - * the previous value is freed. - * - * Requires: - * \li 'view' is valid. - */ - void dns_view_restorekeyring(dns_view_t *view); diff --git a/lib/dns/view.c b/lib/dns/view.c index 164b54becb..7efc9234a2 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -160,7 +160,7 @@ dns_view_create(isc_mem_t *mctx, dns_dispatchmgr_t *dispatchmgr, view->mctx, UNREACH_HOLD_TIME_INITIAL_SEC, UNREACH_HOLD_TIME_MAX_SEC, UNREACH_BACKOFF_ELIGIBLE_SEC); - isc_mutex_init(&view->new_zone_lock); + isc_mutex_init(&view->newzone.lock); dns_order_create(view->mctx, &view->order); @@ -345,20 +345,16 @@ destroy(dns_view_t *view) { dns_dt_detach(&view->dtenv); } #endif /* HAVE_DNSTAP */ - dns_view_setnewzones(view, false, NULL, NULL, 0ULL); - if (view->new_zone_file != NULL) { - isc_mem_free(view->mctx, view->new_zone_file); - } - if (view->new_zone_dir != NULL) { - isc_mem_free(view->mctx, view->new_zone_dir); + if (view->newzone.cleanup != NULL) { + view->newzone.cleanup(view); } #ifdef HAVE_LMDB - if (view->new_zone_dbenv != NULL) { - mdb_env_close((MDB_env *)view->new_zone_dbenv); - view->new_zone_dbenv = NULL; + if (view->newzone.dbenv != NULL) { + mdb_env_close((MDB_env *)view->newzone.dbenv); + view->newzone.dbenv = NULL; } - if (view->new_zone_db != NULL) { - isc_mem_free(view->mctx, view->new_zone_db); + if (view->newzone.db != NULL) { + isc_mem_free(view->mctx, view->newzone.db); } #endif /* HAVE_LMDB */ dns_fwdtable_destroy(&view->fwdtable); @@ -369,7 +365,7 @@ destroy(dns_view_t *view) { if (view->unreachcache != NULL) { dns_unreachcache_destroy(&view->unreachcache); } - isc_mutex_destroy(&view->new_zone_lock); + isc_mutex_destroy(&view->newzone.lock); isc_mutex_destroy(&view->lock); isc_refcount_destroy(&view->references); isc_refcount_destroy(&view->weakrefs); @@ -1680,185 +1676,6 @@ finish: return answer; } -/* - * Create path to a directory and a filename constructed from viewname. - * This is a front-end to isc_file_sanitize(), allowing backward - * compatibility to older versions when a file couldn't be expected - * to be in the specified directory but might be in the current working - * directory instead. - * - * It first tests for the existence of a file . in - * 'directory'. If the file does not exist, it checks again in the - * current working directory. If it does not exist there either, - * return the path inside the directory. - * - * Returns ISC_R_SUCCESS if a path to an existing file is found or - * a new path is created; returns ISC_R_NOSPACE if the path won't - * fit in 'buflen'. - */ - -static isc_result_t -nz_legacy(const char *directory, const char *viewname, const char *suffix, - char *buffer, size_t buflen) { - isc_result_t result; - char newbuf[PATH_MAX]; - - result = isc_file_sanitize(directory, viewname, suffix, buffer, buflen); - if (result != ISC_R_SUCCESS) { - return result; - } else if (directory == NULL || isc_file_exists(buffer)) { - return ISC_R_SUCCESS; - } else { - /* Save buffer */ - strlcpy(newbuf, buffer, sizeof(newbuf)); - } - - /* - * It isn't in the specified directory; check CWD. - */ - result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen); - if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) { - return result; - } - - /* - * File does not exist in either 'directory' or CWD, - * so use the path in 'directory'. - */ - strlcpy(buffer, newbuf, buflen); - return ISC_R_SUCCESS; -} - -isc_result_t -dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx, - void (*cfg_destroy)(void **), uint64_t mapsize) { - isc_result_t result = ISC_R_SUCCESS; - char buffer[1024]; -#ifdef HAVE_LMDB - MDB_env *env = NULL; - int status; -#endif /* ifdef HAVE_LMDB */ - -#ifndef HAVE_LMDB - UNUSED(mapsize); -#endif /* ifndef HAVE_LMDB */ - - REQUIRE(DNS_VIEW_VALID(view)); - REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow); - - if (view->new_zone_file != NULL) { - isc_mem_free(view->mctx, view->new_zone_file); - } - -#ifdef HAVE_LMDB - if (view->new_zone_dbenv != NULL) { - mdb_env_close((MDB_env *)view->new_zone_dbenv); - view->new_zone_dbenv = NULL; - } - - if (view->new_zone_db != NULL) { - isc_mem_free(view->mctx, view->new_zone_db); - } -#endif /* HAVE_LMDB */ - - if (view->new_zone_config != NULL) { - view->cfg_destroy(&view->new_zone_config); - view->cfg_destroy = NULL; - } - - if (!allow) { - return ISC_R_SUCCESS; - } - - CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf", buffer, - sizeof(buffer))); - - view->new_zone_file = isc_mem_strdup(view->mctx, buffer); - -#ifdef HAVE_LMDB - CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd", buffer, - sizeof(buffer))); - - view->new_zone_db = isc_mem_strdup(view->mctx, buffer); - - status = mdb_env_create(&env); - if (status != MDB_SUCCESS) { - isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, - ISC_LOG_ERROR, "mdb_env_create failed: %s", - mdb_strerror(status)); - CHECK(ISC_R_FAILURE); - } - - if (mapsize != 0ULL) { - status = mdb_env_set_mapsize(env, mapsize); - if (status != MDB_SUCCESS) { - isc_log_write(DNS_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_OTHER, ISC_LOG_ERROR, - "mdb_env_set_mapsize failed: %s", - mdb_strerror(status)); - CHECK(ISC_R_FAILURE); - } - view->new_zone_mapsize = mapsize; - } - - status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600); - if (status != MDB_SUCCESS) { - isc_log_write(DNS_LOGCATEGORY_GENERAL, ISC_LOGMODULE_OTHER, - ISC_LOG_ERROR, "mdb_env_open of '%s' failed: %s", - view->new_zone_db, mdb_strerror(status)); - CHECK(ISC_R_FAILURE); - } - - view->new_zone_dbenv = env; - env = NULL; -#endif /* HAVE_LMDB */ - - view->new_zone_config = cfgctx; - view->cfg_destroy = cfg_destroy; - -cleanup: - if (result != ISC_R_SUCCESS) { - if (view->new_zone_file != NULL) { - isc_mem_free(view->mctx, view->new_zone_file); - } - -#ifdef HAVE_LMDB - if (view->new_zone_db != NULL) { - isc_mem_free(view->mctx, view->new_zone_db); - } - if (env != NULL) { - mdb_env_close(env); - } -#endif /* HAVE_LMDB */ - view->new_zone_config = NULL; - view->cfg_destroy = NULL; - } - - return result; -} - -void -dns_view_setnewzonedir(dns_view_t *view, const char *dir) { - REQUIRE(DNS_VIEW_VALID(view)); - - if (view->new_zone_dir != NULL) { - isc_mem_free(view->mctx, view->new_zone_dir); - } - - if (dir == NULL) { - return; - } - - view->new_zone_dir = isc_mem_strdup(view->mctx, dir); -} - -const char * -dns_view_getnewzonedir(dns_view_t *view) { - REQUIRE(DNS_VIEW_VALID(view)); - - return view->new_zone_dir; -} - isc_result_t dns_view_searchdlz(dns_view_t *view, const dns_name_t *name, unsigned int minlabels, dns_clientinfomethods_t *methods, diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c index 2e386a1ffd..8076c82971 100644 --- a/lib/isccfg/aclconf.c +++ b/lib/isccfg/aclconf.c @@ -58,33 +58,18 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **aclctxp) { return ISC_R_SUCCESS; } -void -cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest) { - REQUIRE(src != NULL); - REQUIRE(dest != NULL && *dest == NULL); - - isc_refcount_increment(&src->references); - *dest = src; -} - -void -cfg_aclconfctx_detach(cfg_aclconfctx_t **aclctxp) { - REQUIRE(aclctxp != NULL && *aclctxp != NULL); - - cfg_aclconfctx_t *aclctx = *aclctxp; - *aclctxp = NULL; - - if (isc_refcount_decrement(&aclctx->references) == 1) { - isc_refcount_destroy(&aclctx->references); - ISC_LIST_FOREACH(aclctx->named_acl_cache, dacl, nextincache) { - ISC_LIST_UNLINK(aclctx->named_acl_cache, dacl, - nextincache); - dns_acl_detach(&dacl); - } - isc_mem_putanddetach(&aclctx->mctx, aclctx, sizeof(*aclctx)); +static void +destroy_aclctx(cfg_aclconfctx_t *aclctx) { + isc_refcount_destroy(&aclctx->references); + ISC_LIST_FOREACH(aclctx->named_acl_cache, dacl, nextincache) { + ISC_LIST_UNLINK(aclctx->named_acl_cache, dacl, nextincache); + dns_acl_detach(&dacl); } + isc_mem_putanddetach(&aclctx->mctx, aclctx, sizeof(*aclctx)); } +ISC_REFCOUNT_IMPL(cfg_aclconfctx, destroy_aclctx); + /* * Find the definition of the named acl whose name is "name". */ diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h index 9ad8253bd1..6ce2a5b761 100644 --- a/lib/isccfg/include/isccfg/aclconf.h +++ b/lib/isccfg/include/isccfg/aclconf.h @@ -39,19 +39,6 @@ cfg_aclconfctx_create(isc_mem_t *mctx, cfg_aclconfctx_t **aclctxp); * Creates and initializes an ACL configuration context. */ -void -cfg_aclconfctx_detach(cfg_aclconfctx_t **aclctxp); -/* - * Removes a reference to an ACL configuration context; when references - * reaches zero, clears the contents and deallocate the structure. - */ - -void -cfg_aclconfctx_attach(cfg_aclconfctx_t *src, cfg_aclconfctx_t **dest); -/* - * Attaches a pointer to an existing ACL configuration context. - */ - isc_result_t cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx, @@ -72,3 +59,5 @@ cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx, * 'ctx' to be non NULL. * '*target' to be NULL or a valid dns_acl_t. */ + +ISC_REFCOUNT_DECL(cfg_aclconfctx);