}
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));
}
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])
*/
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
};
#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);
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);
return daemon;
}
-int
+int
daemon_open_shared_ports(struct daemon* daemon)
{
log_assert(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
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.
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;
* \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));
* \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)
*/
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
};
/**
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,
}
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));
}
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])
* 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*
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,
}
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));
}
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])
*/
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*
};
/** 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);
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));
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;
*/
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
};
};
/** 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);
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));
}
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])
*/
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*
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,
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);
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;
}
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);
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);
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;
}
int
-respip_init(struct module_env* env, int id)
+respip_setup(struct module_env* env, int id)
{
(void)env;
(void)id;
}
void
-respip_deinit(struct module_env* env, int id)
+respip_desetup(struct module_env* env, int id)
{
(void)env;
(void)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*
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,
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;
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; i<stack->num; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, stack->mod[i]->name);
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; i<stack->num; 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; i<stack->num; 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; i<stack->num; i++) {
stack->mod = NULL;
}
-int
+int
modstack_find(struct module_stack* stack, const char* name)
{
int i;
};
/**
- * 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
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.
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
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);
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;
+ 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;
#ifdef WITH_PYTHONMODULE
- else if(fptr == &pythonmod_init) return 1;
+ else if(fptr == &pythonmod_setup) return 1;
#endif
#ifdef USE_CACHEDB
- else if(fptr == &cachedb_init) return 1;
+ else if(fptr == &cachedb_setup) return 1;
#endif
#ifdef USE_IPSECMOD
- else if(fptr == &ipsecmod_init) return 1;
+ else if(fptr == &ipsecmod_setup) return 1;
#endif
#ifdef CLIENT_SUBNET
- else if(fptr == &subnetmod_init) return 1;
+ else if(fptr == &subnetmod_setup) return 1;
#endif
#ifdef USE_IPSET
- else if(fptr == &ipset_init) return 1;
+ else if(fptr == &ipset_setup) return 1;
#endif
return 0;
}
int
-fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
+fptr_whitelist_mod_desetup(void (*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;
+ 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_deinit) return 1;
+ else if(fptr == &pythonmod_desetup) return 1;
#endif
#ifdef USE_CACHEDB
- else if(fptr == &cachedb_deinit) return 1;
+ else if(fptr == &cachedb_desetup) return 1;
#endif
#ifdef USE_IPSECMOD
- else if(fptr == &ipsecmod_deinit) return 1;
+ else if(fptr == &ipsecmod_desetup) return 1;
#endif
#ifdef CLIENT_SUBNET
- else if(fptr == &subnetmod_deinit) return 1;
+ else if(fptr == &subnetmod_desetup) return 1;
#endif
#ifdef USE_IPSET
- else if(fptr == &ipset_deinit) return 1;
+ else if(fptr == &ipset_desetup) return 1;
#endif
return 0;
}
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.
super->was_ratelimited = qstate->was_ratelimited;
}
}
+
+int module_dummy_init(struct module_env* env, int id)
+{
+ return 1;
+}
/** text string name of module */
const char* name;
- /**
- * init the module. Called once for the global state.
+ /**
+ * 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
+ * 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);
+ int (*setup)(struct module_env* env, int id);
/**
- * de-init, delete, the module. Called once for the global state.
+ * 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.
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 */
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));
}
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])
*/
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*
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,