]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
add namedconf support for plugin inside a zone
authorColin Vidal <colin@isc.org>
Mon, 26 May 2025 14:53:31 +0000 (16:53 +0200)
committerColin Vidal <colin@isc.org>
Tue, 9 Sep 2025 07:42:34 +0000 (09:42 +0200)
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.

bin/named/server.c
doc/misc/mirror.zoneopt
doc/misc/options
doc/misc/primary.zoneopt
doc/misc/redirect.zoneopt
doc/misc/secondary.zoneopt
lib/isccfg/check.c
lib/isccfg/include/isccfg/check.h
lib/isccfg/namedconf.c

index cce0be6d7bf840930f0fc27556e11527260512ce..5629508a486ca28e4eb202e9a4dfe331a6e15299 100644 (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;
index aa193235a72f348698514aa814ed3b4ae60928de..346f093d335a8988a5e0b0c9aacfa9625465060c 100644 (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>;
index 0c80800b58b6087143e15a633a87e400bee4aa75..e11f0c4d8690a07a069a1b788803e1cf74fa2846 100644 (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>;
index dd1b94756b770b631da926ff2a7c030dfff1cb78..dfebff879b77fd548a81f613d9160a95c216ff7d 100644 (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 );
index e338b6e2316d8485d18f57bbf25294dbc8eed886..077b01af2569bb8a18dcd4e076d6a42f3bf97f80 100644 (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> );
index 7529112a3342fe4d5b047359e4daf62086bf2029..cbbd5fea528c50a8904a8743ae965cc80a686fb6 100644 (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>;
index 3569f7fc18de3e7ba0454bca78397fa74d3d1e65..1d06e1e303d79b4a069646842fe3e8eba533ca88 100644 (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;
                }
index 9a670bbd3d028f99749a7f424ba566bdf3d5d403..f3980204d2079aadb73e9ba33cbd4fe780519214 100644 (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.
index 8ec7607d7ae7c4b6feed638b3de617583d712119..69e5fb0ba991a18932b226aedd6f76bfa0021715 100644 (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 },