$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(CHECKCONF_OBJ)) $(LIBS)
-unbound-host: $(HOST_OBJ) lib
+unbound-host: $(HOST_OBJ) libunbound.la
$(INFO) Link $@
$Q$(LINK) -o $@ $(sort $(HOST_OBJ)) -L. -L.libs -lunbound $(LIBS)
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/localzone.h"
+#include "services/modstack.h"
#include "util/module.h"
-#include "iterator/iterator.h"
-#include "validator/validator.h"
-#include "util/fptr_wlist.h"
#include <signal.h>
/** How many quit requests happened. */
checklock_start();
ERR_load_crypto_strings();
daemon->need_to_exit = 0;
- daemon->num_modules = 0;
+ modstack_init(&daemon->mods);
if(!(daemon->env = (struct module_env*)calloc(1,
sizeof(*daemon->env)))) {
free(daemon);
return 1;
}
-/** count number of modules (words) in the string */
-static int
-count_modules(const char* s)
-{
- int num = 0;
- if(!s)
- return 0;
- while(*s) {
- /* skip whitespace */
- while(*s && isspace((int)*s))
- s++;
- if(*s && !isspace((int)*s)) {
- /* skip identifier */
- num++;
- while(*s && !isspace((int)*s))
- s++;
- }
- }
- return num;
-}
-
-/**
- * Get funcblock for module name
- * @param str: string with module name. Advanced to next value on success.
- * @return funcblock or NULL on error.
- */
-static struct module_func_block*
-daemon_module_factory(const char** str)
-{
- /* these are the modules available */
- int num = 2;
- const char* names[] = {"iterator", "validator", NULL};
- struct module_func_block* (*fb[])(void) =
- {&iter_get_funcblock, &val_get_funcblock, NULL};
-
- int i;
- const char* s = *str;
- while(*s && isspace((int)*s))
- s++;
- for(i=0; i<num; i++) {
- if(strncmp(names[i], s, strlen(names[i])) == 0) {
- s += strlen(names[i]);
- *str = s;
- return (*fb[i])();
- }
- }
- return NULL;
-}
-
-/**
- * Read config file module settings and set up the modfunc block
- * @param daemon: the daemon.
- * @return false on error
- */
-static int
-daemon_config_modules(struct daemon* daemon)
-{
- const char* str = daemon->cfg->module_conf;
- int i;
- verbose(VERB_DETAIL, "module config: \"%s\"", str);
- daemon->num_modules = count_modules(str);
- if(daemon->num_modules == 0) {
- log_err("error: no modules specified");
- return 0;
- }
- if(daemon->num_modules > MAX_MODULE) {
- log_err("error: too many modules (%d max %d)",
- daemon->num_modules, MAX_MODULE);
- return 0;
- }
- daemon->modfunc = (struct module_func_block**)calloc((size_t)
- daemon->num_modules, sizeof(struct module_func_block*));
- if(!daemon->modfunc) {
- log_err("out of memory");
- return 0;
- }
- for(i=0; i<daemon->num_modules; i++) {
- daemon->modfunc[i] = daemon_module_factory(&str);
- if(!daemon->modfunc[i]) {
- log_err("Unknown value for first module in: '%s'",
- str);
- return 0;
- }
- }
- return 1;
-}
-
-/**
- * Desetup the modules, deinit, delete.
- * @param daemon: the daemon.
- */
-static void
-daemon_desetup_modules(struct daemon* daemon)
-{
- int i;
- for(i=0; i<daemon->num_modules; i++) {
- log_assert(fptr_whitelist_mod_deinit(
- daemon->modfunc[i]->deinit));
- (*daemon->modfunc[i]->deinit)(daemon->env, i);
- }
- daemon->num_modules = 0;
- free(daemon->modfunc);
- daemon->modfunc = 0;
-}
-
/**
- * Setup modules. Assigns ids and calls module_init.
+ * Setup modules. setup module stack.
* @param daemon: the daemon
*/
static void daemon_setup_modules(struct daemon* daemon)
{
- int i;
- if(daemon->num_modules != 0)
- daemon_desetup_modules(daemon);
- /* fixed setup of the modules */
- if(!daemon_config_modules(daemon)) {
- fatal_exit("failed to setup modules");
- }
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 */
- for(i=0; i<daemon->num_modules; i++) {
- verbose(VERB_OPS, "init module %d: %s",
- i, daemon->modfunc[i]->name);
- log_assert(fptr_whitelist_mod_init(daemon->modfunc[i]->init));
- if(!(*daemon->modfunc[i]->init)(daemon->env, i)) {
- fatal_exit("module init for module %s failed",
- daemon->modfunc[i]->name);
- }
+ if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
+ daemon->env)) {
+ fatal_exit("failed to setup modules");
}
}
{
if(!daemon)
return;
- daemon_desetup_modules(daemon);
+ modstack_desetup(&daemon->mods, daemon->env);
listening_ports_free(daemon->ports);
if(daemon->env) {
slabhash_delete(daemon->env->msg_cache);
#include "util/locks.h"
#include "util/alloc.h"
+#include "services/modstack.h"
struct config_file;
struct worker;
struct listen_port;
struct alloc_cache superalloc;
/** the module environment master value, copied and changed by threads*/
struct module_env* env;
- /** number of modules active, ids from 0 to num-1. */
- int num_modules;
- /** the module callbacks, array of num_modules length */
- struct module_func_block** modfunc;
+ /** stack of module callbacks */
+ struct module_stack mods;
/** access control, which client IPs are allowed to connect */
struct acl_list* acl;
/** local authority zones */
worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
worker->env.scratch = worker->scratchpad;
- worker->env.mesh = mesh_create(worker->daemon->num_modules,
- worker->daemon->modfunc, &worker->env);
+ worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
worker->env.detach_subs = &mesh_detach_subs;
worker->env.attach_sub = &mesh_attach_sub;
worker->env.kill_sub = &mesh_state_delete;
+4 December 2007: Wouter
+ - minor Makefile fixup.
+ - moved module-stack code out of daemon/daemon into services/modstack,
+ preparing for code-reuse.
+
3 December 2007: Wouter
- changed checkconf/ to smallapp/ to make room for more support tools.
(such as unbound-host).
}
struct mesh_area*
-mesh_create(int num_modules, struct module_func_block** modfunc,
- struct module_env* env)
+mesh_create(struct module_stack* stack, struct module_env* env)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
if(!mesh) {
log_err("mesh area alloc: out of memory");
return NULL;
}
- mesh->num_modules = num_modules;
- mesh->modfunc = modfunc;
+ mesh->mods = *stack;
mesh->env = env;
rbtree_init(&mesh->run, &mesh_state_compare);
rbtree_init(&mesh->all, &mesh_state_compare);
mstate->s.env = env;
mstate->s.mesh_info = mstate;
/* init modules */
- for(i=0; i<env->mesh->num_modules; i++) {
+ for(i=0; i<env->mesh->mods.num; i++) {
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_state_initial;
}
return;
/* de-init modules */
mesh = mstate->s.env->mesh;
- for(i=0; i<mesh->num_modules; i++) {
- log_assert(fptr_whitelist_mod_clear(mesh->modfunc[i]->clear));
- (*mesh->modfunc[i]->clear)(&mstate->s, i);
+ for(i=0; i<mesh->mods.num; i++) {
+ log_assert(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
+ (*mesh->mods.mod[i]->clear)(&mstate->s, i);
mstate->s.minfo[i] = NULL;
mstate->s.ext_state[i] = module_finished;
}
(void)rbtree_insert(&mesh->run, &ref->s->run_node);
/* callback the function to inform super of result */
log_assert(fptr_whitelist_mod_inform_super(
- mesh->modfunc[ref->s->s.curmod]->inform_super));
- (*mesh->modfunc[ref->s->s.curmod]->inform_super)(&mstate->s,
+ mesh->mods.mod[ref->s->s.curmod]->inform_super));
+ (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
ref->s->s.curmod, &ref->s->s);
}
}
if(s == module_wait_module) {
/* start next module */
mstate->s.curmod++;
- if(mesh->num_modules == mstate->s.curmod) {
+ if(mesh->mods.num == mstate->s.curmod) {
log_err("Cannot pass to next module; at last module");
log_query_info(VERB_DETAIL, "pass error for qstate",
&mstate->s.qinfo);
while(mstate) {
/* run the module */
log_assert(fptr_whitelist_mod_operate(
- mesh->modfunc[mstate->s.curmod]->operate));
- (*mesh->modfunc[mstate->s.curmod]->operate)
+ mesh->mods.mod[mstate->s.curmod]->operate));
+ (*mesh->mods.mod[mstate->s.curmod]->operate)
(&mstate->s, ev, mstate->s.curmod, e);
/* examine results */
regional_free_all(mstate->s.env->scratch);
s = mstate->s.ext_state[mstate->s.curmod];
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
- mesh->modfunc[mstate->s.curmod]->name, strextstate(s));
+ mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
e = NULL;
if(mesh_continue(mesh, mstate, s, &ev))
continue;
#include "util/netevent.h"
#include "util/data/msgparse.h"
#include "util/module.h"
+#include "services/modstack.h"
struct mesh_state;
struct mesh_reply;
struct query_info;
* Mesh of query states
*/
struct mesh_area {
- /** the number of modules */
- int num_modules;
- /** the module callbacks, array of num_modules length (ref only) */
- struct module_func_block** modfunc;
+ /** active module stack */
+ struct module_stack mods;
/** environment for new states */
struct module_env* env;
/**
* Allocate mesh, to empty.
- * @param num_modules: number of modules that are present.
- * @param modfunc: array passed (alloced and deleted by caller), that has
- * num_modules function callbacks for the modules.
+ * @param stack: module stack to activate, copied (as readonly reference).
* @param env: environment for new queries.
* @return mesh: the new mesh or NULL on error.
*/
-struct mesh_area* mesh_create(int num_modules,
- struct module_func_block** modfunc, struct module_env* env);
+struct mesh_area* mesh_create(struct module_stack* stack,
+ struct module_env* env);
/**
* Delete mesh, and all query states and replies in it.
--- /dev/null
+/*
+ * services/modstack.c - stack of modules
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to help maintain a stack of modules.
+ */
+#include "config.h"
+#include "services/modstack.h"
+#include "util/module.h"
+#include "util/fptr_wlist.h"
+#include "iterator/iterator.h"
+#include "validator/validator.h"
+
+/** count number of modules (words) in the string */
+static int
+count_modules(const char* s)
+{
+ int num = 0;
+ if(!s)
+ return 0;
+ while(*s) {
+ /* skip whitespace */
+ while(*s && isspace((int)*s))
+ s++;
+ if(*s && !isspace((int)*s)) {
+ /* skip identifier */
+ num++;
+ while(*s && !isspace((int)*s))
+ 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)
+{
+ int i;
+ verbose(VERB_DETAIL, "module config: \"%s\"", module_conf);
+ stack->num = count_modules(module_conf);
+ if(stack->num == 0) {
+ log_err("error: no modules specified");
+ return 0;
+ }
+ if(stack->num > MAX_MODULE) {
+ log_err("error: too many modules (%d max %d)",
+ stack->num, MAX_MODULE);
+ return 0;
+ }
+ stack->mod = (struct module_func_block**)calloc((size_t)
+ stack->num, sizeof(struct module_func_block*));
+ if(!stack->mod) {
+ log_err("out of memory");
+ return 0;
+ }
+ for(i=0; i<stack->num; i++) {
+ stack->mod[i] = module_factory(&module_conf);
+ if(!stack->mod[i]) {
+ log_err("Unknown value for next module: '%s'",
+ module_conf);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+struct
+module_func_block* module_factory(const char** str)
+{
+ /* these are the modules available */
+ int num = 2;
+ const char* names[] = {"iterator", "validator", NULL};
+ struct module_func_block* (*fb[])(void) =
+ {&iter_get_funcblock, &val_get_funcblock, NULL};
+
+ int i;
+ const char* s = *str;
+ while(*s && isspace((int)*s))
+ s++;
+ for(i=0; i<num; i++) {
+ if(strncmp(names[i], s, strlen(names[i])) == 0) {
+ s += strlen(names[i]);
+ *str = s;
+ return (*fb[i])();
+ }
+ }
+ return NULL;
+}
+
+int
+modstack_setup(struct module_stack* stack, const char* module_conf,
+ struct module_env* env)
+{
+ int i;
+ if(stack->num != 0)
+ modstack_desetup(stack, env);
+ /* 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);
+ log_assert(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;
+ }
+ }
+ return 1;
+}
+
+void
+modstack_desetup(struct module_stack* stack, struct module_env* env)
+{
+ int i;
+ for(i=0; i<stack->num; i++) {
+ log_assert(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
+ (*stack->mod[i]->deinit)(env, i);
+ }
+ stack->num = 0;
+ free(stack->mod);
+ stack->mod = NULL;
+}
--- /dev/null
+/*
+ * services/modstack.h - stack of modules
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to help maintain a stack of modules.
+ */
+
+#ifndef SERVICES_MODSTACK_H
+#define SERVICES_MODSTACK_H
+struct module_func_block;
+struct module_env;
+
+/**
+ * Stack of modules.
+ */
+struct module_stack {
+ /** the number of modules */
+ int num;
+ /** the module callbacks, array of num_modules length (ref only) */
+ struct module_func_block** mod;
+};
+
+/**
+ * Init a stack of modules
+ * @param stack: initialised as empty.
+ */
+void modstack_init(struct module_stack* stack);
+
+/**
+ * Read config file module settings and set up the modfunc block
+ * @param stack: the stack of modules (empty before call).
+ * @param module_conf: string what modules to insert.
+ * @return false on error
+ */
+int modstack_config(struct module_stack* stack, const char* module_conf);
+
+/**
+ * Get funcblock for module name
+ * @param str: string with module name. Advanced to next value on success.
+ * The string is assumed whitespace separated list of module names.
+ * @return funcblock or NULL on error.
+ */
+struct module_func_block* module_factory(const char** str);
+
+/**
+ * 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.
+ * @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,
+ struct module_env* env);
+
+/**
+ * Desetup the modules, deinit, delete.
+ * @param stack: made empty.
+ * @param env: module env for module deinit() calls.
+ */
+void modstack_desetup(struct module_stack* stack, struct module_env* env);
+
+#endif /* SERVICES_MODSTACK_H */