Add support for multiple dynamic modules

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.
This commit is contained in:
PMunch 2019-10-21 15:02:03 +02:00
parent 8eeb910e3d
commit f177dc974c
6 changed files with 38 additions and 21 deletions

View 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"

View 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

View 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;

View 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);

View 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;

View 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
{