add namedconf support for plugin inside a zone

The named.conf parser now accepts the plugin clause inside a zone
definition.  This enables us to add (in later commits) support for
zone plugins.
This commit is contained in:
Colin Vidal 2025-05-26 16:53:31 +02:00
parent 014a05a278
commit 7ea70b4e19
9 changed files with 97 additions and 74 deletions

View file

@ -13200,7 +13200,8 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL,
NULL, NULL, NULL, view->name,
view->rdclass, cfg->actx, cfg->mctx);
view->rdclass, BIND_CHECK_PLUGINS,
cfg->actx, cfg->mctx);
if (result != ISC_R_SUCCESS) {
isc_loopmgr_resume();
goto cleanup;
@ -13397,7 +13398,8 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view,
}
result = isccfg_check_zoneconf(zoneobj, voptions, cfg->config, NULL,
NULL, NULL, NULL, view->name,
view->rdclass, cfg->actx, cfg->mctx);
view->rdclass, BIND_CHECK_PLUGINS,
cfg->actx, cfg->mctx);
if (result != ISC_R_SUCCESS) {
isc_loopmgr_resume();
goto cleanup;

View file

@ -33,6 +33,7 @@ zone <string> [ <class> ] {
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
notify-source-v6 ( <ipv6_address> | * );
plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
provide-zoneversion <boolean>;
request-expire <boolean>;

View file

@ -427,6 +427,7 @@ template <string> {
parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
parental-source ( <ipv4_address> | * );
parental-source-v6 ( <ipv6_address> | * );
plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
provide-zoneversion <boolean>;
request-expire <boolean>;

View file

@ -53,6 +53,7 @@ zone <string> [ <class> ] {
parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
parental-source ( <ipv4_address> | * );
parental-source-v6 ( <ipv6_address> | * );
plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
provide-zoneversion <boolean>;
send-report-channel <string>;
serial-update-method ( date | increment | unixtime );

View file

@ -10,6 +10,7 @@ zone <string> [ <class> ] {
max-records-per-type <integer>;
max-types-per-name <integer>;
max-zone-ttl ( unlimited | <duration> ); // deprecated
plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
template <string>;
zone-statistics ( full | terse | none | <boolean> );

View file

@ -50,6 +50,7 @@ zone <string> [ <class> ] {
parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
parental-source ( <ipv4_address> | * );
parental-source-v6 ( <ipv6_address> | * );
plugin ( query ) <string> [ { <unspecified-text> } ]; // may occur multiple times
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
provide-zoneversion <boolean>;
request-expire <boolean>;

View file

@ -2922,6 +2922,68 @@ check:
return result;
}
/*%
* Data structure used for the 'callback_data' argument to check_one_plugin().
*/
struct check_one_plugin_data {
isc_mem_t *mctx;
cfg_aclconfctx_t *actx;
isc_result_t *check_result;
};
/*%
* A callback for the cfg_pluginlist_foreach() call in check_plugins() below.
* Since the point is to check configuration of all plugins even when
* processing some of them fails, always return ISC_R_SUCCESS and indicate any
* check failures through the 'check_result' variable passed in via the
* 'callback_data' structure.
*/
static isc_result_t
check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
const char *plugin_path, const char *parameters,
void *callback_data) {
struct check_one_plugin_data *data = callback_data;
char full_path[PATH_MAX];
isc_result_t result = ISC_R_SUCCESS;
result = ns_plugin_expandpath(plugin_path, full_path,
sizeof(full_path));
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"%s: plugin check failed: "
"unable to get full plugin path: %s",
plugin_path, isc_result_totext(result));
return result;
}
result = ns_plugin_check(full_path, parameters, config,
cfg_obj_file(obj), cfg_obj_line(obj),
data->mctx, data->actx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR, "%s: plugin check failed: %s",
full_path, isc_result_totext(result));
*data->check_result = result;
}
return ISC_R_SUCCESS;
}
static isc_result_t
check_plugins(const cfg_obj_t *plugins, const cfg_obj_t *config,
cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
isc_result_t result = ISC_R_SUCCESS;
struct check_one_plugin_data check_one_plugin_data = {
.mctx = mctx,
.actx = actx,
.check_result = &result,
};
(void)cfg_pluginlist_foreach(config, plugins, check_one_plugin,
&check_one_plugin_data);
return result;
}
/*
* Try to find a zone option in one of up to four levels of options:
* for example, the zone, template, view, and global option blocks.
@ -2957,8 +3019,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
const cfg_obj_t *config, isc_symtab_t *symtab,
isc_symtab_t *files, isc_symtab_t *keydirs,
isc_symtab_t *inview, const char *viewname,
dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
isc_mem_t *mctx) {
dns_rdataclass_t defclass, unsigned int flags,
cfg_aclconfctx_t *actx, isc_mem_t *mctx) {
const char *znamestr = NULL;
const char *typestr = NULL;
const char *target = NULL;
@ -3926,6 +3988,16 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
}
}
if ((flags & BIND_CHECK_PLUGINS) != 0 && zoptions != NULL) {
const cfg_obj_t *plugins = NULL;
(void)cfg_map_get(zoptions, "plugin", &plugins);
tresult = check_plugins(plugins, config, actx, mctx);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
}
}
return result;
}
@ -5179,52 +5251,6 @@ check_catz(const cfg_obj_t *catz_obj, const char *viewname, isc_mem_t *mctx) {
return result;
}
/*%
* Data structure used for the 'callback_data' argument to check_one_plugin().
*/
struct check_one_plugin_data {
isc_mem_t *mctx;
cfg_aclconfctx_t *actx;
isc_result_t *check_result;
};
/*%
* A callback for the cfg_pluginlist_foreach() call in check_viewconf() below.
* Since the point is to check configuration of all plugins even when
* processing some of them fails, always return ISC_R_SUCCESS and indicate any
* check failures through the 'check_result' variable passed in via the
* 'callback_data' structure.
*/
static isc_result_t
check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
const char *plugin_path, const char *parameters,
void *callback_data) {
struct check_one_plugin_data *data = callback_data;
char full_path[PATH_MAX];
isc_result_t result = ISC_R_SUCCESS;
result = ns_plugin_expandpath(plugin_path, full_path,
sizeof(full_path));
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"%s: plugin check failed: "
"unable to get full plugin path: %s",
plugin_path, isc_result_totext(result));
return result;
}
result = ns_plugin_check(full_path, parameters, config,
cfg_obj_file(obj), cfg_obj_line(obj),
data->mctx, data->actx);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR, "%s: plugin check failed: %s",
full_path, isc_result_totext(result));
*data->check_result = result;
}
return ISC_R_SUCCESS;
}
static isc_result_t
check_dnstap(const cfg_obj_t *voptions, const cfg_obj_t *config) {
#ifdef HAVE_DNSTAP
@ -5276,11 +5302,9 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
const cfg_obj_t *obj = NULL;
const cfg_obj_t *options = NULL;
const cfg_obj_t *opts = NULL;
const cfg_obj_t *plugin_list = NULL;
bool autovalidation = false;
unsigned int dflags = 0;
int i;
bool check_plugins = (flags & BIND_CHECK_PLUGINS) != 0;
bool check_algorithms = (flags & BIND_CHECK_ALGORITHMS) != 0;
/*
@ -5314,9 +5338,9 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
CFG_LIST_FOREACH(zones, element) {
const cfg_obj_t *zone = cfg_listelt_value(element);
tresult = isccfg_check_zoneconf(zone, voptions, config, symtab,
files, keydirs, inview,
viewname, vclass, actx, mctx);
tresult = isccfg_check_zoneconf(
zone, voptions, config, symtab, files, keydirs, inview,
viewname, vclass, flags, actx, mctx);
if (tresult != ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
}
@ -5571,27 +5595,16 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
result = tresult;
}
/*
* Load plugins.
*/
if (check_plugins) {
if ((flags & BIND_CHECK_PLUGINS) != 0) {
const cfg_obj_t *plugins = NULL;
if (voptions != NULL) {
(void)cfg_map_get(voptions, "plugin", &plugin_list);
(void)cfg_map_get(voptions, "plugin", &plugins);
} else {
(void)cfg_map_get(config, "plugin", &plugin_list);
(void)cfg_map_get(config, "plugin", &plugins);
}
}
{
struct check_one_plugin_data check_one_plugin_data = {
.mctx = mctx,
.actx = actx,
.check_result = &tresult,
};
(void)cfg_pluginlist_foreach(config, plugin_list,
check_one_plugin,
&check_one_plugin_data);
tresult = check_plugins(plugins, config, actx, mctx);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
}

View file

@ -73,8 +73,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
const cfg_obj_t *config, isc_symtab_t *symtab,
isc_symtab_t *files, isc_symtab_t *keydirs,
isc_symtab_t *inview, const char *viewname,
dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
isc_mem_t *mctx);
dns_rdataclass_t defclass, unsigned int flags,
cfg_aclconfctx_t *actx, isc_mem_t *mctx);
/*%<
* Check the syntactic validity of a zone statement, either in a
* named.conf file or in an "rndc addzone" or "rndc modzone" command.

View file

@ -2463,6 +2463,9 @@ static cfg_clausedef_t zone_only_clauses[] = {
CFG_ZONE_REDIRECT | CFG_CLAUSEFLAG_NODOC },
{ "parental-agents", &cfg_type_namesockaddrkeylist,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
{ "plugin", &cfg_type_plugin,
CFG_CLAUSEFLAG_MULTI | CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY |
CFG_ZONE_REDIRECT | CFG_ZONE_MIRROR },
{ "primaries", &cfg_type_namesockaddrkeylist,
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB |
CFG_ZONE_REDIRECT },