modstack.c revision 307729
1331722Seadler/* 2256694Snp * services/modstack.c - stack of modules 3256694Snp * 4256694Snp * Copyright (c) 2007, NLnet Labs. All rights reserved. 5256694Snp * 6256694Snp * This software is open source. 7256694Snp * 8256694Snp * Redistribution and use in source and binary forms, with or without 9256694Snp * modification, are permitted provided that the following conditions 10256694Snp * are met: 11256694Snp * 12256694Snp * Redistributions of source code must retain the above copyright notice, 13256694Snp * this list of conditions and the following disclaimer. 14256694Snp * 15256694Snp * Redistributions in binary form must reproduce the above copyright notice, 16256694Snp * this list of conditions and the following disclaimer in the documentation 17256694Snp * and/or other materials provided with the distribution. 18256694Snp * 19256694Snp * Neither the name of the NLNET LABS nor the names of its contributors may 20256694Snp * be used to endorse or promote products derived from this software without 21256694Snp * specific prior written permission. 22256694Snp * 23256694Snp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24256694Snp * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25256694Snp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26256694Snp * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27256694Snp * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28256694Snp * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29256694Snp * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30256694Snp * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31256694Snp * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32256694Snp * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33256694Snp * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34256694Snp */ 35256694Snp 36256694Snp/** 37256694Snp * \file 38256694Snp * 39256694Snp * This file contains functions to help maintain a stack of modules. 40256694Snp */ 41256694Snp#include "config.h" 42256694Snp#include <ctype.h> 43256694Snp#include "services/modstack.h" 44256694Snp#include "util/module.h" 45256694Snp#include "util/fptr_wlist.h" 46256694Snp#include "dns64/dns64.h" 47256694Snp#include "iterator/iterator.h" 48256694Snp#include "validator/validator.h" 49256694Snp 50256694Snp#ifdef WITH_PYTHONMODULE 51256694Snp#include "pythonmod/pythonmod.h" 52256694Snp#endif 53256694Snp#ifdef USE_CACHEDB 54256694Snp#include "cachedb/cachedb.h" 55256694Snp#endif 56256694Snp 57256694Snp/** count number of modules (words) in the string */ 58256694Snpstatic int 59256694Snpcount_modules(const char* s) 60256694Snp{ 61256694Snp int num = 0; 62256694Snp if(!s) 63256694Snp return 0; 64256694Snp while(*s) { 65256694Snp /* skip whitespace */ 66256694Snp while(*s && isspace((unsigned char)*s)) 67256694Snp s++; 68256694Snp if(*s && !isspace((unsigned char)*s)) { 69256694Snp /* skip identifier */ 70256694Snp num++; 71256694Snp while(*s && !isspace((unsigned char)*s)) 72256694Snp s++; 73256694Snp } 74256694Snp } 75256694Snp return num; 76256694Snp} 77256694Snp 78256694Snpvoid 79256694Snpmodstack_init(struct module_stack* stack) 80256694Snp{ 81256694Snp stack->num = 0; 82256694Snp stack->mod = NULL; 83256694Snp} 84256694Snp 85256694Snpint 86256694Snpmodstack_config(struct module_stack* stack, const char* module_conf) 87256694Snp{ 88256694Snp int i; 89256694Snp verbose(VERB_QUERY, "module config: \"%s\"", module_conf); 90256694Snp stack->num = count_modules(module_conf); 91256694Snp if(stack->num == 0) { 92256694Snp log_err("error: no modules specified"); 93256694Snp return 0; 94256694Snp } 95256694Snp if(stack->num > MAX_MODULE) { 96256694Snp log_err("error: too many modules (%d max %d)", 97256694Snp stack->num, MAX_MODULE); 98256694Snp return 0; 99256694Snp } 100256694Snp stack->mod = (struct module_func_block**)calloc((size_t) 101256694Snp stack->num, sizeof(struct module_func_block*)); 102256694Snp if(!stack->mod) { 103256694Snp log_err("out of memory"); 104256694Snp return 0; 105256694Snp } 106256694Snp for(i=0; i<stack->num; i++) { 107256694Snp stack->mod[i] = module_factory(&module_conf); 108256694Snp if(!stack->mod[i]) { 109256694Snp log_err("Unknown value for next module: '%s'", 110256694Snp module_conf); 111256694Snp return 0; 112256694Snp } 113256694Snp } 114256694Snp return 1; 115256694Snp} 116256694Snp 117256694Snp/** The list of module names */ 118256694Snpconst char** 119module_list_avail(void) 120{ 121 /* these are the modules available */ 122 static const char* names[] = { 123 "dns64", 124#ifdef WITH_PYTHONMODULE 125 "python", 126#endif 127#ifdef USE_CACHEDB 128 "cachedb", 129#endif 130 "validator", 131 "iterator", 132 NULL}; 133 return names; 134} 135 136/** func block get function type */ 137typedef struct module_func_block* (*fbgetfunctype)(void); 138 139/** The list of module func blocks */ 140static fbgetfunctype* 141module_funcs_avail(void) 142{ 143 static struct module_func_block* (*fb[])(void) = { 144 &dns64_get_funcblock, 145#ifdef WITH_PYTHONMODULE 146 &pythonmod_get_funcblock, 147#endif 148#ifdef USE_CACHEDB 149 &cachedb_get_funcblock, 150#endif 151 &val_get_funcblock, 152 &iter_get_funcblock, 153 NULL}; 154 return fb; 155} 156 157struct 158module_func_block* module_factory(const char** str) 159{ 160 int i = 0; 161 const char* s = *str; 162 const char** names = module_list_avail(); 163 fbgetfunctype* fb = module_funcs_avail(); 164 while(*s && isspace((unsigned char)*s)) 165 s++; 166 while(names[i]) { 167 if(strncmp(names[i], s, strlen(names[i])) == 0) { 168 s += strlen(names[i]); 169 *str = s; 170 return (*fb[i])(); 171 } 172 i++; 173 } 174 return NULL; 175} 176 177int 178modstack_setup(struct module_stack* stack, const char* module_conf, 179 struct module_env* env) 180{ 181 int i; 182 if(stack->num != 0) 183 modstack_desetup(stack, env); 184 /* fixed setup of the modules */ 185 if(!modstack_config(stack, module_conf)) { 186 return 0; 187 } 188 env->need_to_validate = 0; /* set by module init below */ 189 for(i=0; i<stack->num; i++) { 190 verbose(VERB_OPS, "init module %d: %s", 191 i, stack->mod[i]->name); 192 fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 193 if(!(*stack->mod[i]->init)(env, i)) { 194 log_err("module init for module %s failed", 195 stack->mod[i]->name); 196 return 0; 197 } 198 } 199 return 1; 200} 201 202void 203modstack_desetup(struct module_stack* stack, struct module_env* env) 204{ 205 int i; 206 for(i=0; i<stack->num; i++) { 207 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 208 (*stack->mod[i]->deinit)(env, i); 209 } 210 stack->num = 0; 211 free(stack->mod); 212 stack->mod = NULL; 213} 214 215int 216modstack_find(struct module_stack* stack, const char* name) 217{ 218 int i; 219 for(i=0; i<stack->num; i++) { 220 if(strcmp(stack->mod[i]->name, name) == 0) 221 return i; 222 } 223 return -1; 224} 225