add plugin_register param telling the source

The plugin `plugin_register` API has a new parameter `source` indicating
whether the plugin is loaded from a view or a zone.

This extra parameter enables the plugin to fail early during
initialization if a plugin written to be used in a zone exclusively
is loaded at a view level, or vice versa.
This commit is contained in:
Colin Vidal 2025-08-19 14:38:36 +02:00
parent e8156b394e
commit 260bbc24c9
6 changed files with 35 additions and 10 deletions

View file

@ -5417,7 +5417,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
}
if (plugin_list != NULL) {
ns_hook_data_t hookdata = {};
ns_hook_data_t hookdata = { .source = NS_HOOKSOURCE_VIEW };
INSIST(view->hooktable == NULL);
ns_hooktable_create(view->mctx, &hookdata.hooktable);

View file

@ -2125,7 +2125,7 @@ named_zone_loadplugins(dns_zone_t *zone, const cfg_obj_t *config,
}
if (tpluginlist != NULL || zpluginlist != NULL) {
ns_hook_data_t hookdata = {};
ns_hook_data_t hookdata = { .source = NS_HOOKSOURCE_ZONE };
isc_mem_t *zmctx = dns_zone_getmctx(zone);
ns_hooktable_create(zmctx, &hookdata.hooktable);

View file

@ -326,10 +326,13 @@ cleanup:
isc_result_t
plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
unsigned long cfg_line, isc_mem_t *mctx, void *actx,
ns_hooktable_t *hooktable, void **instp) {
ns_hooktable_t *hooktable, ns_hooksource_t source,
void **instp) {
filter_instance_t *inst = NULL;
isc_result_t result = ISC_R_SUCCESS;
UNUSED(source);
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
"registering 'filter-a' "
"module from %s:%lu, %s parameters",

View file

@ -329,10 +329,13 @@ cleanup:
isc_result_t
plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
unsigned long cfg_line, isc_mem_t *mctx, void *actx,
ns_hooktable_t *hooktable, void **instp) {
ns_hooktable_t *hooktable, ns_hooksource_t source,
void **instp) {
filter_instance_t *inst = NULL;
isc_result_t result = ISC_R_SUCCESS;
UNUSED(source);
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
"registering 'filter-aaaa' "
"module from %s:%lu, %s parameters",

View file

@ -239,8 +239,10 @@ ns_plugin_register(const char *modpath, const char *parameters, const void *cfg,
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
"registering plugin '%s'", modpath);
INSIST(hookdata->source != NS_HOOKSOURCE_UNDEFINED);
CHECK(plugin->register_func(parameters, cfg, cfg_file, cfg_line, mctx,
actx, hookdata->hooktable, &plugin->inst));
actx, hookdata->hooktable, hookdata->source,
&plugin->inst));
ISC_LIST_APPEND(*hookdata->plugins, plugin, link);

View file

@ -59,10 +59,11 @@
* contains a function pointer to a hook action and a pointer to data which is
* to be passed to the action function when it is called.
*
* Each view has its own separate hook table, populated by loading plugin
* modules specified in the "plugin" statements in named.conf. There is also a
* special, global hook table (ns__hook_table) that is only used by libns unit
* tests and whose existence can be safely ignored by plugin modules.
* Each view and zone has its own separate hook table, populated by loading
* plugin modules specified in the "plugin" statements in named.conf. (See
* `ZONE-SPECIFIC PLUGINS` section below.) There is also a special, global
* hook table (ns__hook_table) that is only used by libns unit tests and
* whose existence can be safely ignored by plugin modules.
*
* Hook actions are functions which:
*
@ -366,6 +367,14 @@
* looked up. `NS_QUERY_DONE_BEGIN` could be called if an
* authoritative zone has been used, but in some flows (for
* instance, bad cookie handling), it would be skipped.
*
* The `plugin_register` function (defined by each plugin and called
* when the plugin is loaded) has a `ns_hooksource_t source` parameter.
* It indicates whether the plugin has been loaded at the zone level
* (`NS_HOOKSOURCE_ZONE`) or at the view level (`NS_HOOKSOURCE_VIEW`).
* While this can be ignored if it doesn't matter where the plugin is
* loaded, it can also be checked to enforce that the plugin is loaded
* only at the zone or view level.
*/
/*!
@ -476,9 +485,16 @@ typedef struct ns_hook_resume {
* Wrapper struct holding hook/plugins owning data structures used and owned by
* zones and views having registered plugins.
*/
typedef enum {
NS_HOOKSOURCE_UNDEFINED,
NS_HOOKSOURCE_VIEW,
NS_HOOKSOURCE_ZONE
} ns_hooksource_t;
typedef struct ns_hook_data {
ns_hooktable_t *hooktable;
ns_plugins_t *plugins;
ns_hooksource_t source;
} ns_hook_data_t;
/*
@ -497,7 +513,8 @@ typedef struct ns_hook_data {
typedef isc_result_t
ns_plugin_register_t(const char *parameters, const void *cfg, const char *file,
unsigned long line, isc_mem_t *mctx, void *actx,
ns_hooktable_t *hooktable, void **instp);
ns_hooktable_t *hooktable, ns_hooksource_t source,
void **instp);
/*%<
* Called when registering a new plugin.
*