]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Add support for multiple dynamic modules
authorPMunch <peterme@peterme.net>
Mon, 21 Oct 2019 13:02:03 +0000 (15:02 +0200)
committerPMunch <peterme@peterme.net>
Mon, 21 Oct 2019 13:59:53 +0000 (15:59 +0200)
Allows the use of multiple dynamic modules. Simply add more "dynlib"
entries to the "modules-config" and the same amount of "dynlib-file"
entries in the dynlib configuration block.

doc/example.conf.in
doc/unbound.conf.5.in
dynlibmod/dynlibmod.c
util/config_file.c
util/config_file.h
util/configparser.y

index ab6b43baae3e0829a08e5ca3adb07814be604d91..5820e5e0a56a36d64a2a5a4caa4b0499c6e3f828 100644 (file)
@@ -842,7 +842,8 @@ python:
 # o list dynlib in the module-config string (above) to enable.
 #   It can be placed anywhere, the dynlib module is only a very thin wrapper
 #   to load modules dynamically.
-# o and give a dynlib-file to run.
+# o and give a dynlib-file to run. If more than one dynlib entry is listed in
+#   the module-config then you need one dynlib-file per instance.
 dynlib:
        # Script file to load
        # dynlib-file: "@UNBOUND_SHARE_DIR@/dynlib.so"
index 434467995f4f1088a8309dc98826f5fe9d0af88b..d0583d5004367774a9b24d509a2d0f413de0986f 100644 (file)
@@ -1792,14 +1792,16 @@ clause gives the settings for the \fIdynlib\fR(1) module.  This module is only
 a very small wrapper that allows dynamic modules to be loaded on runtime
 instead of being compiled into the application. To enable the dynlib module it
 has to be compiled into the daemon, and the word "dynlib" has to be put in the
-\fBmodule\-config:\fR option.
+\fBmodule\-config:\fR option. Multiple instances of dynamic libraries are
+supported by adding the word "dynlib" more than once.
 .LP
 The \fBdynlib\-file:\fR path should be specified as an absolute path relative
 to the new path set by \fBchroot:\fR option, or as a relative path to the
 working directory.
 .TP
 .B dynlib\-file: \fI<dynlib file>\fR
-The dynamic library file to load.
+The dynamic library file to load. Repeat this option for every dynlib module
+instance added to the \fBmodule\-config:\fR option.
 .SS "DNS64 Module Options"
 .LP
 The dns64 module must be configured in the \fBmodule\-config:\fR "dns64
index 3592f7de77edc5425d06e7c28a50c9920bb1f135..54b2a5816729a805f02466dd6995bb929bad59c6 100644 (file)
@@ -81,34 +81,48 @@ struct dynlibmod_env {
        struct module_qstate* qstate;
 };
 
