From c96e4ca121f4b932701d5158d4d56f9fdef61757 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jan 2020 15:49:04 +0100 Subject: [PATCH 01/11] allow privileged initialisation of modules --- cachedb/cachedb.c | 6 +-- cachedb/cachedb.h | 4 +- daemon/daemon.c | 20 +++++++- daemon/daemon.h | 5 +- daemon/unbound.c | 4 +- dns64/dns64.c | 8 ++-- dns64/dns64.h | 4 +- edns-subnet/subnetmod.c | 10 ++-- edns-subnet/subnetmod.h | 4 +- ipsecmod/ipsecmod.c | 9 ++-- ipsecmod/ipsecmod.h | 4 +- ipset/ipset.c | 6 +-- ipset/ipset.h | 4 +- iterator/iterator.c | 8 ++-- iterator/iterator.h | 4 +- libunbound/context.c | 2 + libunbound/libunbound.c | 5 +- respip/respip.c | 8 ++-- respip/respip.h | 4 +- services/modstack.c | 61 +++++++++++++++++------- services/modstack.h | 29 ++++++++---- smallapp/unbound-checkconf.c | 6 ++- util/fptr_wlist.c | 90 ++++++++++++++++++++++-------------- util/fptr_wlist.h | 12 ++++- util/module.c | 5 ++ util/module.h | 33 ++++++++++--- validator/validator.c | 8 ++-- validator/validator.h | 4 +- 28 files changed, 245 insertions(+), 122 deletions(-) diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index eed4d5fd9..06738972f 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -229,7 +229,7 @@ cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg) } int -cachedb_init(struct module_env* env, int id) +cachedb_setup(struct module_env* env, int id) { struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1, sizeof(struct cachedb_env)); @@ -268,7 +268,7 @@ cachedb_init(struct module_env* env, int id) } void -cachedb_deinit(struct module_env* env, int id) +cachedb_desetup(struct module_env* env, int id) { struct cachedb_env* cachedb_env; if(!env || !env->modinfo[id]) @@ -846,7 +846,7 @@ cachedb_get_mem(struct module_env* env, int id) */ static struct module_func_block cachedb_block = { "cachedb", - &cachedb_init, &cachedb_deinit, &cachedb_operate, + &module_dummy_init, &module_dummy_init, &cachedb_setup, &cachedb_desetup, &cachedb_operate, &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem }; diff --git a/cachedb/cachedb.h b/cachedb/cachedb.h index 05c4368e6..117916e4b 100644 --- a/cachedb/cachedb.h +++ b/cachedb/cachedb.h @@ -90,9 +90,9 @@ struct cachedb_backend { #define CACHEDB_HASHSIZE 256 /* bit hash */ /** Init the cachedb module */ -int cachedb_init(struct module_env* env, int id); +int cachedb_setup(struct module_env* env, int id); /** Deinit the cachedb module */ -void cachedb_deinit(struct module_env* env, int id); +void cachedb_desetup(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/daemon/daemon.c b/daemon/daemon.c index 5d4279259..05f16cc60 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -251,7 +251,7 @@ daemon_init(void) tzset(); #endif daemon->need_to_exit = 0; - modstack_init(&daemon->mods); + memset(&daemon->mods, 0, sizeof(daemon->mods)); if(!(daemon->env = (struct module_env*)calloc(1, sizeof(*daemon->env)))) { free(daemon); @@ -293,7 +293,7 @@ daemon_init(void) return daemon; } -int +int daemon_open_shared_ports(struct daemon* daemon) { log_assert(daemon); @@ -365,6 +365,22 @@ daemon_open_shared_ports(struct daemon* daemon) return 1; } +int +daemon_privileged(struct daemon* daemon) +{ + if(!daemon_open_shared_ports(daemon)) + fatal_exit("could not open ports"); + + daemon->env->cfg = daemon->cfg; + daemon->env->alloc = &daemon->superalloc; + daemon->env->worker = NULL; + if(!modstack_init(&daemon->mods, daemon->cfg->module_conf, + daemon->env)) { + fatal_exit("failed to init modules"); + } + return 1; +} + /** * Setup modules. setup module stack. * @param daemon: the daemon diff --git a/daemon/daemon.h b/daemon/daemon.h index 3effbafb7..7d8b99fc4 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -147,12 +147,13 @@ struct daemon { struct daemon* daemon_init(void); /** - * Open shared listening ports (if needed). + * Do daemon setup that needs privileges + * like opening privileged ports or opening device files. * The cfg member pointer must have been set for the daemon. * @param daemon: the daemon. * @return: false on error. */ -int daemon_open_shared_ports(struct daemon* daemon); +int daemon_privileged(struct daemon* daemon); /** * Fork workers and start service. diff --git a/daemon/unbound.c b/daemon/unbound.c index ceb3da6f5..32604728d 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -668,8 +668,8 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi config_lookup_uid(cfg); /* prepare */ - if(!daemon_open_shared_ports(daemon)) - fatal_exit("could not open ports"); + if(!daemon_privileged(daemon)) + fatal_exit("could not do privileged setup"); if(!done_setup) { perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile); done_setup = 1; diff --git a/dns64/dns64.c b/dns64/dns64.c index 5c70119a5..97ecce4b0 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -394,7 +394,7 @@ dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg) * \param id This instance's ID number. */ int -dns64_init(struct module_env* env, int id) +dns64_setup(struct module_env* env, int id) { struct dns64_env* dns64_env = (struct dns64_env*)calloc(1, sizeof(struct dns64_env)); @@ -428,7 +428,7 @@ free_ignore_aaaa_node(rbnode_type* node, void* ATTR_UNUSED(arg)) * \param id This instance's ID number. */ void -dns64_deinit(struct module_env* env, int id) +dns64_desetup(struct module_env* env, int id) { struct dns64_env* dns64_env; if (!env) @@ -1019,8 +1019,8 @@ dns64_get_mem(struct module_env* env, int id) */ static struct module_func_block dns64_block = { "dns64", - &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super, - &dns64_clear, &dns64_get_mem + &module_dummy_init, &module_dummy_init, &dns64_setup, &dns64_desetup, + &dns64_operate, &dns64_inform_super, &dns64_clear, &dns64_get_mem }; /** diff --git a/dns64/dns64.h b/dns64/dns64.h index 2f0c01a22..532a5bed3 100644 --- a/dns64/dns64.h +++ b/dns64/dns64.h @@ -50,10 +50,10 @@ struct module_func_block *dns64_get_funcblock(void); /** dns64 init */ -int dns64_init(struct module_env* env, int id); +int dns64_setup(struct module_env* env, int id); /** dns64 deinit */ -void dns64_deinit(struct module_env* env, int id); +void dns64_desetup(struct module_env* env, int id); /** dns64 operate on a query */ void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index 37dc550cd..cb2969352 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -188,7 +188,7 @@ subnet_markdel(void* key) } int -subnetmod_init(struct module_env *env, int id) +subnetmod_setup(struct module_env *env, int id) { struct subnet_env *sn_env = (struct subnet_env*)calloc(1, sizeof(struct subnet_env)); @@ -246,7 +246,7 @@ subnetmod_init(struct module_env *env, int id) } void -subnetmod_deinit(struct module_env *env, int id) +subnetmod_desetup(struct module_env *env, int id) { struct subnet_env *sn_env; if(!env || !env->modinfo[id]) @@ -846,8 +846,10 @@ subnetmod_get_mem(struct module_env *env, int id) * The module function block */ static struct module_func_block subnetmod_block = { - "subnet", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate, - &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem + "subnet", + &module_dummy_init, &module_dummy_init, &subnetmod_setup, + &subnetmod_desetup, &subnetmod_operate, &subnetmod_inform_super, + &subnetmod_clear, &subnetmod_get_mem }; struct module_func_block* diff --git a/edns-subnet/subnetmod.h b/edns-subnet/subnetmod.h index e408627b0..7936d889e 100644 --- a/edns-subnet/subnetmod.h +++ b/edns-subnet/subnetmod.h @@ -97,10 +97,10 @@ size_t msg_cache_sizefunc(void* k, void* d); struct module_func_block* subnetmod_get_funcblock(void); /** subnet module init */ -int subnetmod_init(struct module_env* env, int id); +int subnetmod_setup(struct module_env* env, int id); /** subnet module deinit */ -void subnetmod_deinit(struct module_env* env, int id); +void subnetmod_desetup(struct module_env* env, int id); /** subnet module operate on a query */ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c index a1f40a512..ce461f00a 100644 --- a/ipsecmod/ipsecmod.c +++ b/ipsecmod/ipsecmod.c @@ -67,7 +67,7 @@ ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg) } int -ipsecmod_init(struct module_env* env, int id) +ipsecmod_setup(struct module_env* env, int id) { struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1, sizeof(struct ipsecmod_env)); @@ -85,7 +85,7 @@ ipsecmod_init(struct module_env* env, int id) } void -ipsecmod_deinit(struct module_env* env, int id) +ipsecmod_desetup(struct module_env* env, int id) { struct ipsecmod_env* ipsecmod_env; if(!env || !env->modinfo[id]) @@ -598,8 +598,9 @@ ipsecmod_get_mem(struct module_env* env, int id) */ static struct module_func_block ipsecmod_block = { "ipsecmod", - &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate, - &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem + &module_dummy_init, &module_dummy_init, &ipsecmod_setup, + &ipsecmod_desetup, &ipsecmod_operate, &ipsecmod_inform_super, + &ipsecmod_clear, &ipsecmod_get_mem }; struct module_func_block* diff --git a/ipsecmod/ipsecmod.h b/ipsecmod/ipsecmod.h index e00816d4b..96d28717b 100644 --- a/ipsecmod/ipsecmod.h +++ b/ipsecmod/ipsecmod.h @@ -74,9 +74,9 @@ struct ipsecmod_qstate { }; /** Init the ipsecmod module */ -int ipsecmod_init(struct module_env* env, int id); +int ipsecmod_setup(struct module_env* env, int id); /** Deinit the ipsecmod module */ -void ipsecmod_deinit(struct module_env* env, int id); +void ipsecmod_desetup(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/ipset/ipset.c b/ipset/ipset.c index f6e2c4a9d..bf4cbea47 100755 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -223,7 +223,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru return 0; } -int ipset_init(struct module_env* env, int id) { +int ipset_setup(struct module_env* env, int id) { struct ipset_env *ipset_env; ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); @@ -250,7 +250,7 @@ int ipset_init(struct module_env* env, int id) { return 1; } -void ipset_deinit(struct module_env *env, int id) { +void ipset_desetup(struct module_env *env, int id) { struct mnl_socket *mnl; struct ipset_env *ipset_env; @@ -373,7 +373,7 @@ size_t ipset_get_mem(struct module_env *env, int id) { */ static struct module_func_block ipset_block = { "ipset", - &ipset_init, &ipset_deinit, &ipset_operate, + &module_dummy_init, &module_dummy_init, &ipset_setup, &ipset_desetup, &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem }; diff --git a/ipset/ipset.h b/ipset/ipset.h index f60a8be8c..6273ec789 100755 --- a/ipset/ipset.h +++ b/ipset/ipset.h @@ -51,9 +51,9 @@ struct ipset_qstate { }; /** Init the ipset module */ -int ipset_init(struct module_env* env, int id); +int ipset_setup(struct module_env* env, int id); /** Deinit the ipset module */ -void ipset_deinit(struct module_env* env, int id); +void ipset_desetup(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void ipset_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/iterator/iterator.c b/iterator/iterator.c index eea2f2fb2..af209f84d 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -73,7 +73,7 @@ int UNKNOWN_SERVER_NICENESS = 376; int -iter_init(struct module_env* env, int id) +iter_setup(struct module_env* env, int id) { struct iter_env* iter_env = (struct iter_env*)calloc(1, sizeof(struct iter_env)); @@ -107,7 +107,7 @@ caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d)) } void -iter_deinit(struct module_env* env, int id) +iter_desetup(struct module_env* env, int id) { struct iter_env* iter_env; if(!env || !env->modinfo[id]) @@ -3849,8 +3849,8 @@ iter_get_mem(struct module_env* env, int id) */ static struct module_func_block iter_block = { "iterator", - &iter_init, &iter_deinit, &iter_operate, &iter_inform_super, - &iter_clear, &iter_get_mem + &module_dummy_init, &module_dummy_init, &iter_setup, &iter_desetup, + &iter_operate, &iter_inform_super, &iter_clear, &iter_get_mem }; struct module_func_block* diff --git a/iterator/iterator.h b/iterator/iterator.h index 26ff39559..30bc47289 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -429,10 +429,10 @@ const char* iter_state_to_string(enum iter_state state); int iter_state_is_responsestate(enum iter_state s); /** iterator init */ -int iter_init(struct module_env* env, int id); +int iter_setup(struct module_env* env, int id); /** iterator deinit */ -void iter_deinit(struct module_env* env, int id); +void iter_desetup(struct module_env* env, int id); /** iterator operate on a query */ void iter_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/libunbound/context.c b/libunbound/context.c index 6d62e32b5..e04cd653d 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -69,6 +69,8 @@ context_finalize(struct ub_ctx* ctx) log_init(cfg->logfile, cfg->use_syslog, NULL); } config_apply(cfg); + if(!modstack_init(&ctx->mods, cfg->module_conf, ctx->env)) + return UB_INITFAIL; if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; log_edns_known_options(VERB_ALGO, ctx->env); diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 3b30419b3..e1abfe64a 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -156,7 +156,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void) ctx->env->alloc = &ctx->superalloc; ctx->env->worker = NULL; ctx->env->need_to_validate = 0; - modstack_init(&ctx->mods); + memset(&ctx->mods, 0, sizeof(ctx->mods)); rbtree_init(&ctx->queries, &context_query_cmp); return ctx; } @@ -172,6 +172,7 @@ ub_ctx_create(void) ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); + modstack_deinit(&ctx->mods, ctx->env); edns_known_options_delete(ctx->env); free(ctx->env); free(ctx); @@ -184,6 +185,7 @@ ub_ctx_create(void) ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); + modstack_deinit(&ctx->mods, ctx->env); edns_known_options_delete(ctx->env); free(ctx->env); free(ctx); @@ -303,6 +305,7 @@ ub_ctx_delete(struct ub_ctx* ctx) libworker_delete_event(ctx->event_worker); modstack_desetup(&ctx->mods, ctx->env); + modstack_deinit(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { na = a->super; diff --git a/respip/respip.c b/respip/respip.c index 6fa4f1885..44aea841c 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -547,7 +547,7 @@ copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region) } int -respip_init(struct module_env* env, int id) +respip_setup(struct module_env* env, int id) { (void)env; (void)id; @@ -555,7 +555,7 @@ respip_init(struct module_env* env, int id) } void -respip_deinit(struct module_env* env, int id) +respip_desetup(struct module_env* env, int id) { (void)env; (void)id; @@ -1273,8 +1273,8 @@ respip_get_mem(struct module_env* env, int id) */ static struct module_func_block respip_block = { "respip", - &respip_init, &respip_deinit, &respip_operate, &respip_inform_super, - &respip_clear, &respip_get_mem + &module_dummy_init, &module_dummy_init, &respip_setup, &respip_desetup, &respip_operate, + &respip_inform_super, &respip_clear, &respip_get_mem }; struct module_func_block* diff --git a/respip/respip.h b/respip/respip.h index bbd471421..d26014766 100644 --- a/respip/respip.h +++ b/respip/respip.h @@ -192,10 +192,10 @@ int respip_rewrite_reply(const struct query_info* qinfo, struct module_func_block* respip_get_funcblock(void); /** response-ip init */ -int respip_init(struct module_env* env, int id); +int respip_setup(struct module_env* env, int id); /** response-ip deinit */ -void respip_deinit(struct module_env* env, int id); +void respip_desetup(struct module_env* env, int id); /** response-ip operate on a query */ void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/services/modstack.c b/services/modstack.c index 68e592814..5a57ecd2d 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -85,14 +85,7 @@ count_modules(const char* s) return num; } -void -modstack_init(struct module_stack* stack) -{ - stack->num = 0; - stack->mod = NULL; -} - -int +int modstack_config(struct module_stack* stack, const char* module_conf) { int i; @@ -210,18 +203,17 @@ module_func_block* module_factory(const char** str) return NULL; } -int -modstack_setup(struct module_stack* stack, const char* module_conf, +int +modstack_init(struct module_stack* stack, const char* module_conf, struct module_env* env) { - int i; - if(stack->num != 0) - modstack_desetup(stack, env); + int i; + if (stack->num != 0) + fatal_exit("unexpected already initialised modules"); /* fixed setup of the modules */ if(!modstack_config(stack, module_conf)) { return 0; } - env->need_to_validate = 0; /* set by module init below */ for(i=0; inum; i++) { verbose(VERB_OPS, "init module %d: %s", i, stack->mod[i]->name); @@ -235,8 +227,45 @@ modstack_setup(struct module_stack* stack, const char* module_conf, return 1; } -void +int +modstack_setup(struct module_stack* stack, const char* module_conf, + struct module_env* env) +{ + int i; + env->need_to_validate = 0; /* set by module setup below */ + for(i=0; inum; i++) { + while(*module_conf && isspace(*module_conf)) + module_conf++; + if(strncmp(stack->mod[i]->name, module_conf, + strlen(stack->mod[i]->name))) { + log_err("changed module ordering during reload not supported"); + return 0; + } + module_conf += strlen(stack->mod[i]->name); + verbose(VERB_OPS, "setup module %d: %s", + i, stack->mod[i]->name); + fptr_ok(fptr_whitelist_mod_setup(stack->mod[i]->setup)); + if(!(*stack->mod[i]->setup)(env, i)) { + log_err("module setup for module %s failed", + stack->mod[i]->name); + return 0; + } + } + return 1; +} + +void modstack_desetup(struct module_stack* stack, struct module_env* env) +{ + int i; + for(i=0; inum; i++) { + fptr_ok(fptr_whitelist_mod_desetup(stack->mod[i]->desetup)); + (*stack->mod[i]->desetup)(env, i); + } +} + +void +modstack_deinit(struct module_stack* stack, struct module_env* env) { int i; for(i=0; inum; i++) { @@ -248,7 +277,7 @@ modstack_desetup(struct module_stack* stack, struct module_env* env) stack->mod = NULL; } -int +int modstack_find(struct module_stack* stack, const char* name) { int i; diff --git a/services/modstack.h b/services/modstack.h index 3ff01b54d..3e79595ed 100644 --- a/services/modstack.h +++ b/services/modstack.h @@ -55,10 +55,16 @@ struct module_stack { }; /** - * Init a stack of modules - * @param stack: initialised as empty. + * Initialises modules and assignes ids. + * @param stack: Expected empty, filled according to module_conf + * @param module_conf: string what modules to initialize + * @param env: module environment which is inited by the modules. + * environment should have a superalloc, cfg, + * env.need_to_validate is set by the modules. + * @return on false a module init failed. */ -void modstack_init(struct module_stack* stack); +int modstack_init(struct module_stack* stack, const char* module_conf, + struct module_env* env); /** * Read config file module settings and set up the modfunc block @@ -83,10 +89,10 @@ struct module_func_block* module_factory(const char** str); const char** module_list_avail(void); /** - * Setup modules. Assigns ids and calls module_init. - * @param stack: if not empty beforehand, it will be desetup()ed. - * It is then modstack_configged(). - * @param module_conf: string what modules to insert. + * Setup modules. Calls module_setup(). + * @param stack: It is modstack_setupped(). + * @param module_conf: module ordering to check against the ordering in stack. + * fails on changed ordering. * @param env: module environment which is inited by the modules. * environment should have a superalloc, cfg, * env.need_to_validate is set by the modules. @@ -96,12 +102,19 @@ int modstack_setup(struct module_stack* stack, const char* module_conf, struct module_env* env); /** - * Desetup the modules, deinit, delete. + * Desetup the modules * @param stack: made empty. * @param env: module env for module deinit() calls. */ void modstack_desetup(struct module_stack* stack, struct module_env* env); +/** + * Deinit the modules, deinit, delete. + * @param stack: made empty. + * @param env: module env for module deinit() calls. + */ +void modstack_deinit(struct module_stack* stack, struct module_env* env); + /** * Find index of module by name. * @param stack: to look in diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index 3fc638cae..a1f70a8e6 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -137,9 +137,11 @@ check_mod(struct config_file* cfg, struct module_func_block* fb) fatal_exit("out of memory"); if(!edns_known_options_init(&env)) fatal_exit("out of memory"); - if(!(*fb->init)(&env, 0)) { + if(!(*fb->setup)(&env, 0)) fatal_exit("bad config for %s module", fb->name); - } + if(!(*fb->setup)(&env, 0)) + fatal_exit("bad config for %s module", fb->name); + (*fb->desetup)(&env, 0); (*fb->deinit)(&env, 0); sldns_buffer_free(env.scratch_buffer); regional_destroy(env.scratch); diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index b124e7169..35d8bfaed 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -382,56 +382,76 @@ fptr_whitelist_modenv_detect_cycle(int (*fptr)( return 0; } -int +int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)) { - if(fptr == &iter_init) return 1; - else if(fptr == &val_init) return 1; - else if(fptr == &dns64_init) return 1; - else if(fptr == &respip_init) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_init) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_init) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_init) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_init) return 1; -#endif + if(fptr == &module_dummy_init) return 1; #ifdef USE_IPSET else if(fptr == &ipset_init) return 1; #endif return 0; } -int -fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)) +int +fptr_whitelist_mod_deinit(int (*fptr)(struct module_env* env, int id)) { - if(fptr == &iter_deinit) return 1; - else if(fptr == &val_deinit) return 1; - else if(fptr == &dns64_deinit) return 1; - else if(fptr == &respip_deinit) return 1; -#ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_deinit) return 1; -#endif -#ifdef USE_CACHEDB - else if(fptr == &cachedb_deinit) return 1; -#endif -#ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_deinit) return 1; -#endif -#ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_deinit) return 1; -#endif + if(fptr == &module_dummy_init) return 1; #ifdef USE_IPSET else if(fptr == &ipset_deinit) return 1; #endif return 0; } +int +fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)) +{ + if(fptr == &iter_setup) return 1; + else if(fptr == &val_setup) return 1; + else if(fptr == &dns64_setup) return 1; + else if(fptr == &respip_setup) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_setup) return 1; +#endif +#ifdef USE_CACHEDB + else if(fptr == &cachedb_setup) return 1; +#endif +#ifdef USE_IPSECMOD + else if(fptr == &ipsecmod_setup) return 1; +#endif +#ifdef CLIENT_SUBNET + else if(fptr == &subnetmod_setup) return 1; +#endif +#ifdef USE_IPSET + else if(fptr == &ipset_setup) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)) +{ + if(fptr == &iter_desetup) return 1; + else if(fptr == &val_desetup) return 1; + else if(fptr == &dns64_desetup) return 1; + else if(fptr == &respip_desetup) return 1; +#ifdef WITH_PYTHONMODULE + else if(fptr == &pythonmod_desetup) return 1; +#endif +#ifdef USE_CACHEDB + else if(fptr == &cachedb_desetup) return 1; +#endif +#ifdef USE_IPSECMOD + else if(fptr == &ipsecmod_desetup) return 1; +#endif +#ifdef CLIENT_SUBNET + else if(fptr == &subnetmod_desetup) return 1; +#endif +#ifdef USE_IPSET + else if(fptr == &ipset_desetup) return 1; +#endif + return 0; +} + int fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound)) diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index cd331febb..3f74fc8b0 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -270,12 +270,20 @@ int fptr_whitelist_modenv_detect_cycle(int (*fptr)( int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)); /** - * Check function pointer whitelist for module deinit call values. + * Check function pointer whitelist for module setup call values. * * @param fptr: function pointer to check. * @return false if not in whitelist. */ -int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)); +int fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)); + +/** + * Check function pointer whitelist for module desetup call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)); /** * Check function pointer whitelist for module operate call values. diff --git a/util/module.c b/util/module.c index f16583183..a94b0fffa 100644 --- a/util/module.c +++ b/util/module.c @@ -246,3 +246,8 @@ copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id), super->was_ratelimited = qstate->was_ratelimited; } } + +int module_dummy_init(struct module_env* env, int id) +{ + return 1; +} diff --git a/util/module.h b/util/module.h index fa89c647e..e7b1f33e5 100644 --- a/util/module.h +++ b/util/module.h @@ -672,21 +672,40 @@ struct module_func_block { /** text string name of module */ const char* name; - /** - * init the module. Called once for the global state. - * This is the place to apply settings from the config file. - * @param env: module environment. + /** + * initialise the module. This is called only once at startup. + * Privileged operations like opening device files may be done here. * @param id: module id number. * return: 0 on error */ int (*init)(struct module_env* env, int id); /** - * de-init, delete, the module. Called once for the global state. + * deinitialise the module. This is called only once before shutdown to + * free resources allocated during init(). + * Closing privileged ports or files must be done here. + * @param id: module id number. + * return: 0 on error + */ + int (*deinit)(struct module_env* env, int id); + + /** + * setup the module. Called when restarting or reloading the + * daemon. + * This is the place to apply settings from the config file. + * @param env: module environment. + * @param id: module id number. + * return: 0 on error + */ + int (*setup)(struct module_env* env, int id); + + /** + * de-setup, undo stuff done during setup(). + * Called before reloading the daemon. * @param env: module environment. * @param id: module id number. */ - void (*deinit)(struct module_env* env, int id); + void (*desetup)(struct module_env* env, int id); /** * accept a new query, or work further on existing query. @@ -858,4 +877,6 @@ void log_edns_known_options(enum verbosity_value level, void copy_state_to_super(struct module_qstate* qstate, int id, struct module_qstate* super); +int module_dummy_init(struct module_env* env, int id); + #endif /* UTIL_MODULE_H */ diff --git a/validator/validator.c b/validator/validator.c index c3ca0a27d..fa5fe4c0e 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -165,7 +165,7 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env, void ecdsa_evp_workaround_init(void); #endif int -val_init(struct module_env* env, int id) +val_setup(struct module_env* env, int id) { struct val_env* val_env = (struct val_env*)calloc(1, sizeof(struct val_env)); @@ -190,7 +190,7 @@ val_init(struct module_env* env, int id) } void -val_deinit(struct module_env* env, int id) +val_desetup(struct module_env* env, int id) { struct val_env* val_env; if(!env || !env->modinfo[id]) @@ -3266,8 +3266,8 @@ val_get_mem(struct module_env* env, int id) */ static struct module_func_block val_block = { "validator", - &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear, - &val_get_mem + &module_dummy_init, &module_dummy_init, &val_setup, &val_desetup, + &val_operate, &val_inform_super, &val_clear, &val_get_mem }; struct module_func_block* diff --git a/validator/validator.h b/validator/validator.h index 9e4c8a941..caa18d7fd 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -254,10 +254,10 @@ struct module_func_block* val_get_funcblock(void); const char* val_state_to_string(enum val_state state); /** validator init */ -int val_init(struct module_env* env, int id); +int val_setup(struct module_env* env, int id); /** validator deinit */ -void val_deinit(struct module_env* env, int id); +void val_desetup(struct module_env* env, int id); /** validator operate on a query */ void val_operate(struct module_qstate* qstate, enum module_ev event, int id, From 7d76e84953a1753529219bd8e33412f26ba721d8 Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Sat, 11 Jan 2020 15:58:55 +0100 Subject: [PATCH 02/11] Port ipset to BSD pf tables --- config.h.in | 3 + configure | 63 +++++++++++------ configure.ac | 57 ++++++++------- ipset/ipset.c | 188 ++++++++++++++++++++++++++++++++++++++++---------- ipset/ipset.h | 8 ++- 5 files changed, 234 insertions(+), 85 deletions(-) diff --git a/config.h.in b/config.h.in index bd9b38bc0..0b1f8053a 100644 --- a/config.h.in +++ b/config.h.in @@ -371,6 +371,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETTLE_EDDSA_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_PFVAR_H + /* Use libnss for crypto */ #undef HAVE_NSS diff --git a/configure b/configure index fb1ce374e..6e40fa0f8 100755 --- a/configure +++ b/configure @@ -21376,7 +21376,22 @@ $as_echo "#define USE_IPSET 1" >>confdefs.h IPSET_OBJ="ipset.lo" - # mnl + # BSD's pf + for ac_header in net/pfvar.h +do : + ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" " + #include + #include + +" +if test "x$ac_cv_header_net_pfvar_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NET_PFVAR_H 1 +_ACEOF + +else + + # mnl # Check whether --with-libmnl was given. if test "${with_libmnl+set}" = set; then : @@ -21385,28 +21400,34 @@ else withval="yes" fi - found_libmnl="no" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmnl" >&5 + found_libmnl="no" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmnl" >&5 $as_echo_n "checking for libmnl... " >&6; } - if test x_$withval = x_ -o x_$withval = x_yes; then - withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $withval ; do - if test -f "$dir/include/libmnl/libmnl.h"; then - found_libmnl="yes" - if test "$dir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5 + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" + fi + for dir in $withval ; do + if test -f "$dir/include/libmnl/libmnl.h"; then + found_libmnl="yes" + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5 $as_echo "found in $dir" >&6; } - LIBS="$LIBS -lmnl" - break; - fi - done - if test x_$found_libmnl != x_yes; then - as_fn_error $? "Could not find libmnl, libmnl.h" "$LINENO" 5 - fi + LIBS="$LIBS -lmnl" + break; + fi + done + if test x_$found_libmnl != x_yes + then + as_fn_error $? "Could not find libmnl, libmnl.h" "$LINENO" 5 + fi + +fi + +done + ;; no|*) # nothing diff --git a/configure.ac b/configure.ac index f96a24ef2..09bdf7c57 100644 --- a/configure.ac +++ b/configure.ac @@ -1756,31 +1756,38 @@ case "$enable_ipset" in IPSET_OBJ="ipset.lo" AC_SUBST(IPSET_OBJ) - # mnl - AC_ARG_WITH(libmnl, AC_HELP_STRING([--with-libmnl=path], - [specify explicit path for libmnl.]), - [ ],[ withval="yes" ]) - found_libmnl="no" - AC_MSG_CHECKING(for libmnl) - if test x_$withval = x_ -o x_$withval = x_yes; then - withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" - fi - for dir in $withval ; do - if test -f "$dir/include/libmnl/libmnl.h"; then - found_libmnl="yes" - dnl assume /usr is in default path. - if test "$dir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$dir/include" - LDFLAGS="$LDFLAGS -L$dir/lib" - fi - AC_MSG_RESULT(found in $dir) - LIBS="$LIBS -lmnl" - break; - fi - done - if test x_$found_libmnl != x_yes; then - AC_ERROR([Could not find libmnl, libmnl.h]) - fi + # BSD's pf + AC_CHECK_HEADERS([net/pfvar.h], [], [ + # mnl + AC_ARG_WITH(libmnl, AC_HELP_STRING([--with-libmnl=path], + [specify explicit path for libmnl.]), + [ ],[ withval="yes" ]) + found_libmnl="no" + AC_MSG_CHECKING(for libmnl) + if test x_$withval = x_ -o x_$withval = x_yes; then + withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr" + fi + for dir in $withval ; do + if test -f "$dir/include/libmnl/libmnl.h"; then + found_libmnl="yes" + dnl assume /usr is in default path. + if test "$dir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$dir/include" + LDFLAGS="$LDFLAGS -L$dir/lib" + fi + AC_MSG_RESULT(found in $dir) + LIBS="$LIBS -lmnl" + break; + fi + done + if test x_$found_libmnl != x_yes + then + AC_ERROR([Could not find libmnl, libmnl.h]) + fi + ], [ + #include + #include + ]) ;; no|*) # nothing diff --git a/ipset/ipset.c b/ipset/ipset.c index bf4cbea47..347512406 100755 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -17,9 +17,21 @@ #include "sldns/wire2str.h" #include "sldns/parseutil.h" +#include + +#ifdef HAVE_NET_PFVAR_H +#include +#include +#include +#include +#include +typedef intptr_t filter_dev; +#else #include #include #include +typedef struct mnl_socket * filter_dev; +#endif #define BUFF_LEN 256 @@ -41,24 +53,95 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) { return 0; } -static struct mnl_socket * open_mnl_socket() { - struct mnl_socket *mnl; +#ifdef HAVE_NET_PFVAR_H +static void * open_filter() { + filter_dev dev; - mnl = mnl_socket_open(NETLINK_NETFILTER); - if (!mnl) { + dev = open("/dev/pf", O_RDWR); + if (dev == -1) { + log_err("open(\"/dev/pf\") failed"); + return NULL; + } + else + return (void *)dev; +} +#else +static void * open_filter() { + filter_dev dev; + + dev = mnl_socket_open(NETLINK_NETFILTER); + if (!dev) { log_err("ipset: could not open netfilter."); return NULL; } - if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) { - mnl_socket_close(mnl); + if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) { + mnl_socket_close(dev); log_err("ipset: could not bind netfilter."); return NULL; } - return mnl; + return dev; } +#endif -static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) { +#ifdef HAVE_NET_PFVAR_H +static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) { + struct pfioc_table io; + struct pfr_addr addr; + const char *p; + int i; + + bzero(&io, sizeof(io)); + bzero(&addr, sizeof(addr)); + + p = strrchr(setname, '/'); + if (p) { + i = p - setname; + if (i >= PATH_MAX) { + errno = ENAMETOOLONG; + return -1; + } + memcpy(io.pfrio_table.pfrt_anchor, setname, i); + if (i < PATH_MAX) + io.pfrio_table.pfrt_anchor[i] = '\0'; + p++; + } + else + p = setname; + + if (strlen(p) >= PF_TABLE_NAME_SIZE) { + errno = ENAMETOOLONG; + return -1; + } + strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE); + + io.pfrio_buffer = &addr; + io.pfrio_size = 1; + io.pfrio_esize = sizeof(addr); + + switch (af) { + case AF_INET: + addr.pfra_ip4addr = *(struct in_addr *)ipaddr; + addr.pfra_net = 32; + break; + case AF_INET6: + addr.pfra_ip6addr = *(struct in6_addr *)ipaddr; + addr.pfra_net = 128; + break; + default: + errno = EAFNOSUPPORT; + return -1; + } + addr.pfra_af = af; + + if (ioctl(dev, DIOCRADDADDRS, &io) == -1) { + log_err("ioctl failed: %s", strerror(errno)); + return -1; + } + return 0; +} +#else +static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) { struct nlmsghdr *nlh; struct nfgenmsg *nfg; struct nlattr *nested[2]; @@ -91,14 +174,15 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void mnl_attr_nest_end(nlh, nested[1]); mnl_attr_nest_end(nlh, nested[0]); - if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) { + if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) { return -1; } return 0; } +#endif static void -ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl, +ipset_add_rrset_data(struct ipset_env *ie, struct packed_rrset_data *d, const char* setname, int af, const char* dname) { @@ -123,12 +207,16 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl, snprintf(ip, sizeof(ip), "(inet_ntop_error)"); verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname); } - ret = add_to_ipset(mnl, setname, rr_data + 2, af); + ret = add_to_ipset((filter_dev)ie->dev, setname, rr_data + 2, af); if (ret < 0) { log_err("ipset: could not add %s into %s", dname, setname); - mnl_socket_close(mnl); - ie->mnl = NULL; +#if HAVE_NET_PFVAR_H + /* don't close as we might not be able to open again due to dropped privs */ +#else + mnl_socket_close((filter_dev)ie->dev); + ie->dev = NULL; +#endif break; } } @@ -137,7 +225,7 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl, static int ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, - struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset, + struct ub_packed_rrset_key *rrset, const char *setname, int af) { static char dname[BUFF_LEN]; @@ -158,13 +246,16 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, for (p = env->cfg->local_zones_ipset; p; p = p->next) { plen = strlen(p->str); + if (p->str[plen - 1] == '.') { + plen--; + } if (dlen >= plen) { s = dname + (dlen - plen); if (strncasecmp(p->str, s, plen) == 0) { d = (struct packed_rrset_data*)rrset->entry.data; - ipset_add_rrset_data(ie, mnl, d, setname, + ipset_add_rrset_data(ie, d, setname, af, dname); break; } @@ -174,8 +265,6 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, } static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) { - struct mnl_socket *mnl; - size_t i; const char *setname; @@ -184,17 +273,17 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru int af; - - mnl = (struct mnl_socket *)ie->mnl; - if (!mnl) { +#ifdef HAVE_NET_PFVAR_H +#else + if (!ie->dev) { // retry to create mnl socket - mnl = open_mnl_socket(); - if (!mnl) { + ie->dev = open_filter(); + if (!ie->dev) { + log_warn("ipset open_filter failed"); return -1; } - - ie->mnl = mnl; } +#endif for (i = 0; i < return_msg->rep->rrset_count; ++i) { setname = NULL; @@ -203,18 +292,18 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) { af = AF_INET; - if ((ie->v4_enabled == 1)) { + if (ie->v4_enabled == 1) { setname = ie->name_v4; } } else { af = AF_INET6; - if ((ie->v6_enabled == 1)) { + if (ie->v6_enabled == 1) { setname = ie->name_v6; } } if (setname) { - if(ipset_check_zones_for_rrset(env, ie, mnl, rrset, + if(ipset_check_zones_for_rrset(env, ie, rrset, setname, af) == -1) return -1; } @@ -223,10 +312,10 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, stru return 0; } -int ipset_setup(struct module_env* env, int id) { +int ipset_init(struct module_env* env, int id) { struct ipset_env *ipset_env; - ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); + ipset_env = (struct ipset_env *)malloc(sizeof(struct ipset_env)); if (!ipset_env) { log_err("malloc failure"); return 0; @@ -234,7 +323,28 @@ int ipset_setup(struct module_env* env, int id) { env->modinfo[id] = (void *)ipset_env; - ipset_env->mnl = NULL; +#ifdef HAVE_NET_PFVAR_H + ipset_env->dev = open_filter(); + if (!ipset_env->dev) { + log_err("ipset open_filter failed"); + return 0; + } +#else + ipset_env->dev = NULL; +#endif + return 1; +} + +int ipset_deinit(struct module_env* env, int id) { + struct ipset_env *ipset_env = env->modinfo[id]; + close((filter_dev)ipset_env->dev); + free(ipset_env); + env->modinfo[id] = NULL; + return 1; +} + +int ipset_setup(struct module_env* env, int id) { + struct ipset_env *ipset_env = env->modinfo[id]; ipset_env->name_v4 = env->cfg->ipset_name_v4; ipset_env->name_v6 = env->cfg->ipset_name_v6; @@ -251,7 +361,7 @@ int ipset_setup(struct module_env* env, int id) { } void ipset_desetup(struct module_env *env, int id) { - struct mnl_socket *mnl; + filter_dev dev; struct ipset_env *ipset_env; if (!env || !env->modinfo[id]) { @@ -260,10 +370,14 @@ void ipset_desetup(struct module_env *env, int id) { ipset_env = (struct ipset_env *)env->modinfo[id]; - mnl = (struct mnl_socket *)ipset_env->mnl; - if (mnl) { - mnl_socket_close(mnl); - ipset_env->mnl = NULL; + dev = (filter_dev)ipset_env->dev; + if (dev) { +#if HAVE_NET_PFVAR_H + close(dev); +#else + mnl_socket_close(dev); +#endif + ipset_env->dev = NULL; } free(ipset_env); @@ -373,8 +487,8 @@ size_t ipset_get_mem(struct module_env *env, int id) { */ static struct module_func_block ipset_block = { "ipset", - &module_dummy_init, &module_dummy_init, &ipset_setup, &ipset_desetup, &ipset_operate, - &ipset_inform_super, &ipset_clear, &ipset_get_mem + &ipset_init, &ipset_deinit, &ipset_setup, &ipset_desetup, + &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem }; struct module_func_block * ipset_get_funcblock(void) { diff --git a/ipset/ipset.h b/ipset/ipset.h index 6273ec789..66a4378b6 100755 --- a/ipset/ipset.h +++ b/ipset/ipset.h @@ -37,7 +37,7 @@ extern "C" { #endif struct ipset_env { - void* mnl; + void* dev; int v4_enabled; int v6_enabled; @@ -51,8 +51,12 @@ struct ipset_qstate { }; /** Init the ipset module */ -int ipset_setup(struct module_env* env, int id); +int ipset_init(struct module_env* env, int id); /** Deinit the ipset module */ +int ipset_deinit(struct module_env* env, int id); +/** Setup the ipset module */ +int ipset_setup(struct module_env* env, int id); +/** Desetup the ipset module */ void ipset_desetup(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void ipset_operate(struct module_qstate* qstate, enum module_ev event, From ad51795314b9bc89f78e4c2a2efe9feec871367c Mon Sep 17 00:00:00 2001 From: Christopher Zimmermann Date: Tue, 14 Jan 2020 23:45:21 +0100 Subject: [PATCH 03/11] Don't try to run daemon_privileged on reload. --- daemon/unbound.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/unbound.c b/daemon/unbound.c index 32604728d..358d57bf1 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -668,9 +668,9 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi config_lookup_uid(cfg); /* prepare */ - if(!daemon_privileged(daemon)) - fatal_exit("could not do privileged setup"); if(!done_setup) { + if(!daemon_privileged(daemon)) + fatal_exit("could not do privileged setup"); perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile); done_setup = 1; } else { From fd11cd91824bf6d253412aa2a955dbc5792fd04f Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Jul 2024 14:54:45 +0200 Subject: [PATCH 04/11] ipset-pf-support, fix compilation, close of pf socket. --- ipset/ipset.c | 3 +++ pythonmod/pythonmod.c | 2 +- util/fptr_wlist.c | 4 ++-- util/fptr_wlist.h | 8 ++++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ipset/ipset.c b/ipset/ipset.c index 59fd9ce9f..f7cf2082e 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -270,6 +270,7 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct query_info qinfo, struct ipset_env *ie) +{ size_t i; const char *setname; struct ub_packed_rrset_key *rrset; @@ -344,7 +345,9 @@ int ipset_init(struct module_env* env, int id) { int ipset_deinit(struct module_env* env, int id) { struct ipset_env *ipset_env = env->modinfo[id]; +#ifdef HAVE_NET_PFVAR_H close((filter_dev)ipset_env->dev); +#endif free(ipset_env); env->modinfo[id] = NULL; return 1; diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index b8f2d62fb..6bc6752e2 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -777,7 +777,7 @@ size_t pythonmod_get_mem(struct module_env* env, int id) */ static struct module_func_block pythonmod_block = { "python", - &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, + &module_dummy_init, &module_dummy_init, &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, &pythonmod_clear, &pythonmod_get_mem }; diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 3ea258358..d24941321 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -420,7 +420,7 @@ fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)) else if(fptr == &dns64_setup) return 1; else if(fptr == &respip_setup) return 1; #ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_setup) return 1; + else if(fptr == &pythonmod_init) return 1; #endif #ifdef WITH_DYNLIBMODULE else if(fptr == &dynlibmod_init) return 1; @@ -448,7 +448,7 @@ fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)) else if(fptr == &dns64_desetup) return 1; else if(fptr == &respip_desetup) return 1; #ifdef WITH_PYTHONMODULE - else if(fptr == &pythonmod_desetup) return 1; + else if(fptr == &pythonmod_deinit) return 1; #endif #ifdef WITH_DYNLIBMODULE else if(fptr == &dynlibmod_deinit) return 1; diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index cf1a4fbc3..cf70c7066 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -270,6 +270,14 @@ int fptr_whitelist_modenv_detect_cycle(int (*fptr)( */ int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)); +/** + * Check function pointer whitelist for module deinit call values. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_mod_deinit(int (*fptr)(struct module_env* env, int id)); + /** * Check function pointer whitelist for module setup call values. * From ff653a7ef83e1ed147f21522a21ec9d1dbf6bbf5 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Jul 2024 16:10:07 +0200 Subject: [PATCH 05/11] Call module init init again, and new function startup and destartup. NULL can be used if the function is not used. Open shared ports during reload. Deinit is called during reload. --- cachedb/cachedb.c | 6 +-- cachedb/cachedb.h | 4 +- daemon/daemon.c | 16 ++++---- daemon/daemon.h | 8 ++++ daemon/unbound.c | 8 +++- dns64/dns64.c | 8 ++-- dns64/dns64.h | 4 +- dynlibmod/dynlibmod.c | 4 +- edns-subnet/subnetmod.c | 9 ++--- edns-subnet/subnetmod.h | 4 +- ipsecmod/ipsecmod.c | 9 ++--- ipsecmod/ipsecmod.h | 4 +- ipset/ipset.c | 13 +++---- ipset/ipset.h | 10 ++--- iterator/iterator.c | 8 ++-- iterator/iterator.h | 4 +- libunbound/context.c | 12 ++++-- libunbound/context.h | 3 ++ libunbound/libunbound.c | 8 ++-- pythonmod/pythonmod.c | 4 +- respip/respip.c | 6 +-- respip/respip.h | 4 +- services/modstack.c | 44 +++++++++++---------- services/modstack.h | 25 ++++++------ smallapp/unbound-checkconf.c | 11 +++--- testcode/unitzonemd.c | 11 ++++-- util/fptr_wlist.c | 75 ++++++++++++++++++------------------ util/fptr_wlist.h | 10 ++--- util/module.c | 5 --- util/module.h | 47 +++++++++++----------- validator/validator.c | 8 ++-- validator/validator.h | 4 +- 32 files changed, 209 insertions(+), 187 deletions(-) diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index d610c4f19..aca68d7ed 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -241,7 +241,7 @@ cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg) } int -cachedb_setup(struct module_env* env, int id) +cachedb_init(struct module_env* env, int id) { struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1, sizeof(struct cachedb_env)); @@ -271,7 +271,7 @@ cachedb_setup(struct module_env* env, int id) } void -cachedb_desetup(struct module_env* env, int id) +cachedb_deinit(struct module_env* env, int id) { struct cachedb_env* cachedb_env; if(!env || !env->modinfo[id]) @@ -983,7 +983,7 @@ cachedb_get_mem(struct module_env* env, int id) */ static struct module_func_block cachedb_block = { "cachedb", - &module_dummy_init, &module_dummy_init, &cachedb_setup, &cachedb_desetup, &cachedb_operate, + &cachedb_init, &cachedb_deinit, NULL, NULL, &cachedb_operate, &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem }; diff --git a/cachedb/cachedb.h b/cachedb/cachedb.h index 3d3e101d7..482c5db6c 100644 --- a/cachedb/cachedb.h +++ b/cachedb/cachedb.h @@ -91,9 +91,9 @@ struct cachedb_backend { #define CACHEDB_HASHSIZE 256 /* bit hash */ /** Init the cachedb module */ -int cachedb_setup(struct module_env* env, int id); +int cachedb_init(struct module_env* env, int id); /** Deinit the cachedb module */ -void cachedb_desetup(struct module_env* env, int id); +void cachedb_deinit(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void cachedb_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/daemon/daemon.c b/daemon/daemon.c index 15102b9d2..eb933cc93 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -447,15 +447,12 @@ daemon_open_shared_ports(struct daemon* daemon) int daemon_privileged(struct daemon* daemon) { - if(!daemon_open_shared_ports(daemon)) - fatal_exit("could not open ports"); - daemon->env->cfg = daemon->cfg; daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; - if(!modstack_init(&daemon->mods, daemon->cfg->module_conf, + if(!modstack_startup(&daemon->mods, daemon->cfg->module_conf, daemon->env)) { - fatal_exit("failed to init modules"); + fatal_exit("failed to startup modules"); } return 1; } @@ -470,7 +467,9 @@ static void daemon_setup_modules(struct daemon* daemon) daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; daemon->env->need_to_validate = 0; /* set by module init below */ - if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, + if(daemon->mods.num != 0) + modstack_deinit(&daemon->mods, daemon->env); + if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf, daemon->env)) { fatal_exit("failed to setup modules"); } @@ -877,7 +876,7 @@ daemon_cleanup(struct daemon* daemon) daemon->views = NULL; if(daemon->env->auth_zones) auth_zones_cleanup(daemon->env->auth_zones); - /* key cache is cleared by module desetup during next daemon_fork() */ + /* key cache is cleared by module deinit during next daemon_fork() */ daemon_remote_clear(daemon->rc); for(i=0; inum; i++) worker_delete(daemon->workers[i]); @@ -907,7 +906,8 @@ daemon_delete(struct daemon* daemon) size_t i; if(!daemon) return; - modstack_desetup(&daemon->mods, daemon->env); + modstack_deinit(&daemon->mods, daemon->env); + modstack_destartup(&daemon->mods, daemon->env); daemon_remote_delete(daemon->rc); for(i = 0; i < daemon->num_ports; i++) listening_ports_free(daemon->ports[i]); diff --git a/daemon/daemon.h b/daemon/daemon.h index 0f6c260a8..200149745 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -154,6 +154,14 @@ struct daemon { */ struct daemon* daemon_init(void); +/** + * Open shared listening ports (if needed). + * The cfg member pointer must have been set for the daemon. + * @param daemon: the daemon. + * @return: false on error. + */ +int daemon_open_shared_ports(struct daemon* daemon); + /** * Do daemon setup that needs privileges * like opening privileged ports or opening device files. diff --git a/daemon/unbound.c b/daemon/unbound.c index 3644709d0..306fe6caf 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -473,7 +473,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, #endif #ifdef HAVE_GETPWNAM struct passwd *pwd = NULL; +#endif + if(!daemon_privileged(daemon)) + fatal_exit("could not do privileged setup"); +#ifdef HAVE_GETPWNAM if(cfg->username && cfg->username[0]) { if((pwd = getpwnam(cfg->username)) == NULL) fatal_exit("user '%s' does not exist.", cfg->username); @@ -717,9 +721,9 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi config_lookup_uid(cfg); /* prepare */ + if(!daemon_open_shared_ports(daemon)) + fatal_exit("could not open ports"); if(!done_setup) { - if(!daemon_privileged(daemon)) - fatal_exit("could not do privileged setup"); perform_setup(daemon, cfg, debug_mode, &cfgfile, need_pidfile); done_setup = 1; } else { diff --git a/dns64/dns64.c b/dns64/dns64.c index 3f2994fa6..d34eafb9f 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -399,7 +399,7 @@ dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg) * \param id This instance's ID number. */ int -dns64_setup(struct module_env* env, int id) +dns64_init(struct module_env* env, int id) { struct dns64_env* dns64_env = (struct dns64_env*)calloc(1, sizeof(struct dns64_env)); @@ -433,7 +433,7 @@ free_ignore_aaaa_node(rbnode_type* node, void* ATTR_UNUSED(arg)) * \param id This instance's ID number. */ void -dns64_desetup(struct module_env* env, int id) +dns64_deinit(struct module_env* env, int id) { struct dns64_env* dns64_env; if (!env) @@ -1044,8 +1044,8 @@ dns64_get_mem(struct module_env* env, int id) */ static struct module_func_block dns64_block = { "dns64", - &module_dummy_init, &module_dummy_init, &dns64_setup, &dns64_desetup, - &dns64_operate, &dns64_inform_super, &dns64_clear, &dns64_get_mem + &dns64_init, &dns64_deinit, NULL, NULL, &dns64_operate, + &dns64_inform_super, &dns64_clear, &dns64_get_mem }; /** diff --git a/dns64/dns64.h b/dns64/dns64.h index 532a5bed3..2f0c01a22 100644 --- a/dns64/dns64.h +++ b/dns64/dns64.h @@ -50,10 +50,10 @@ struct module_func_block *dns64_get_funcblock(void); /** dns64 init */ -int dns64_setup(struct module_env* env, int id); +int dns64_init(struct module_env* env, int id); /** dns64 deinit */ -void dns64_desetup(struct module_env* env, int id); +void dns64_deinit(struct module_env* env, int id); /** dns64 operate on a query */ void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/dynlibmod/dynlibmod.c b/dynlibmod/dynlibmod.c index 1e040a30e..06c4f08c1 100644 --- a/dynlibmod/dynlibmod.c +++ b/dynlibmod/dynlibmod.c @@ -297,8 +297,8 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type */ static struct module_func_block dynlibmod_block = { "dynlib", - &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super, - &dynlibmod_clear, &dynlibmod_get_mem + &dynlibmod_init, &dynlibmod_deinit, NULL, NULL, &dynlibmod_operate, + &dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem }; struct module_func_block* dynlibmod_get_funcblock(void) diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index 61672be59..8e6db02e7 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -206,7 +206,7 @@ subnet_markdel(void* key) } int -subnetmod_setup(struct module_env *env, int id) +subnetmod_init(struct module_env *env, int id) { struct subnet_env *sn_env = (struct subnet_env*)calloc(1, sizeof(struct subnet_env)); @@ -275,7 +275,7 @@ subnetmod_setup(struct module_env *env, int id) } void -subnetmod_desetup(struct module_env *env, int id) +subnetmod_deinit(struct module_env *env, int id) { struct subnet_env *sn_env; if(!env || !env->modinfo[id]) @@ -996,9 +996,8 @@ subnetmod_get_mem(struct module_env *env, int id) */ static struct module_func_block subnetmod_block = { "subnetcache", - &module_dummy_init, &module_dummy_init, &subnetmod_setup, - &subnetmod_desetup, &subnetmod_operate, &subnetmod_inform_super, - &subnetmod_clear, &subnetmod_get_mem + &subnetmod_init, &subnetmod_deinit, NULL, NULL, &subnetmod_operate, + &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem }; struct module_func_block* diff --git a/edns-subnet/subnetmod.h b/edns-subnet/subnetmod.h index 8999aa632..1ff8a23ec 100644 --- a/edns-subnet/subnetmod.h +++ b/edns-subnet/subnetmod.h @@ -114,10 +114,10 @@ size_t msg_cache_sizefunc(void* k, void* d); struct module_func_block* subnetmod_get_funcblock(void); /** subnet module init */ -int subnetmod_setup(struct module_env* env, int id); +int subnetmod_init(struct module_env* env, int id); /** subnet module deinit */ -void subnetmod_desetup(struct module_env* env, int id); +void subnetmod_deinit(struct module_env* env, int id); /** subnet module operate on a query */ void subnetmod_operate(struct module_qstate* qstate, enum module_ev event, diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c index 83f91702b..137e22c33 100644 --- a/ipsecmod/ipsecmod.c +++ b/ipsecmod/ipsecmod.c @@ -67,7 +67,7 @@ ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg) } int -ipsecmod_setup(struct module_env* env, int id) +ipsecmod_init(struct module_env* env, int id) { struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1, sizeof(struct ipsecmod_env)); @@ -85,7 +85,7 @@ ipsecmod_setup(struct module_env* env, int id) } void -ipsecmod_desetup(struct module_env* env, int id) +ipsecmod_deinit(struct module_env* env, int id) { struct ipsecmod_env* ipsecmod_env; if(!env || !env->modinfo[id]) @@ -615,9 +615,8 @@ ipsecmod_get_mem(struct module_env* env, int id) */ static struct module_func_block ipsecmod_block = { "ipsecmod", - &module_dummy_init, &module_dummy_init, &ipsecmod_setup, - &ipsecmod_desetup, &ipsecmod_operate, &ipsecmod_inform_super, - &ipsecmod_clear, &ipsecmod_get_mem + &ipsecmod_init, &ipsecmod_deinit, NULL, NULL, &ipsecmod_operate, + &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem }; struct module_func_block* diff --git a/ipsecmod/ipsecmod.h b/ipsecmod/ipsecmod.h index 9e77208c4..272f473c2 100644 --- a/ipsecmod/ipsecmod.h +++ b/ipsecmod/ipsecmod.h @@ -74,9 +74,9 @@ struct ipsecmod_qstate { }; /** Init the ipsecmod module */ -int ipsecmod_setup(struct module_env* env, int id); +int ipsecmod_init(struct module_env* env, int id); /** Deinit the ipsecmod module */ -void ipsecmod_desetup(struct module_env* env, int id); +void ipsecmod_deinit(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/ipset/ipset.c b/ipset/ipset.c index f7cf2082e..9d1a8aa43 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -320,10 +320,10 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, return 0; } -int ipset_init(struct module_env* env, int id) { +int ipset_startup(struct module_env* env, int id) { struct ipset_env *ipset_env; - ipset_env = (struct ipset_env *)malloc(sizeof(struct ipset_env)); + ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env)); if (!ipset_env) { log_err("malloc failure"); return 0; @@ -343,17 +343,16 @@ int ipset_init(struct module_env* env, int id) { return 1; } -int ipset_deinit(struct module_env* env, int id) { +void ipset_destartup(struct module_env* env, int id) { struct ipset_env *ipset_env = env->modinfo[id]; #ifdef HAVE_NET_PFVAR_H close((filter_dev)ipset_env->dev); #endif free(ipset_env); env->modinfo[id] = NULL; - return 1; } -int ipset_setup(struct module_env* env, int id) { +int ipset_init(struct module_env* env, int id) { struct ipset_env *ipset_env = env->modinfo[id]; ipset_env->name_v4 = env->cfg->ipset_name_v4; @@ -370,7 +369,7 @@ int ipset_setup(struct module_env* env, int id) { return 1; } -void ipset_desetup(struct module_env *env, int id) { +void ipset_deinit(struct module_env *env, int id) { filter_dev dev; struct ipset_env *ipset_env; @@ -497,7 +496,7 @@ size_t ipset_get_mem(struct module_env *env, int id) { */ static struct module_func_block ipset_block = { "ipset", - &ipset_init, &ipset_deinit, &ipset_setup, &ipset_desetup, + &ipset_init, &ipset_deinit, &ipset_startup, &ipset_destartup, &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem }; diff --git a/ipset/ipset.h b/ipset/ipset.h index 66a4378b6..195c7db93 100644 --- a/ipset/ipset.h +++ b/ipset/ipset.h @@ -50,14 +50,14 @@ struct ipset_qstate { int dummy; }; +/** Startup the ipset module */ +int ipset_startup(struct module_env* env, int id); +/** Destartup the ipset module */ +void ipset_destartup(struct module_env* env, int id); /** Init the ipset module */ int ipset_init(struct module_env* env, int id); /** Deinit the ipset module */ -int ipset_deinit(struct module_env* env, int id); -/** Setup the ipset module */ -int ipset_setup(struct module_env* env, int id); -/** Desetup the ipset module */ -void ipset_desetup(struct module_env* env, int id); +void ipset_deinit(struct module_env* env, int id); /** Operate on an event on a query (in qstate). */ void ipset_operate(struct module_qstate* qstate, enum module_ev event, int id, struct outbound_entry* outbound); diff --git a/iterator/iterator.c b/iterator/iterator.c index 5a9729ff0..c99d9504a 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -80,7 +80,7 @@ int BLACKLIST_PENALTY = (120000*4); static void target_count_increase_nx(struct iter_qstate* iq, int num); int -iter_setup(struct module_env* env, int id) +iter_init(struct module_env* env, int id) { struct iter_env* iter_env = (struct iter_env*)calloc(1, sizeof(struct iter_env)); @@ -114,7 +114,7 @@ caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d)) } void -iter_desetup(struct module_env* env, int id) +iter_deinit(struct module_env* env, int id) { struct iter_env* iter_env; if(!env || !env->modinfo[id]) @@ -4489,8 +4489,8 @@ iter_get_mem(struct module_env* env, int id) */ static struct module_func_block iter_block = { "iterator", - &module_dummy_init, &module_dummy_init, &iter_setup, &iter_desetup, - &iter_operate, &iter_inform_super, &iter_clear, &iter_get_mem + &iter_init, &iter_deinit, NULL, NULL, &iter_operate, + &iter_inform_super, &iter_clear, &iter_get_mem }; struct module_func_block* diff --git a/iterator/iterator.h b/iterator/iterator.h index ec093014e..e253f3f7e 100644 --- a/iterator/iterator.h +++ b/iterator/iterator.h @@ -499,10 +499,10 @@ const char* iter_state_to_string(enum iter_state state); int iter_state_is_responsestate(enum iter_state s); /** iterator init */ -int iter_setup(struct module_env* env, int id); +int iter_init(struct module_env* env, int id); /** iterator deinit */ -void iter_desetup(struct module_env* env, int id); +void iter_deinit(struct module_env* env, int id); /** iterator operate on a query */ void iter_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/libunbound/context.c b/libunbound/context.c index 51f4474bb..f55aeb666 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -56,6 +56,9 @@ #include "iterator/iter_fwd.h" #include "iterator/iter_hints.h" +/** If the modules have started, once. */ +int modstack_started = 0; + int context_finalize(struct ub_ctx* ctx) { @@ -75,9 +78,12 @@ context_finalize(struct ub_ctx* ctx) ctx->pipe_pid = getpid(); cfg_apply_local_port_policy(cfg, 65536); config_apply(cfg); - if(!modstack_init(&ctx->mods, cfg->module_conf, ctx->env)) - return UB_INITFAIL; - if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) + if(!modstack_started) { + modstack_started = 1; + if(!modstack_startup(&ctx->mods, cfg->module_conf, ctx->env)) + return UB_INITFAIL; + } + if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; listen_setup_locks(); log_edns_known_options(VERB_ALGO, ctx->env); diff --git a/libunbound/context.h b/libunbound/context.h index c0fc80e57..0a48db72d 100644 --- a/libunbound/context.h +++ b/libunbound/context.h @@ -337,4 +337,7 @@ struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, uint8_t* p, uint32_t len); +/** If the modules have started. */ +extern int modstack_started; + #endif /* LIBUNBOUND_CONTEXT_H */ diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 8a5e0188f..4b6e60c08 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -188,7 +188,8 @@ ub_ctx_create(void) int e = errno; ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); + modstack_deinit(&ctx->mods, ctx->env); + modstack_destartup(&ctx->mods, ctx->env); listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); @@ -202,7 +203,8 @@ ub_ctx_create(void) tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); + modstack_deinit(&ctx->mods, ctx->env); + modstack_destartup(&ctx->mods, ctx->env); listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); @@ -360,8 +362,8 @@ ub_ctx_delete(struct ub_ctx* ctx) } libworker_delete_event(ctx->event_worker); - modstack_desetup(&ctx->mods, ctx->env); modstack_deinit(&ctx->mods, ctx->env); + modstack_destartup(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { na = a->super; diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index 6bc6752e2..f397012ac 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -777,8 +777,8 @@ size_t pythonmod_get_mem(struct module_env* env, int id) */ static struct module_func_block pythonmod_block = { "python", - &module_dummy_init, &module_dummy_init, &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, - &pythonmod_clear, &pythonmod_get_mem + &pythonmod_init, &pythonmod_deinit, NULL, NULL, &pythonmod_operate, + &pythonmod_inform_super, &pythonmod_clear, &pythonmod_get_mem }; struct module_func_block* pythonmod_get_funcblock(void) diff --git a/respip/respip.c b/respip/respip.c index 0dc6b626a..cfc6a4908 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -548,7 +548,7 @@ respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region } int -respip_setup(struct module_env* env, int id) +respip_init(struct module_env* env, int id) { (void)env; (void)id; @@ -556,7 +556,7 @@ respip_setup(struct module_env* env, int id) } void -respip_desetup(struct module_env* env, int id) +respip_deinit(struct module_env* env, int id) { (void)env; (void)id; @@ -1259,7 +1259,7 @@ respip_get_mem(struct module_env* env, int id) */ static struct module_func_block respip_block = { "respip", - &module_dummy_init, &module_dummy_init, &respip_setup, &respip_desetup, &respip_operate, + &respip_init, &respip_deinit, NULL, NULL, &respip_operate, &respip_inform_super, &respip_clear, &respip_get_mem }; diff --git a/respip/respip.h b/respip/respip.h index 3ebda5ce7..e4ab5cc9c 100644 --- a/respip/respip.h +++ b/respip/respip.h @@ -195,10 +195,10 @@ int respip_rewrite_reply(const struct query_info* qinfo, struct module_func_block* respip_get_funcblock(void); /** response-ip init */ -int respip_setup(struct module_env* env, int id); +int respip_init(struct module_env* env, int id); /** response-ip deinit */ -void respip_desetup(struct module_env* env, int id); +void respip_deinit(struct module_env* env, int id); /** response-ip operate on a query */ void respip_operate(struct module_qstate* qstate, enum module_ev event, int id, diff --git a/services/modstack.c b/services/modstack.c index 77e33263c..85f0afc5d 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -216,7 +216,7 @@ module_func_block* module_factory(const char** str) } int -modstack_init(struct module_stack* stack, const char* module_conf, +modstack_startup(struct module_stack* stack, const char* module_conf, struct module_env* env) { int i; @@ -227,11 +227,13 @@ modstack_init(struct module_stack* stack, const char* module_conf, return 0; } for(i=0; inum; i++) { - verbose(VERB_OPS, "init module %d: %s", + if(stack->mod[i]->startup == NULL) + continue; + verbose(VERB_OPS, "startup module %d: %s", i, stack->mod[i]->name); - fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); - if(!(*stack->mod[i]->init)(env, i)) { - log_err("module init for module %s failed", + fptr_ok(fptr_whitelist_mod_startup(stack->mod[i]->startup)); + if(!(*stack->mod[i]->startup)(env, i)) { + log_err("module startup for module %s failed", stack->mod[i]->name); return 0; } @@ -240,7 +242,7 @@ modstack_init(struct module_stack* stack, const char* module_conf, } int -modstack_setup(struct module_stack* stack, const char* module_conf, +modstack_call_init(struct module_stack* stack, const char* module_conf, struct module_env* env) { int i; @@ -254,11 +256,11 @@ modstack_setup(struct module_stack* stack, const char* module_conf, return 0; } module_conf += strlen(stack->mod[i]->name); - verbose(VERB_OPS, "setup module %d: %s", + verbose(VERB_OPS, "init module %d: %s", i, stack->mod[i]->name); - fptr_ok(fptr_whitelist_mod_setup(stack->mod[i]->setup)); - if(!(*stack->mod[i]->setup)(env, i)) { - log_err("module setup for module %s failed", + fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); + if(!(*stack->mod[i]->init)(env, i)) { + log_err("module init for module %s failed", stack->mod[i]->name); return 0; } @@ -266,16 +268,6 @@ modstack_setup(struct module_stack* stack, const char* module_conf, return 1; } -void -modstack_desetup(struct module_stack* stack, struct module_env* env) -{ - int i; - for(i=0; inum; i++) { - fptr_ok(fptr_whitelist_mod_desetup(stack->mod[i]->desetup)); - (*stack->mod[i]->desetup)(env, i); - } -} - void modstack_deinit(struct module_stack* stack, struct module_env* env) { @@ -284,6 +276,18 @@ modstack_deinit(struct module_stack* stack, struct module_env* env) fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); (*stack->mod[i]->deinit)(env, i); } +} + +void +modstack_destartup(struct module_stack* stack, struct module_env* env) +{ + int i; + for(i=0; inum; i++) { + if(stack->mod[i]->destartup == NULL) + continue; + fptr_ok(fptr_whitelist_mod_destartup(stack->mod[i]->destartup)); + (*stack->mod[i]->destartup)(env, i); + } stack->num = 0; free(stack->mod); stack->mod = NULL; diff --git a/services/modstack.h b/services/modstack.h index 3e79595ed..3f01be619 100644 --- a/services/modstack.h +++ b/services/modstack.h @@ -60,10 +60,9 @@ struct module_stack { * @param module_conf: string what modules to initialize * @param env: module environment which is inited by the modules. * environment should have a superalloc, cfg, - * env.need_to_validate is set by the modules. * @return on false a module init failed. */ -int modstack_init(struct module_stack* stack, const char* module_conf, +int modstack_startup(struct module_stack* stack, const char* module_conf, struct module_env* env); /** @@ -89,32 +88,32 @@ struct module_func_block* module_factory(const char** str); const char** module_list_avail(void); /** - * Setup modules. Calls module_setup(). + * Init modules. Calls module_init(). * @param stack: It is modstack_setupped(). * @param module_conf: module ordering to check against the ordering in stack. - * fails on changed ordering. + * fails on changed ordering. * @param env: module environment which is inited by the modules. * environment should have a superalloc, cfg, * env.need_to_validate is set by the modules. * @return on false a module init failed. */ -int modstack_setup(struct module_stack* stack, const char* module_conf, +int modstack_call_init(struct module_stack* stack, const char* module_conf, struct module_env* env); /** - * Desetup the modules - * @param stack: made empty. - * @param env: module env for module deinit() calls. - */ -void modstack_desetup(struct module_stack* stack, struct module_env* env); - -/** - * Deinit the modules, deinit, delete. + * Deinint the modules * @param stack: made empty. * @param env: module env for module deinit() calls. */ void modstack_deinit(struct module_stack* stack, struct module_env* env); +/** + * Destartup the modules, close, delete. + * @param stack: made empty. + * @param env: module env for module destartup() calls. + */ +void modstack_destartup(struct module_stack* stack, struct module_env* env); + /** * Find index of module by name. * @param stack: to look in diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index 6271d10cf..6cc5285ec 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -140,12 +140,13 @@ check_mod(struct config_file* cfg, struct module_func_block* fb) fatal_exit("out of memory"); if(!edns_known_options_init(&env)) fatal_exit("out of memory"); - if(!(*fb->setup)(&env, 0)) - fatal_exit("bad config for %s module", fb->name); - if(!(*fb->setup)(&env, 0)) - fatal_exit("bad config for %s module", fb->name); - (*fb->desetup)(&env, 0); + if(fb->startup && !(*fb->startup)(&env, 0)) + fatal_exit("bad config during startup for %s module", fb->name); + if(!(*fb->init)(&env, 0)) + fatal_exit("bad config during init for %s module", fb->name); (*fb->deinit)(&env, 0); + if(fb->destartup) + (*fb->destartup)(&env, 0); sldns_buffer_free(env.scratch_buffer); regional_destroy(env.scratch); edns_known_options_delete(&env); diff --git a/testcode/unitzonemd.c b/testcode/unitzonemd.c index 23c9f7010..5336a1224 100644 --- a/testcode/unitzonemd.c +++ b/testcode/unitzonemd.c @@ -287,9 +287,11 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, env.auth_zones = auth_zones_create(); if(!env.auth_zones) fatal_exit("out of memory"); - modstack_init(&mods); - if(!modstack_setup(&mods, env.cfg->module_conf, &env)) - fatal_exit("could not modstack_setup"); + memset(&mods, 0, sizeof(mods)); + if(!modstack_startup(&mods, env.cfg->module_conf, &env)) + fatal_exit("could not modstack_startup"); + if(!modstack_call_init(&mods, env.cfg->module_conf, &env)) + fatal_exit("could not modstack_call_init"); env.mesh = mesh_create(&mods, &env); if(!env.mesh) fatal_exit("out of memory"); @@ -327,7 +329,8 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, /* desetup test harness */ mesh_delete(env.mesh); - modstack_desetup(&mods, &env); + modstack_deinit(&mods, &env); + modstack_destartup(&mods, &env); auth_zones_delete(env.auth_zones); anchors_delete(env.anchors); config_delete(env.cfg); diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index d24941321..b13988835 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -395,30 +395,10 @@ fptr_whitelist_modenv_detect_cycle(int (*fptr)( int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)) { - if(fptr == &module_dummy_init) return 1; -#ifdef USE_IPSET - else if(fptr == &ipset_init) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_deinit(int (*fptr)(struct module_env* env, int id)) -{ - if(fptr == &module_dummy_init) return 1; -#ifdef USE_IPSET - else if(fptr == &ipset_deinit) return 1; -#endif - return 0; -} - -int -fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)) -{ - if(fptr == &iter_setup) return 1; - else if(fptr == &val_setup) return 1; - else if(fptr == &dns64_setup) return 1; - else if(fptr == &respip_setup) return 1; + if(fptr == &iter_init) return 1; + else if(fptr == &val_init) return 1; + else if(fptr == &dns64_init) return 1; + else if(fptr == &respip_init) return 1; #ifdef WITH_PYTHONMODULE else if(fptr == &pythonmod_init) return 1; #endif @@ -426,27 +406,28 @@ fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)) else if(fptr == &dynlibmod_init) return 1; #endif #ifdef USE_CACHEDB - else if(fptr == &cachedb_setup) return 1; + else if(fptr == &cachedb_init) return 1; #endif #ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_setup) return 1; + else if(fptr == &ipsecmod_init) return 1; #endif #ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_setup) return 1; + else if(fptr == &subnetmod_init) return 1; #endif #ifdef USE_IPSET - else if(fptr == &ipset_setup) return 1; + else if(fptr == &ipset_init) return 1; #endif return 0; + } -int -fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)) +int +fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)) { - if(fptr == &iter_desetup) return 1; - else if(fptr == &val_desetup) return 1; - else if(fptr == &dns64_desetup) return 1; - else if(fptr == &respip_desetup) return 1; + if(fptr == &iter_deinit) return 1; + else if(fptr == &val_deinit) return 1; + else if(fptr == &dns64_deinit) return 1; + else if(fptr == &respip_deinit) return 1; #ifdef WITH_PYTHONMODULE else if(fptr == &pythonmod_deinit) return 1; #endif @@ -454,16 +435,34 @@ fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)) else if(fptr == &dynlibmod_deinit) return 1; #endif #ifdef USE_CACHEDB - else if(fptr == &cachedb_desetup) return 1; + else if(fptr == &cachedb_deinit) return 1; #endif #ifdef USE_IPSECMOD - else if(fptr == &ipsecmod_desetup) return 1; + else if(fptr == &ipsecmod_deinit) return 1; #endif #ifdef CLIENT_SUBNET - else if(fptr == &subnetmod_desetup) return 1; + else if(fptr == &subnetmod_deinit) return 1; #endif #ifdef USE_IPSET - else if(fptr == &ipset_desetup) return 1; + else if(fptr == &ipset_deinit) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_startup(int (*fptr)(struct module_env* env, int id)) +{ +#ifdef USE_IPSET + if(fptr == &ipset_startup) return 1; +#endif + return 0; +} + +int +fptr_whitelist_mod_destartup(void (*fptr)(struct module_env* env, int id)) +{ +#ifdef USE_IPSET + if(fptr == &ipset_destartup) return 1; #endif return 0; } diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index cf70c7066..fb2475cce 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -276,23 +276,23 @@ int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id)); * @param fptr: function pointer to check. * @return false if not in whitelist. */ -int fptr_whitelist_mod_deinit(int (*fptr)(struct module_env* env, int id)); +int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id)); /** - * Check function pointer whitelist for module setup call values. + * Check function pointer whitelist for module startup call values. * * @param fptr: function pointer to check. * @return false if not in whitelist. */ -int fptr_whitelist_mod_setup(int (*fptr)(struct module_env* env, int id)); +int fptr_whitelist_mod_startup(int (*fptr)(struct module_env* env, int id)); /** - * Check function pointer whitelist for module desetup call values. + * Check function pointer whitelist for module destartup call values. * * @param fptr: function pointer to check. * @return false if not in whitelist. */ -int fptr_whitelist_mod_desetup(void (*fptr)(struct module_env* env, int id)); +int fptr_whitelist_mod_destartup(void (*fptr)(struct module_env* env, int id)); /** * Check function pointer whitelist for module operate call values. diff --git a/util/module.c b/util/module.c index 1f0cdbef3..90a155b5e 100644 --- a/util/module.c +++ b/util/module.c @@ -415,8 +415,3 @@ copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id), super->was_ratelimited = qstate->was_ratelimited; } } - -int module_dummy_init(struct module_env* env, int id) -{ - return 1; -} diff --git a/util/module.h b/util/module.h index b140fd2bb..702372cb8 100644 --- a/util/module.h +++ b/util/module.h @@ -713,39 +713,42 @@ struct module_func_block { const char* name; /** - * initialise the module. This is called only once at startup. - * Privileged operations like opening device files may be done here. - * @param id: module id number. - * return: 0 on error - */ - int (*init)(struct module_env* env, int id); - - /** - * deinitialise the module. This is called only once before shutdown to - * free resources allocated during init(). - * Closing privileged ports or files must be done here. - * @param id: module id number. - * return: 0 on error - */ - int (*deinit)(struct module_env* env, int id); - - /** - * setup the module. Called when restarting or reloading the + * Initialise the module. Called when restarting or reloading the * daemon. * This is the place to apply settings from the config file. * @param env: module environment. * @param id: module id number. * return: 0 on error */ - int (*setup)(struct module_env* env, int id); + int (*init)(struct module_env* env, int id); /** - * de-setup, undo stuff done during setup(). + * Deinitialise the module, undo stuff done during init(). * Called before reloading the daemon. * @param env: module environment. * @param id: module id number. */ - void (*desetup)(struct module_env* env, int id); + void (*deinit)(struct module_env* env, int id); + + /** + * Set up the module for start. This is called only once at startup. + * Privileged operations like opening device files may be done here. + * The function ptr can be NULL, if it is not used. + * @param env: module environment. + * @param id: module id number. + * return: 0 on error + */ + int (*startup)(struct module_env* env, int id); + + /** + * Close down the module for stop. This is called only once before + * shutdown to free resources allocated during startup(). + * Closing privileged ports or files must be done here. + * The function ptr can be NULL, if it is not used. + * @param env: module environment. + * @param id: module id number. + */ + void (*destartup)(struct module_env* env, int id); /** * accept a new query, or work further on existing query. @@ -983,6 +986,4 @@ void log_edns_known_options(enum verbosity_value level, void copy_state_to_super(struct module_qstate* qstate, int id, struct module_qstate* super); -int module_dummy_init(struct module_env* env, int id); - #endif /* UTIL_MODULE_H */ diff --git a/validator/validator.c b/validator/validator.c index 2a3be7e40..3f62733c7 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -185,7 +185,7 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env, void ecdsa_evp_workaround_init(void); #endif int -val_setup(struct module_env* env, int id) +val_init(struct module_env* env, int id) { struct val_env* val_env = (struct val_env*)calloc(1, sizeof(struct val_env)); @@ -221,7 +221,7 @@ val_setup(struct module_env* env, int id) } void -val_desetup(struct module_env* env, int id) +val_deinit(struct module_env* env, int id) { struct val_env* val_env; if(!env || !env->modinfo[id]) @@ -3344,8 +3344,8 @@ val_get_mem(struct module_env* env, int id) */ static struct module_func_block val_block = { "validator", - &module_dummy_init, &module_dummy_init, &val_setup, &val_desetup, - &val_operate, &val_inform_super, &val_clear, &val_get_mem + &val_init, &val_deinit, NULL, NULL, &val_operate, &val_inform_super, + &val_clear, &val_get_mem }; struct module_func_block* diff --git a/validator/validator.h b/validator/validator.h index 844dfe7be..72f44b16e 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -246,10 +246,10 @@ struct module_func_block* val_get_funcblock(void); const char* val_state_to_string(enum val_state state); /** validator init */ -int val_setup(struct module_env* env, int id); +int val_init(struct module_env* env, int id); /** validator deinit */ -void val_desetup(struct module_env* env, int id); +void val_deinit(struct module_env* env, int id); /** validator operate on a query */ void val_operate(struct module_qstate* qstate, enum module_ev event, int id, From 2279cde8f7a4fcb8f2fbea624a16f5713b201775 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Jul 2024 17:02:49 +0200 Subject: [PATCH 06/11] ipset-pf-support, fix to remove unused include, free at end, adjust qname for comparison. --- ipset/ipset.c | 51 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/ipset/ipset.c b/ipset/ipset.c index 9d1a8aa43..8645c78b5 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -17,8 +17,6 @@ #include "sldns/wire2str.h" #include "sldns/parseutil.h" -#include - #ifdef HAVE_NET_PFVAR_H #include #include @@ -225,7 +223,7 @@ ipset_add_rrset_data(struct ipset_env *ie, static int ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, - struct ub_packed_rrset_key *rrset, const char *qname, const int qlen, + struct ub_packed_rrset_key *rrset, const char *qname, int qlen, const char *setname, int af) { static char dname[BUFF_LEN]; @@ -243,6 +241,9 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie, if (dname[dlen - 1] == '.') { dlen--; } + if (qname[qlen - 1] == '.') { + qlen--; + } for (p = env->cfg->local_zones_ipset; p; p = p->next) { ds = NULL; @@ -344,10 +345,24 @@ int ipset_startup(struct module_env* env, int id) { } void ipset_destartup(struct module_env* env, int id) { - struct ipset_env *ipset_env = env->modinfo[id]; -#ifdef HAVE_NET_PFVAR_H - close((filter_dev)ipset_env->dev); + filter_dev dev; + struct ipset_env *ipset_env; + + if (!env || !env->modinfo[id]) { + return; + } + ipset_env = (struct ipset_env*)env->modinfo[id]; + + dev = (filter_dev)ipset_env->dev; + if (dev) { +#if HAVE_NET_PFVAR_H + close(dev); +#else + mnl_socket_close(dev); #endif + ipset_env->dev = NULL; + } + free(ipset_env); env->modinfo[id] = NULL; } @@ -369,28 +384,8 @@ int ipset_init(struct module_env* env, int id) { return 1; } -void ipset_deinit(struct module_env *env, int id) { - filter_dev dev; - struct ipset_env *ipset_env; - - if (!env || !env->modinfo[id]) { - return; - } - - ipset_env = (struct ipset_env *)env->modinfo[id]; - - dev = (filter_dev)ipset_env->dev; - if (dev) { -#if HAVE_NET_PFVAR_H - close(dev); -#else - mnl_socket_close(dev); -#endif - ipset_env->dev = NULL; - } - - free(ipset_env); - env->modinfo[id] = NULL; +void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) { + /* nothing */ } static int ipset_new(struct module_qstate* qstate, int id) { From 97ad1df34364b8265a9eff626a33166870d008f5 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Jul 2024 17:06:11 +0200 Subject: [PATCH 07/11] ipset-pf-support, fix to log error on failure to open pf. --- ipset/ipset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipset/ipset.c b/ipset/ipset.c index 8645c78b5..3cc906f32 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -57,7 +57,7 @@ static void * open_filter() { dev = open("/dev/pf", O_RDWR); if (dev == -1) { - log_err("open(\"/dev/pf\") failed"); + log_err("open(\"/dev/pf\") failed: %s", strerror(errno)); return NULL; } else From 03ac9022963a0fc401d04fa0eb0df47347d5bab9 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 1 Jul 2024 17:11:20 +0200 Subject: [PATCH 08/11] - ipset-pf-support, fix to skip unit test if no pf dev. --- testdata/ipset.tdir/ipset.pre | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/testdata/ipset.tdir/ipset.pre b/testdata/ipset.tdir/ipset.pre index 42c94fac4..7c61e6468 100644 --- a/testdata/ipset.tdir/ipset.pre +++ b/testdata/ipset.tdir/ipset.pre @@ -8,6 +8,11 @@ PRE="../.." if grep "define USE_IPSET 1" $PRE/config.h; then echo test enabled; else skip_test "test skipped"; fi +if grep "define HAVE_NET_PFVAR_H 1" $PRE/config.h; then + if test ! -f /dev/pf; then + skip_test "no /dev/pf" + fi +fi get_random_port 2 UNBOUND_PORT=$RND_PORT From 65e7253d190ba182dacc2869641e86e94292deaf Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 2 Jul 2024 09:08:27 +0200 Subject: [PATCH 09/11] ipset-pf-support, simplification of code. --- daemon/daemon.c | 8 +++----- libunbound/context.c | 12 +++--------- libunbound/context.h | 3 --- libunbound/libunbound.c | 8 ++++---- services/modstack.c | 19 ++++++++++++++----- services/modstack.h | 12 +++++++++--- testcode/unitzonemd.c | 4 ++-- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/daemon/daemon.c b/daemon/daemon.c index eb933cc93..ab3d182c3 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -259,7 +259,7 @@ daemon_init(void) tzset(); #endif daemon->need_to_exit = 0; - memset(&daemon->mods, 0, sizeof(daemon->mods)); + modstack_init(&daemon->mods); if(!(daemon->env = (struct module_env*)calloc(1, sizeof(*daemon->env)))) { free(daemon); @@ -467,9 +467,7 @@ static void daemon_setup_modules(struct daemon* daemon) daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; daemon->env->need_to_validate = 0; /* set by module init below */ - if(daemon->mods.num != 0) - modstack_deinit(&daemon->mods, daemon->env); - if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf, + if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, daemon->env)) { fatal_exit("failed to setup modules"); } @@ -906,7 +904,7 @@ daemon_delete(struct daemon* daemon) size_t i; if(!daemon) return; - modstack_deinit(&daemon->mods, daemon->env); + modstack_desetup(&daemon->mods, daemon->env); modstack_destartup(&daemon->mods, daemon->env); daemon_remote_delete(daemon->rc); for(i = 0; i < daemon->num_ports; i++) diff --git a/libunbound/context.c b/libunbound/context.c index f55aeb666..5b2d36b2d 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -56,9 +56,6 @@ #include "iterator/iter_fwd.h" #include "iterator/iter_hints.h" -/** If the modules have started, once. */ -int modstack_started = 0; - int context_finalize(struct ub_ctx* ctx) { @@ -78,12 +75,9 @@ context_finalize(struct ub_ctx* ctx) ctx->pipe_pid = getpid(); cfg_apply_local_port_policy(cfg, 65536); config_apply(cfg); - if(!modstack_started) { - modstack_started = 1; - if(!modstack_startup(&ctx->mods, cfg->module_conf, ctx->env)) - return UB_INITFAIL; - } - if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env)) + if(!modstack_startup(&ctx->mods, cfg->module_conf, ctx->env)) + return UB_INITFAIL; + if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; listen_setup_locks(); log_edns_known_options(VERB_ALGO, ctx->env); diff --git a/libunbound/context.h b/libunbound/context.h index 0a48db72d..c0fc80e57 100644 --- a/libunbound/context.h +++ b/libunbound/context.h @@ -337,7 +337,4 @@ struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, uint8_t* p, uint32_t len); -/** If the modules have started. */ -extern int modstack_started; - #endif /* LIBUNBOUND_CONTEXT_H */ diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 4b6e60c08..561e41fba 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -172,7 +172,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void) ctx->env->alloc = &ctx->superalloc; ctx->env->worker = NULL; ctx->env->need_to_validate = 0; - memset(&ctx->mods, 0, sizeof(ctx->mods)); + modstack_init(&ctx->mods); ctx->env->modstack = &ctx->mods; rbtree_init(&ctx->queries, &context_query_cmp); return ctx; @@ -188,7 +188,7 @@ ub_ctx_create(void) int e = errno; ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_deinit(&ctx->mods, ctx->env); + modstack_desetup(&ctx->mods, ctx->env); modstack_destartup(&ctx->mods, ctx->env); listen_desetup_locks(); edns_known_options_delete(ctx->env); @@ -203,7 +203,7 @@ ub_ctx_create(void) tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_deinit(&ctx->mods, ctx->env); + modstack_desetup(&ctx->mods, ctx->env); modstack_destartup(&ctx->mods, ctx->env); listen_desetup_locks(); edns_known_options_delete(ctx->env); @@ -362,7 +362,7 @@ ub_ctx_delete(struct ub_ctx* ctx) } libworker_delete_event(ctx->event_worker); - modstack_deinit(&ctx->mods, ctx->env); + modstack_desetup(&ctx->mods, ctx->env); modstack_destartup(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { diff --git a/services/modstack.c b/services/modstack.c index 85f0afc5d..f32f942c8 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -88,6 +88,13 @@ count_modules(const char* s) return num; } +void +modstack_init(struct module_stack* stack) +{ + stack->num = 0; + stack->mod = NULL; +} + int modstack_config(struct module_stack* stack, const char* module_conf) { @@ -219,8 +226,8 @@ int modstack_startup(struct module_stack* stack, const char* module_conf, struct module_env* env) { - int i; - if (stack->num != 0) + int i; + if(stack->num != 0) fatal_exit("unexpected already initialised modules"); /* fixed setup of the modules */ if(!modstack_config(stack, module_conf)) { @@ -242,11 +249,13 @@ modstack_startup(struct module_stack* stack, const char* module_conf, } int -modstack_call_init(struct module_stack* stack, const char* module_conf, +modstack_setup(struct module_stack* stack, const char* module_conf, struct module_env* env) { int i; - env->need_to_validate = 0; /* set by module setup below */ + if(stack->num != 0) + modstack_desetup(stack, env); + env->need_to_validate = 0; /* set by module init below */ for(i=0; inum; i++) { while(*module_conf && isspace(*module_conf)) module_conf++; @@ -269,7 +278,7 @@ modstack_call_init(struct module_stack* stack, const char* module_conf, } void -modstack_deinit(struct module_stack* stack, struct module_env* env) +modstack_desetup(struct module_stack* stack, struct module_env* env) { int i; for(i=0; inum; i++) { diff --git a/services/modstack.h b/services/modstack.h index 3f01be619..deb8b634b 100644 --- a/services/modstack.h +++ b/services/modstack.h @@ -54,6 +54,12 @@ struct module_stack { struct module_func_block** mod; }; +/** + * Init a stack of modules + * @param stack: initialised as empty. + */ +void modstack_init(struct module_stack* stack); + /** * Initialises modules and assignes ids. * @param stack: Expected empty, filled according to module_conf @@ -97,15 +103,15 @@ const char** module_list_avail(void); * env.need_to_validate is set by the modules. * @return on false a module init failed. */ -int modstack_call_init(struct module_stack* stack, const char* module_conf, +int modstack_setup(struct module_stack* stack, const char* module_conf, struct module_env* env); /** - * Deinint the modules + * Desetup the modules, deinit. * @param stack: made empty. * @param env: module env for module deinit() calls. */ -void modstack_deinit(struct module_stack* stack, struct module_env* env); +void modstack_desetup(struct module_stack* stack, struct module_env* env); /** * Destartup the modules, close, delete. diff --git a/testcode/unitzonemd.c b/testcode/unitzonemd.c index 5336a1224..6ae29cdc4 100644 --- a/testcode/unitzonemd.c +++ b/testcode/unitzonemd.c @@ -290,7 +290,7 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, memset(&mods, 0, sizeof(mods)); if(!modstack_startup(&mods, env.cfg->module_conf, &env)) fatal_exit("could not modstack_startup"); - if(!modstack_call_init(&mods, env.cfg->module_conf, &env)) + if(!modstack_setup(&mods, env.cfg->module_conf, &env)) fatal_exit("could not modstack_call_init"); env.mesh = mesh_create(&mods, &env); if(!env.mesh) @@ -329,7 +329,7 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, /* desetup test harness */ mesh_delete(env.mesh); - modstack_deinit(&mods, &env); + modstack_desetup(&mods, &env); modstack_destartup(&mods, &env); auth_zones_delete(env.auth_zones); anchors_delete(env.anchors); From a19009df1dac8a2b30ee74d418efc816b2f7d55e Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 3 Jul 2024 13:08:51 +0200 Subject: [PATCH 10/11] Apply suggestions from code review Co-authored-by: Yorgos Thessalonikefs --- ipset/ipset.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ipset/ipset.c b/ipset/ipset.c index 3cc906f32..d416f34fd 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -78,7 +78,7 @@ static void * open_filter() { log_err("ipset: could not bind netfilter."); return NULL; } - return dev; + return (void *)dev; } #endif @@ -282,7 +282,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg, #ifdef HAVE_NET_PFVAR_H #else if (!ie->dev) { - // retry to create mnl socket + /* retry to create mnl socket */ ie->dev = open_filter(); if (!ie->dev) { log_warn("ipset open_filter failed"); From a335e601e42ea90d0bb9a028734ab45d263efd45 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Wed, 3 Jul 2024 13:53:44 +0200 Subject: [PATCH 11/11] ipset-pf-support, move startup and destartup to the front of the module func block functions, modstack call deinit function names, and detect module change when no startup functions are needed. --- cachedb/cachedb.c | 2 +- daemon/daemon.c | 19 ++++++++++++------- daemon/daemon.h | 2 ++ dns64/dns64.c | 2 +- dynlibmod/dynlibmod.c | 2 +- edns-subnet/subnetmod.c | 2 +- ipsecmod/ipsecmod.c | 2 +- ipset/ipset.c | 2 +- iterator/iterator.c | 2 +- libunbound/context.c | 4 ++-- libunbound/libunbound.c | 15 +++++++++------ pythonmod/pythonmod.c | 2 +- respip/respip.c | 2 +- services/modstack.c | 42 +++++++++++++++++++++++++++++------------ services/modstack.h | 18 ++++++++++++------ testcode/unitzonemd.c | 9 +++++---- util/module.h | 36 +++++++++++++++++------------------ validator/validator.c | 2 +- 18 files changed, 100 insertions(+), 65 deletions(-) diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index aca68d7ed..7a07b9976 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -983,7 +983,7 @@ cachedb_get_mem(struct module_env* env, int id) */ static struct module_func_block cachedb_block = { "cachedb", - &cachedb_init, &cachedb_deinit, NULL, NULL, &cachedb_operate, + NULL, NULL, &cachedb_init, &cachedb_deinit, &cachedb_operate, &cachedb_inform_super, &cachedb_clear, &cachedb_get_mem }; diff --git a/daemon/daemon.c b/daemon/daemon.c index ab3d182c3..d81bec844 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -450,7 +450,7 @@ daemon_privileged(struct daemon* daemon) daemon->env->cfg = daemon->cfg; daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; - if(!modstack_startup(&daemon->mods, daemon->cfg->module_conf, + if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf, daemon->env)) { fatal_exit("failed to startup modules"); } @@ -466,11 +466,15 @@ static void daemon_setup_modules(struct daemon* daemon) daemon->env->cfg = daemon->cfg; daemon->env->alloc = &daemon->superalloc; daemon->env->worker = NULL; - daemon->env->need_to_validate = 0; /* set by module init below */ - if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf, - daemon->env)) { - fatal_exit("failed to setup modules"); + if(daemon->mods_inited) { + modstack_call_deinit(&daemon->mods, daemon->env); } + daemon->env->need_to_validate = 0; /* set by module init below */ + if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf, + daemon->env)) { + fatal_exit("failed to init modules"); + } + daemon->mods_inited = 1; log_edns_known_options(VERB_ALGO, daemon->env); } @@ -904,8 +908,9 @@ daemon_delete(struct daemon* daemon) size_t i; if(!daemon) return; - modstack_desetup(&daemon->mods, daemon->env); - modstack_destartup(&daemon->mods, daemon->env); + modstack_call_deinit(&daemon->mods, daemon->env); + modstack_call_destartup(&daemon->mods, daemon->env); + modstack_free(&daemon->mods); daemon_remote_delete(daemon->rc); for(i = 0; i < daemon->num_ports; i++) listening_ports_free(daemon->ports[i]); diff --git a/daemon/daemon.h b/daemon/daemon.h index 200149745..a6b6391cc 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -115,6 +115,8 @@ struct daemon { struct module_env* env; /** stack of module callbacks */ struct module_stack mods; + /** The module stack has been inited */ + int mods_inited; /** access control, which client IPs are allowed to connect */ struct acl_list* acl; /** access control, which interfaces are allowed to connect */ diff --git a/dns64/dns64.c b/dns64/dns64.c index d34eafb9f..3a43698a8 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -1044,7 +1044,7 @@ dns64_get_mem(struct module_env* env, int id) */ static struct module_func_block dns64_block = { "dns64", - &dns64_init, &dns64_deinit, NULL, NULL, &dns64_operate, + NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super, &dns64_clear, &dns64_get_mem }; diff --git a/dynlibmod/dynlibmod.c b/dynlibmod/dynlibmod.c index 06c4f08c1..c94115492 100644 --- a/dynlibmod/dynlibmod.c +++ b/dynlibmod/dynlibmod.c @@ -297,7 +297,7 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type */ static struct module_func_block dynlibmod_block = { "dynlib", - &dynlibmod_init, &dynlibmod_deinit, NULL, NULL, &dynlibmod_operate, + NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem }; diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index 8e6db02e7..ead720f34 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -996,7 +996,7 @@ subnetmod_get_mem(struct module_env *env, int id) */ static struct module_func_block subnetmod_block = { "subnetcache", - &subnetmod_init, &subnetmod_deinit, NULL, NULL, &subnetmod_operate, + NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate, &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem }; diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c index 137e22c33..76f9b1965 100644 --- a/ipsecmod/ipsecmod.c +++ b/ipsecmod/ipsecmod.c @@ -615,7 +615,7 @@ ipsecmod_get_mem(struct module_env* env, int id) */ static struct module_func_block ipsecmod_block = { "ipsecmod", - &ipsecmod_init, &ipsecmod_deinit, NULL, NULL, &ipsecmod_operate, + NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate, &ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem }; diff --git a/ipset/ipset.c b/ipset/ipset.c index d416f34fd..1ad2c09f4 100644 --- a/ipset/ipset.c +++ b/ipset/ipset.c @@ -491,7 +491,7 @@ size_t ipset_get_mem(struct module_env *env, int id) { */ static struct module_func_block ipset_block = { "ipset", - &ipset_init, &ipset_deinit, &ipset_startup, &ipset_destartup, + &ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit, &ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem }; diff --git a/iterator/iterator.c b/iterator/iterator.c index c99d9504a..cddb02717 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -4489,7 +4489,7 @@ iter_get_mem(struct module_env* env, int id) */ static struct module_func_block iter_block = { "iterator", - &iter_init, &iter_deinit, NULL, NULL, &iter_operate, + NULL, NULL, &iter_init, &iter_deinit, &iter_operate, &iter_inform_super, &iter_clear, &iter_get_mem }; diff --git a/libunbound/context.c b/libunbound/context.c index 5b2d36b2d..05f57987a 100644 --- a/libunbound/context.c +++ b/libunbound/context.c @@ -75,9 +75,9 @@ context_finalize(struct ub_ctx* ctx) ctx->pipe_pid = getpid(); cfg_apply_local_port_policy(cfg, 65536); config_apply(cfg); - if(!modstack_startup(&ctx->mods, cfg->module_conf, ctx->env)) + if(!modstack_call_startup(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; - if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) + if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; listen_setup_locks(); log_edns_known_options(VERB_ALGO, ctx->env); diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 561e41fba..9c6a3e309 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -188,8 +188,9 @@ ub_ctx_create(void) int e = errno; ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); - modstack_destartup(&ctx->mods, ctx->env); + modstack_call_deinit(&ctx->mods, ctx->env); + modstack_call_destartup(&ctx->mods, ctx->env); + modstack_free(&ctx->mods); listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); @@ -203,8 +204,9 @@ ub_ctx_create(void) tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); - modstack_desetup(&ctx->mods, ctx->env); - modstack_destartup(&ctx->mods, ctx->env); + modstack_call_deinit(&ctx->mods, ctx->env); + modstack_call_destartup(&ctx->mods, ctx->env); + modstack_free(&ctx->mods); listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); @@ -362,8 +364,9 @@ ub_ctx_delete(struct ub_ctx* ctx) } libworker_delete_event(ctx->event_worker); - modstack_desetup(&ctx->mods, ctx->env); - modstack_destartup(&ctx->mods, ctx->env); + modstack_call_deinit(&ctx->mods, ctx->env); + modstack_call_destartup(&ctx->mods, ctx->env); + modstack_free(&ctx->mods); a = ctx->alloc_list; while(a) { na = a->super; diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index f397012ac..e231ad079 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -777,7 +777,7 @@ size_t pythonmod_get_mem(struct module_env* env, int id) */ static struct module_func_block pythonmod_block = { "python", - &pythonmod_init, &pythonmod_deinit, NULL, NULL, &pythonmod_operate, + NULL, NULL, &pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super, &pythonmod_clear, &pythonmod_get_mem }; diff --git a/respip/respip.c b/respip/respip.c index cfc6a4908..db48f176e 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -1259,7 +1259,7 @@ respip_get_mem(struct module_env* env, int id) */ static struct module_func_block respip_block = { "respip", - &respip_init, &respip_deinit, NULL, NULL, &respip_operate, + NULL, NULL, &respip_init, &respip_deinit, &respip_operate, &respip_inform_super, &respip_clear, &respip_get_mem }; diff --git a/services/modstack.c b/services/modstack.c index f32f942c8..6c8af0505 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -95,6 +95,16 @@ modstack_init(struct module_stack* stack) stack->mod = NULL; } +void +modstack_free(struct module_stack* stack) +{ + if(!stack) + return; + stack->num = 0; + free(stack->mod); + stack->mod = NULL; +} + int modstack_config(struct module_stack* stack, const char* module_conf) { @@ -223,7 +233,7 @@ module_func_block* module_factory(const char** str) } int -modstack_startup(struct module_stack* stack, const char* module_conf, +modstack_call_startup(struct module_stack* stack, const char* module_conf, struct module_env* env) { int i; @@ -249,22 +259,33 @@ modstack_startup(struct module_stack* stack, const char* module_conf, } int -modstack_setup(struct module_stack* stack, const char* module_conf, +modstack_call_init(struct module_stack* stack, const char* module_conf, struct module_env* env) { - int i; - if(stack->num != 0) - modstack_desetup(stack, env); + int i, changed = 0; env->need_to_validate = 0; /* set by module init below */ for(i=0; inum; i++) { while(*module_conf && isspace(*module_conf)) module_conf++; if(strncmp(stack->mod[i]->name, module_conf, strlen(stack->mod[i]->name))) { - log_err("changed module ordering during reload not supported"); - return 0; + if(stack->mod[i]->startup || stack->mod[i]->destartup) { + log_err("changed module ordering during reload not supported, for module that needs startup"); + return 0; + } else { + changed = 1; + } } module_conf += strlen(stack->mod[i]->name); + } + if(changed) { + modstack_free(stack); + if(!modstack_config(stack, module_conf)) { + return 0; + } + } + + for(i=0; inum; i++) { verbose(VERB_OPS, "init module %d: %s", i, stack->mod[i]->name); fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); @@ -278,7 +299,7 @@ modstack_setup(struct module_stack* stack, const char* module_conf, } void -modstack_desetup(struct module_stack* stack, struct module_env* env) +modstack_call_deinit(struct module_stack* stack, struct module_env* env) { int i; for(i=0; inum; i++) { @@ -288,7 +309,7 @@ modstack_desetup(struct module_stack* stack, struct module_env* env) } void -modstack_destartup(struct module_stack* stack, struct module_env* env) +modstack_call_destartup(struct module_stack* stack, struct module_env* env) { int i; for(i=0; inum; i++) { @@ -297,9 +318,6 @@ modstack_destartup(struct module_stack* stack, struct module_env* env) fptr_ok(fptr_whitelist_mod_destartup(stack->mod[i]->destartup)); (*stack->mod[i]->destartup)(env, i); } - stack->num = 0; - free(stack->mod); - stack->mod = NULL; } int diff --git a/services/modstack.h b/services/modstack.h index deb8b634b..5674aefdd 100644 --- a/services/modstack.h +++ b/services/modstack.h @@ -61,14 +61,20 @@ struct module_stack { void modstack_init(struct module_stack* stack); /** - * Initialises modules and assignes ids. + * Free the stack of modules + * @param stack: stack that frees up memory. + */ +void modstack_free(struct module_stack* stack); + +/** + * Initialises modules and assignes ids. Calls module_startup(). * @param stack: Expected empty, filled according to module_conf * @param module_conf: string what modules to initialize * @param env: module environment which is inited by the modules. * environment should have a superalloc, cfg, * @return on false a module init failed. */ -int modstack_startup(struct module_stack* stack, const char* module_conf, +int modstack_call_startup(struct module_stack* stack, const char* module_conf, struct module_env* env); /** @@ -103,22 +109,22 @@ const char** module_list_avail(void); * env.need_to_validate is set by the modules. * @return on false a module init failed. */ -int modstack_setup(struct module_stack* stack, const char* module_conf, +int modstack_call_init(struct module_stack* stack, const char* module_conf, struct module_env* env); /** - * Desetup the modules, deinit. + * Deinit the modules. * @param stack: made empty. * @param env: module env for module deinit() calls. */ -void modstack_desetup(struct module_stack* stack, struct module_env* env); +void modstack_call_deinit(struct module_stack* stack, struct module_env* env); /** * Destartup the modules, close, delete. * @param stack: made empty. * @param env: module env for module destartup() calls. */ -void modstack_destartup(struct module_stack* stack, struct module_env* env); +void modstack_call_destartup(struct module_stack* stack, struct module_env* env); /** * Find index of module by name. diff --git a/testcode/unitzonemd.c b/testcode/unitzonemd.c index 6ae29cdc4..81d92c102 100644 --- a/testcode/unitzonemd.c +++ b/testcode/unitzonemd.c @@ -288,9 +288,9 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, if(!env.auth_zones) fatal_exit("out of memory"); memset(&mods, 0, sizeof(mods)); - if(!modstack_startup(&mods, env.cfg->module_conf, &env)) + if(!modstack_call_startup(&mods, env.cfg->module_conf, &env)) fatal_exit("could not modstack_startup"); - if(!modstack_setup(&mods, env.cfg->module_conf, &env)) + if(!modstack_call_init(&mods, env.cfg->module_conf, &env)) fatal_exit("could not modstack_call_init"); env.mesh = mesh_create(&mods, &env); if(!env.mesh) @@ -329,8 +329,9 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, /* desetup test harness */ mesh_delete(env.mesh); - modstack_desetup(&mods, &env); - modstack_destartup(&mods, &env); + modstack_call_deinit(&mods, &env); + modstack_call_destartup(&mods, &env); + modstack_free(&mods); auth_zones_delete(env.auth_zones); anchors_delete(env.anchors); config_delete(env.cfg); diff --git a/util/module.h b/util/module.h index 702372cb8..5bdb622a2 100644 --- a/util/module.h +++ b/util/module.h @@ -712,24 +712,6 @@ struct module_func_block { /** text string name of module */ const char* name; - /** - * Initialise the module. Called when restarting or reloading the - * daemon. - * This is the place to apply settings from the config file. - * @param env: module environment. - * @param id: module id number. - * return: 0 on error - */ - int (*init)(struct module_env* env, int id); - - /** - * Deinitialise the module, undo stuff done during init(). - * Called before reloading the daemon. - * @param env: module environment. - * @param id: module id number. - */ - void (*deinit)(struct module_env* env, int id); - /** * Set up the module for start. This is called only once at startup. * Privileged operations like opening device files may be done here. @@ -750,6 +732,24 @@ struct module_func_block { */ void (*destartup)(struct module_env* env, int id); + /** + * Initialise the module. Called when restarting or reloading the + * daemon. + * This is the place to apply settings from the config file. + * @param env: module environment. + * @param id: module id number. + * return: 0 on error + */ + int (*init)(struct module_env* env, int id); + + /** + * Deinitialise the module, undo stuff done during init(). + * Called before reloading the daemon. + * @param env: module environment. + * @param id: module id number. + */ + void (*deinit)(struct module_env* env, int id); + /** * accept a new query, or work further on existing query. * Changes the qstate->ext_state to be correct on exit. diff --git a/validator/validator.c b/validator/validator.c index 3f62733c7..d02f66d1f 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -3344,7 +3344,7 @@ val_get_mem(struct module_env* env, int id) */ static struct module_func_block val_block = { "validator", - &val_init, &val_deinit, NULL, NULL, &val_operate, &val_inform_super, + NULL, NULL, &val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear, &val_get_mem };