effective config: specific view cases

User specified views don't override default views. In particular, the
_bind/CH view is still active. However, the order is important: if the
user defines a foo/CH view, it must be able to override _bind/CH by
matching clients first (this is how the view is documented).

The server configuration code is now simpler; it only has to build the
views based on the effective view list, and only creates the _default
view if there are no explicit views created by the user.
This commit is contained in:
Colin Vidal 2025-10-16 16:33:51 +02:00 committed by Evan Hunt
parent a99573d648
commit 27c4f68dcc
2 changed files with 51 additions and 46 deletions

View file

@ -3827,6 +3827,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
maps[i++] = voptions;
cfgmaps[j++] = voptions;
}
if (options != NULL) {
maps[i++] = options;
}
@ -7631,47 +7632,65 @@ static isc_result_t
create_views(cfg_obj_t *config, cfg_aclconfctx_t *aclctx,
dns_viewlist_t *viewlist) {
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *bindview = NULL;
const cfg_obj_t *views = NULL;
bool explicitviews = false;
dns_view_t *view = NULL;
APPLY_CONFIGURATION_SUBROUTINE_LOG;
(void)cfg_map_get(config, "view", &views);
CFG_LIST_FOREACH(views, element) {
cfg_obj_t *vconfig = cfg_listelt_value(element);
dns_view_t *view = NULL;
const char *vname = NULL;
dns_rdataclass_t vclass;
result = create_view(vconfig, viewlist, &view);
if (result != ISC_R_SUCCESS) {
return result;
/*
* Skip the addition of the _bind/CHAOS zone until
* after all the others.
*/
CHECK(get_viewinfo(vconfig, &vname, &vclass));
if (strcmp(vname, "_bind") == 0 &&
vclass == dns_rdataclass_chaos)
{
INSIST(cfg_list_next(element) == NULL);
bindview = vconfig;
continue;
}
CHECK(create_view(vconfig, viewlist, &view));
INSIST(view != NULL);
result = setup_newzones(view, config, vconfig, aclctx);
dns_view_detach(&view);
explicitviews = true;
if (result != ISC_R_SUCCESS) {
return result;
}
dns_view_detach(&view);
}
/*
* If there were no explicit views then we do the default
* view here.
*/
if (views == NULL) {
dns_view_t *view = NULL;
result = create_view(NULL, viewlist, &view);
if (result != ISC_R_SUCCESS) {
return result;
}
if (explicitviews == false) {
CHECK(create_view(NULL, viewlist, &view));
INSIST(view != NULL);
result = setup_newzones(view, config, NULL, aclctx);
CHECK(setup_newzones(view, config, NULL, aclctx));
dns_view_detach(&view);
}
/*
* Finally, add _bind/CHAOS.
*/
INSIST(bindview != NULL);
CHECK(create_view(bindview, viewlist, &view));
INSIST(view != NULL);
cleanup:
if (view != NULL) {
dns_view_detach(&view);
}
return result;
}
@ -7685,6 +7704,7 @@ configure_views(cfg_obj_t *config, const cfg_obj_t *bindkeys,
isc_result_t result = ISC_R_SUCCESS;
const cfg_obj_t *views = NULL;
dns_viewlist_t tmpviewlist;
bool explicitviews = false;
APPLY_CONFIGURATION_SUBROUTINE_LOG;
@ -7711,6 +7731,13 @@ configure_views(cfg_obj_t *config, const cfg_obj_t *bindkeys,
dns_view_detach(&view);
return result;
}
if (!(strcmp(view->name, "_bind") == 0 &&
view->rdclass == dns_rdataclass_chaos))
{
explicitviews = true;
}
dns_view_freeze(view);
dns_view_detach(&view);
}
@ -7719,7 +7746,7 @@ configure_views(cfg_obj_t *config, const cfg_obj_t *bindkeys,
* Make sure we have a default view if and only if there
* were no explicit views.
*/
if (views == NULL) {
if (explicitviews == false) {
dns_view_t *view = NULL;
result = find_view(NULL, viewlist, &view);
if (result != ISC_R_SUCCESS) {
@ -7737,33 +7764,6 @@ configure_views(cfg_obj_t *config, const cfg_obj_t *bindkeys,
dns_view_detach(&view);
}
/*
* Create (or recreate) the built-in views.
*/
views = NULL;
RUNTIME_CHECK(cfg_map_get(named_g_defaultconfig, "view", &views) ==
ISC_R_SUCCESS);
CFG_LIST_FOREACH(views, element) {
cfg_obj_t *vconfig = cfg_listelt_value(element);
dns_view_t *view = NULL;
result = create_view(vconfig, viewlist, &view);
if (result != ISC_R_SUCCESS) {
return result;
}
result = configure_view(view, viewlist, config, vconfig,
cachelist, &server->cachelist, kasplist,
bindkeys, isc_g_mctx, aclctx,
tlsctx_client_cache, false, first_time);
if (result != ISC_R_SUCCESS) {
dns_view_detach(&view);
return result;
}
dns_view_freeze(view);
dns_view_detach(&view);
}
/*
* Commit any dns_zone_setview() calls on all zones in the new
* view.

View file

@ -1196,6 +1196,11 @@ map_merge(cfg_obj_t *effectivemap, const cfg_obj_t *defaultmap) {
}
}
static void
merge_append(cfg_obj_t *effectiveobj, const cfg_obj_t *defaultobj) {
cfg_list_addclone(effectiveobj, defaultobj, false);
}
static void
options_merge_defaultacl(cfg_obj_t *effectiveoptions,
const cfg_obj_t *defaultoptions, const char *aclname,
@ -1363,7 +1368,7 @@ static cfg_clausedef_t namedconf_clauses[] = {
#endif
{ "template", &cfg_type_template, CFG_CLAUSEFLAG_MULTI },
{ "tls", &cfg_type_tlsconf, CFG_CLAUSEFLAG_MULTI },
{ "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
{ "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI, merge_append },
{ NULL, NULL, 0 }
};