]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
provide a context structure for plugin_register()
authorColin Vidal <colin@isc.org>
Fri, 26 Sep 2025 13:54:51 +0000 (15:54 +0200)
committerColin Vidal <colin@isc.org>
Wed, 1 Oct 2025 09:11:00 +0000 (11:11 +0200)
This commit introduces a new type, ns_pluginregister_ctx_t,
which is passed to plugin_check() and 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.

bin/named/server.c
bin/named/zoneconf.c
bin/plugins/filter-a.c
bin/plugins/filter-aaaa.c
bin/tests/system/hooks/driver/test-async.c
bin/tests/system/hooks/driver/test-syncplugin.c
lib/isccfg/check.c
lib/ns/hooks.c
lib/ns/include/ns/hooks.h

index c34fd28a8be67a997368e19b5a7a7edf36982552..6dedd6a6e054d535013d5779a6ffd3c9cfd839c7 100644 (file)
@@ -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);
index 6c58acfbaf93f2caf63d78bb195f8c7758c3cbf0..5bf24c14559f3a8dd897753fc399fcb87f069b47 100644 (file)
@@ -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);
index 74209132d9c2a2eed35673036c82da608c23de76..bd85a3b008a7dda2233094c78f30a0861b38e362 100644 (file)
@@ -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;
index bf58f557b957fb8d58d0b2652e55dbf114d74adf..80403455a060976b5cdbd3192c0c5ea0b6fadb48 100644 (file)
@@ -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;
index 1d86de1e9ceea71256042f1a9f731a6a9bcee164..57197a76ae004990509d56979050222ea799f24b 100644 (file)
@@ -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;
 }
index 59f163add492b601abd43e94f706412d18ae2bc0..89009161f884443f55e72d3313135639352577d2 100644 (file)
@@ -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;
 }
index bd2bfb4740cb2369ced54cef8508bd2a215d80fa..c60315d4a2533e07815526aebf52a615c6123c28 100644 (file)
@@ -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;
                }
index c8fc2c34f8cffe1ea84e5684b7d79ea29c1a3ac2..2b4fd9e031b9c61b0f16e9a14cbd789a9ceba0f2 100644 (file)
@@ -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) {
index 7bf6eaccec0b813eb074f6d1a64fbecfe289f800..aac396ccaac26729b8a69f1c2d3c62ec900e2848 100644 (file)
  *   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