+/**
+ * counter for dynamic library module instances
+ * incremeted by dynlibmod_init
+ */
+int dynlib_mod_count = 0;
+
 /** dynlib module init */
 int dynlibmod_init(struct module_env* env, int id) {
+    int dynlib_mod_idx = dynlib_mod_count++;
+    struct config_strlist* cfg_item = env->cfg->dynlib_file;
     struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
     __DYNMOD dynamic_library;
     if (!de)
     {
-        log_err("dynlibmod: malloc failure");
+        log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
         return 0;
     }
 
     env->modinfo[id] = (void*) de;
 
-    de->fname = env->cfg->dynlib_file;
-    if (de->fname == NULL || de->fname[0] == 0) {
-        log_err("dynlibmod: no dynamic library given.");
+    de->fname = NULL;
+    for(int i = dynlib_mod_idx;
+        i != 0 && cfg_item != NULL;
+        i--, cfg_item = cfg_item->next) {}
+
+    if (cfg_item == NULL || cfg_item->str == NULL || cfg_item->str[0] == 0) {
+        log_err("dynlibmod[%d]: no dynamic library given.", dynlib_mod_idx);
         return 0;
+    } else {
+        de->fname = cfg_item->str;
     }
-    verbose(VERB_ALGO, "dynlibmod: Trying to load library %s", de->fname);
+    verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname);
     dynamic_library = open_library(de->fname);
     if (dynamic_library == NULL) {
         log_dlerror();
-        log_err("dynlibmod: unable to load dynamic library \"%s\".", de->fname);
+        log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname);
         return 0;
     } else {
         __DYNSYM initializer = __LOADSYM(dynamic_library,"init");
         if (initializer == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load init procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load init procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_init = (func_init_t) initializer;
@@ -116,7 +130,7 @@ int dynlibmod_init(struct module_env* env, int id) {
         __DYNSYM deinitializer = __LOADSYM(dynamic_library,"deinit");
         if (deinitializer == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load deinit procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load deinit procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_deinit = (func_deinit_t) deinitializer;
@@ -124,7 +138,7 @@ int dynlibmod_init(struct module_env* env, int id) {
         __DYNSYM operate = __LOADSYM(dynamic_library,"operate");
         if (operate == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load operate procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load operate procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_operate = (func_operate_t) operate;
@@ -132,7 +146,7 @@ int dynlibmod_init(struct module_env* env, int id) {
         __DYNSYM inform = __LOADSYM(dynamic_library,"inform_super");
         if (inform == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load inform_super procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load inform_super procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_inform = (func_inform_t) inform;
@@ -140,7 +154,7 @@ int dynlibmod_init(struct module_env* env, int id) {
         __DYNSYM clear = __LOADSYM(dynamic_library,"clear");
         if (clear == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load clear procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load clear procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_clear = (func_clear_t) clear;
@@ -148,7 +162,7 @@ int dynlibmod_init(struct module_env* env, int id) {
         __DYNSYM get_mem = __LOADSYM(dynamic_library,"get_mem");
         if (get_mem == NULL) {
             log_dlerror();
-            log_err("dynlibmod: unable to load get_mem procedure from dynamic library \"%s\".", de->fname);
+            log_err("dynlibmod[%d]: unable to load get_mem procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
             return 0;
         } else {
             de->func_get_mem = (func_get_mem_t) get_mem;
index 7a8fb0bbc667de4d64458b66cb2f799acaf79f20..1afeb46bf30a8d2d7f760adba5b661d83910b833 100644 (file)
@@ -611,7 +611,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_STR("control-cert-file:", control_cert_file)
        else S_STR("module-config:", module_conf)
        else S_STRLIST("python-script:", python_script)
-       else S_STR("dynlib-file:", dynlib_file)
+       else S_STRLIST("dynlib-file:", dynlib_file)
        else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
 #ifdef CLIENT_SUBNET
        /* Can't set max subnet prefix here, since that value is used when
@@ -1064,7 +1064,7 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
        else O_DEC(opt, "max-udp-size", max_udp_size)
        else O_LST(opt, "python-script", python_script)
-       else O_STR(opt, "dynlib-file", dynlib_file)
+       else O_LST(opt, "dynlib-file", dynlib_file)
        else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
        else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
        else O_DEC(opt, "ratelimit", ratelimit)
@@ -1401,7 +1401,6 @@ config_delete(struct config_file* cfg)
        free(cfg->version);
        free(cfg->module_conf);
        free(cfg->outgoing_avail_ports);
-       free(cfg->dynlib_file);
        config_delstrlist(cfg->caps_whitelist);
        config_delstrlist(cfg->private_address);
        config_delstrlist(cfg->private_domain);
@@ -1441,6 +1440,7 @@ config_delete(struct config_file* cfg)
        config_deldblstrlist(cfg->ratelimit_for_domain);
        config_deldblstrlist(cfg->ratelimit_below_domain);
        config_delstrlist(cfg->python_script);
+       config_delstrlist(cfg->dynlib_file);
 #ifdef USE_IPSECMOD
        free(cfg->ipsecmod_hook);
        config_delstrlist(cfg->ipsecmod_whitelist);
index 6706ab08bacb33f80c4298c2deaef04ff53835c4..972c70fb8ae9ad38988a32bf947d627f48d5403a 100644 (file)
@@ -440,7 +440,7 @@ struct config_file {
        struct config_strlist* python_script;
 
        /** Dynamic library file */
-       char* dynlib_file;
+       struct config_strlist* dynlib_file;
 
        /** Use systemd socket activation. */
        int use_systemd;
index 5f58d75b3ac4715dac5b6a106c58a473963390ef..f180f188fcaebe8524536faad5a99ce7c41933fe 100644 (file)
@@ -2754,8 +2754,8 @@ content_dl: dl_file
 dl_file: VAR_DYNLIB_FILE STRING_ARG
        {
                OUTYY(("P(dynlib-file:%s)\n", $2));
-               free(cfg_parser->cfg->dynlib_file);
-               cfg_parser->cfg->dynlib_file = $2;
+               if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, $2))
+                       yyerror("out of memory");
        }
 server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
        {