mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 08:09:59 -04:00
chg: dev: provide more context when registering plugins
Add a new type, `ns_pluginregister_ctx_t`, which is passed to `plugin_register()` in place of the `source` parameter. The source value is now just part of the structure, which also holds a pointer to the zone origin if the plugin is loaded at a zone level.
This provides more contextual information, enabling the plugin to make specific configuration decisions based on the name of the zone for which it is loaded.
It's also flexible if more contextual data are needed in the future: add a new field to `ns_pluginregister_ctx_t`, and new plugins can use it without affecting compatibility with existing plugins.
Closes #5533
Merge branch '5533-plugin-register-ctx' into 'main'
See merge request isc-projects/bind9!11019
This commit is contained in:
commit
ac4cf4cce8
10 changed files with 111 additions and 41 deletions
|
|
@ -5421,7 +5421,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
}
|
||||
|
||||
if (plugin_list != NULL) {
|
||||
ns_hook_data_t hookdata = { .source = NS_HOOKSOURCE_VIEW };
|
||||
ns_hook_data_t hookdata = {
|
||||
.pluginregister_ctx = { .source = NS_HOOKSOURCE_VIEW }
|
||||
};
|
||||
|
||||
INSIST(view->hooktable == NULL);
|
||||
ns_hooktable_create(view->mctx, &hookdata.hooktable);
|
||||
|
|
|
|||
|
|
@ -2129,7 +2129,11 @@ named_zone_loadplugins(dns_zone_t *zone, const cfg_obj_t *config,
|
|||
}
|
||||
|
||||
if (tpluginlist != NULL || zpluginlist != NULL) {
|
||||
ns_hook_data_t hookdata = { .source = NS_HOOKSOURCE_ZONE };
|
||||
ns_hook_data_t hookdata = {
|
||||
.pluginregister_ctx = { .source = NS_HOOKSOURCE_ZONE,
|
||||
.origin = dns_zone_getorigin(
|
||||
zone) }
|
||||
};
|
||||
isc_mem_t *zmctx = dns_zone_getmctx(zone);
|
||||
|
||||
ns_hooktable_create(zmctx, &hookdata.hooktable);
|
||||
|
|
|
|||
|
|
@ -324,12 +324,12 @@ 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 *aclctx,
|
||||
ns_hooktable_t *hooktable, ns_hooksource_t source,
|
||||
ns_hooktable_t *hooktable, const ns_pluginregister_ctx_t *ctx,
|
||||
void **instp) {
|
||||
filter_instance_t *inst = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
UNUSED(source);
|
||||
UNUSED(ctx);
|
||||
|
||||
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"registering 'filter-a' "
|
||||
|
|
@ -366,7 +366,7 @@ cleanup:
|
|||
isc_result_t
|
||||
plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
|
||||
unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooksource_t source ISC_ATTR_UNUSED) {
|
||||
const ns_pluginregister_ctx_t *ctx ISC_ATTR_UNUSED) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
cfg_parser_t *parser = NULL;
|
||||
cfg_obj_t *param_obj = NULL;
|
||||
|
|
|
|||
|
|
@ -327,12 +327,12 @@ 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 *aclctx,
|
||||
ns_hooktable_t *hooktable, ns_hooksource_t source,
|
||||
ns_hooktable_t *hooktable, const ns_pluginregister_ctx_t *ctx,
|
||||
void **instp) {
|
||||
filter_instance_t *inst = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
UNUSED(source);
|
||||
UNUSED(ctx);
|
||||
|
||||
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"registering 'filter-aaaa' "
|
||||
|
|
@ -370,7 +370,7 @@ cleanup:
|
|||
isc_result_t
|
||||
plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
|
||||
unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooksource_t source ISC_ATTR_UNUSED) {
|
||||
const ns_pluginregister_ctx_t *ctx ISC_ATTR_UNUSED) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
cfg_parser_t *parser = NULL;
|
||||
cfg_obj_t *param_obj = NULL;
|
||||
|
|
|
|||
|
|
@ -125,14 +125,14 @@ logmsg(const char *fmt, ...) {
|
|||
isc_result_t
|
||||
plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
|
||||
unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooktable_t *hooktable, ns_hooksource_t source,
|
||||
ns_hooktable_t *hooktable, const ns_pluginregister_ctx_t *ctx,
|
||||
void **instp) {
|
||||
async_instance_t *inst = NULL;
|
||||
|
||||
UNUSED(source);
|
||||
UNUSED(parameters);
|
||||
UNUSED(cfg);
|
||||
UNUSED(aclctx);
|
||||
UNUSED(ctx);
|
||||
|
||||
isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, ISC_LOG_INFO,
|
||||
"registering 'test-async' module from %s:%lu", cfg_file,
|
||||
|
|
@ -158,14 +158,14 @@ plugin_register(const char *parameters, const void *cfg, const char *cfg_file,
|
|||
isc_result_t
|
||||
plugin_check(const char *parameters, const void *cfg, const char *cfg_file,
|
||||
unsigned long cfg_line, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooksource_t source) {
|
||||
const ns_pluginregister_ctx_t *ctx) {
|
||||
UNUSED(parameters);
|
||||
UNUSED(cfg);
|
||||
UNUSED(cfg_file);
|
||||
UNUSED(cfg_line);
|
||||
UNUSED(mctx);
|
||||
UNUSED(aclctx);
|
||||
UNUSED(source);
|
||||
UNUSED(ctx);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ syncplugin__parse_rcode(const cfg_obj_t *syncplugincfg, uint8_t *rcode) {
|
|||
isc_result_t
|
||||
plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
|
||||
unsigned long cfgline, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooktable_t *hooktable, ns_hooksource_t source,
|
||||
ns_hooktable_t *hooktable, const ns_pluginregister_ctx_t *ctx,
|
||||
void **instp) {
|
||||
isc_result_t result;
|
||||
cfg_parser_t *parser = NULL;
|
||||
|
|
@ -123,10 +123,13 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
|
|||
ns_hook_t hook;
|
||||
syncplugin_t *inst = NULL;
|
||||
char *sourcestr = NULL;
|
||||
dns_name_t example2com;
|
||||
dns_name_t example3com;
|
||||
dns_name_t example4com;
|
||||
|
||||
UNUSED(cfg);
|
||||
UNUSED(aclctx);
|
||||
UNUSED(source);
|
||||
UNUSED(ctx);
|
||||
|
||||
inst = isc_mem_get(mctx, sizeof(*inst));
|
||||
*inst = (syncplugin_t){ .mctx = mctx };
|
||||
|
|
@ -155,12 +158,40 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
|
|||
sourcestr = obj->value.string.base;
|
||||
|
||||
if (strcmp(sourcestr, "zone") == 0) {
|
||||
if (source != NS_HOOKSOURCE_ZONE) {
|
||||
if (ctx->source != NS_HOOKSOURCE_ZONE) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ctx->origin == NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dns_name_init(&example2com);
|
||||
dns_name_init(&example3com);
|
||||
dns_name_init(&example4com);
|
||||
|
||||
result = dns_name_fromstring(&example2com, "example2.com.",
|
||||
NULL, 0, isc_g_mctx);
|
||||
result = dns_name_fromstring(&example3com, "example3.com.",
|
||||
NULL, 0, isc_g_mctx);
|
||||
result = dns_name_fromstring(&example4com, "example4.com.",
|
||||
NULL, 0, isc_g_mctx);
|
||||
|
||||
if (!dns_name_equal(ctx->origin, &example2com) &&
|
||||
!dns_name_equal(ctx->origin, &example3com) &&
|
||||
!dns_name_equal(ctx->origin, &example4com))
|
||||
{
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
} else if (strcmp(sourcestr, "view") == 0) {
|
||||
if (source != NS_HOOKSOURCE_VIEW) {
|
||||
if (ctx->source != NS_HOOKSOURCE_VIEW) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
if (ctx->origin != NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -173,6 +204,18 @@ plugin_register(const char *parameters, const void *cfg, const char *cfgfile,
|
|||
ns_hook_add(hooktable, mctx, NS_QUERY_NXDOMAIN_BEGIN, &hook);
|
||||
|
||||
cleanup:
|
||||
if (DNS_NAME_VALID(&example2com)) {
|
||||
dns_name_free(&example2com, isc_g_mctx);
|
||||
}
|
||||
|
||||
if (DNS_NAME_VALID(&example3com)) {
|
||||
dns_name_free(&example3com, isc_g_mctx);
|
||||
}
|
||||
|
||||
if (DNS_NAME_VALID(&example4com)) {
|
||||
dns_name_free(&example4com, isc_g_mctx);
|
||||
}
|
||||
|
||||
if (syncplugincfg != NULL) {
|
||||
cfg_obj_destroy(parser, &syncplugincfg);
|
||||
}
|
||||
|
|
@ -187,14 +230,14 @@ cleanup:
|
|||
isc_result_t
|
||||
plugin_check(const char *parameters, const void *cfg, const char *cfgfile,
|
||||
unsigned long cfgline, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooksource_t source) {
|
||||
const ns_pluginregister_ctx_t *ctx) {
|
||||
UNUSED(parameters);
|
||||
UNUSED(cfg);
|
||||
UNUSED(cfgfile);
|
||||
UNUSED(cfgline);
|
||||
UNUSED(mctx);
|
||||
UNUSED(aclctx);
|
||||
UNUSED(source);
|
||||
UNUSED(ctx);
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1237,6 +1237,8 @@ zone_free(dns_zone_t *zone) {
|
|||
REQUIRE(zone->timer == NULL);
|
||||
REQUIRE(zone->zmgr == NULL);
|
||||
|
||||
dns_zone_unloadplugins(zone);
|
||||
|
||||
isc_refcount_destroy(&zone->references);
|
||||
isc_refcount_destroy(&zone->irefs);
|
||||
|
||||
|
|
@ -1385,7 +1387,6 @@ zone_free(dns_zone_t *zone) {
|
|||
if (zone->gluecachestats != NULL) {
|
||||
isc_stats_detach(&zone->gluecachestats);
|
||||
}
|
||||
dns_zone_unloadplugins(zone);
|
||||
|
||||
/* last stuff */
|
||||
ZONEDB_DESTROYLOCK(&zone->dblock);
|
||||
|
|
|
|||
|
|
@ -3063,6 +3063,7 @@ struct check_one_plugin_data {
|
|||
cfg_aclconfctx_t *aclctx;
|
||||
ns_hooksource_t source;
|
||||
isc_result_t *check_result;
|
||||
const ns_pluginregister_ctx_t *ctx;
|
||||
};
|
||||
|
||||
/*%
|
||||
|
|
@ -3094,7 +3095,7 @@ check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
|||
|
||||
result = ns_plugin_check(full_path, parameters, config,
|
||||
cfg_obj_file(obj), cfg_obj_line(obj),
|
||||
data->mctx, data->aclctx, data->source);
|
||||
data->mctx, data->aclctx, data->ctx);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR, "%s: plugin check failed: %s",
|
||||
full_path, isc_result_totext(result));
|
||||
|
|
@ -3106,14 +3107,20 @@ check_one_plugin(const cfg_obj_t *config, const cfg_obj_t *obj,
|
|||
|
||||
static isc_result_t
|
||||
check_plugins(const cfg_obj_t *plugins, const cfg_obj_t *config,
|
||||
cfg_aclconfctx_t *aclctx, ns_hooksource_t source,
|
||||
cfg_aclconfctx_t *aclctx, const dns_name_t *zname,
|
||||
isc_mem_t *mctx) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
ns_pluginregister_ctx_t ctx = {
|
||||
.source = (zname == NULL) ? NS_HOOKSOURCE_VIEW
|
||||
: NS_HOOKSOURCE_ZONE,
|
||||
.origin = zname,
|
||||
};
|
||||
struct check_one_plugin_data check_one_plugin_data = {
|
||||
.mctx = mctx,
|
||||
.aclctx = aclctx,
|
||||
.source = source,
|
||||
.source = ctx.source,
|
||||
.check_result = &result,
|
||||
.ctx = &ctx,
|
||||
};
|
||||
|
||||
(void)cfg_pluginlist_foreach(config, plugins, aclctx, check_one_plugin,
|
||||
|
|
@ -4132,8 +4139,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
|||
const cfg_obj_t *plugins = NULL;
|
||||
|
||||
(void)cfg_map_get(zoptions, "plugin", &plugins);
|
||||
tresult = check_plugins(plugins, config, aclctx,
|
||||
NS_HOOKSOURCE_ZONE, mctx);
|
||||
tresult = check_plugins(plugins, config, aclctx, zname, mctx);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
result = tresult;
|
||||
}
|
||||
|
|
@ -5745,8 +5751,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
|
|||
(void)cfg_map_get(config, "plugin", &plugins);
|
||||
}
|
||||
|
||||
tresult = check_plugins(plugins, config, aclctx,
|
||||
NS_HOOKSOURCE_VIEW, mctx);
|
||||
tresult = check_plugins(plugins, config, aclctx, NULL, mctx);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
result = tresult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,13 +239,14 @@ 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);
|
||||
INSIST(hookdata->pluginregister_ctx.source != NS_HOOKSOURCE_UNDEFINED);
|
||||
|
||||
CHECK(plugin->check_func(parameters, cfg, cfg_file, cfg_line, mctx,
|
||||
aclctx, hookdata->source));
|
||||
aclctx, &hookdata->pluginregister_ctx));
|
||||
CHECK(plugin->register_func(parameters, cfg, cfg_file, cfg_line, mctx,
|
||||
aclctx, hookdata->hooktable,
|
||||
hookdata->source, &plugin->inst));
|
||||
&hookdata->pluginregister_ctx,
|
||||
&plugin->inst));
|
||||
|
||||
ISC_LIST_APPEND(*hookdata->plugins, plugin, link);
|
||||
|
||||
|
|
@ -260,14 +261,14 @@ cleanup:
|
|||
isc_result_t
|
||||
ns_plugin_check(const char *modpath, const char *parameters, const void *cfg,
|
||||
const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx,
|
||||
void *aclctx, ns_hooksource_t source) {
|
||||
void *aclctx, const ns_pluginregister_ctx_t *ctx) {
|
||||
isc_result_t result;
|
||||
ns_plugin_t *plugin = NULL;
|
||||
|
||||
CHECK(load_plugin(mctx, modpath, &plugin));
|
||||
|
||||
result = plugin->check_func(parameters, cfg, cfg_file, cfg_line, mctx,
|
||||
aclctx, source);
|
||||
aclctx, ctx);
|
||||
|
||||
cleanup:
|
||||
if (plugin != NULL) {
|
||||
|
|
|
|||
|
|
@ -369,12 +369,18 @@
|
|||
* 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
|
||||
* when the plugin is loaded) has a `ns_pluginregister_ctx_t ctx` parameter.
|
||||
* This provides to the plugin registering function various contextual
|
||||
* informations about the plugin. For instance, the `ns_hooksource_t source`
|
||||
* property 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.
|
||||
* only at the zone or view level. Another property is `dns_name_t *origin`
|
||||
* which indicates the zone name to the plugin if it is loaded at the zone level
|
||||
* (this property is NULL otherwise). Note that `ns_pluginregister_ctx_t`
|
||||
* parameter is defined in a parent stack frame, thus, it is valid only during
|
||||
* `plugin_register` execution.
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
|
@ -490,10 +496,18 @@ typedef enum {
|
|||
NS_HOOKSOURCE_ZONE
|
||||
} ns_hooksource_t;
|
||||
|
||||
typedef struct ns_hook_data {
|
||||
ns_hooktable_t *hooktable;
|
||||
ns_plugins_t *plugins;
|
||||
typedef struct ns_pluginregister_ctx {
|
||||
/* is this a zone or a view plugin */
|
||||
ns_hooksource_t source;
|
||||
|
||||
/* origin of the zone if this is a zone plugin, NULL otherwise */
|
||||
const dns_name_t *origin;
|
||||
} ns_pluginregister_ctx_t;
|
||||
|
||||
typedef struct ns_hook_data {
|
||||
ns_hooktable_t *hooktable;
|
||||
ns_plugins_t *plugins;
|
||||
ns_pluginregister_ctx_t pluginregister_ctx;
|
||||
} ns_hook_data_t;
|
||||
|
||||
/*
|
||||
|
|
@ -512,8 +526,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 *aclctx,
|
||||
ns_hooktable_t *hooktable, ns_hooksource_t source,
|
||||
void **instp);
|
||||
ns_hooktable_t *hooktable,
|
||||
const ns_pluginregister_ctx_t *ctx, void **instp);
|
||||
/*%<
|
||||
* Called when registering a new plugin.
|
||||
*
|
||||
|
|
@ -538,7 +552,7 @@ ns_plugin_destroy_t(void **instp);
|
|||
typedef isc_result_t
|
||||
ns_plugin_check_t(const char *parameters, const void *cfg, const char *file,
|
||||
unsigned long line, isc_mem_t *mctx, void *aclctx,
|
||||
ns_hooksource_t source);
|
||||
const ns_pluginregister_ctx_t *ctx);
|
||||
/*%<
|
||||
* Check the validity of 'parameters'.
|
||||
*/
|
||||
|
|
@ -605,7 +619,7 @@ ns_plugin_register(const char *modpath, const char *parameters, const void *cfg,
|
|||
isc_result_t
|
||||
ns_plugin_check(const char *modpath, const char *parameters, const void *cfg,
|
||||
const char *cfg_file, unsigned long cfg_line, isc_mem_t *mctx,
|
||||
void *aclctx, ns_hooksource_t source);
|
||||
void *aclctx, const ns_pluginregister_ctx_t *ctx);
|
||||
/*%<
|
||||
* Open the plugin module at 'modpath' and check the validity of
|
||||
* 'parameters', logging any errors or warnings found, then
|
||||
|
|
|
|||
Loading…
Reference in a new issue