1 /* 2 * services/modstack.c - stack of modules 3 * 4 * Copyright (c) 2007, NLnet Labs. All rights reserved. 5 * 6 * This software is open source. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 19 * Neither the name of the NLNET LABS nor the names of its contributors may 20 * be used to endorse or promote products derived from this software without 21 * specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 /** 37 * \file 38 * 39 * This file contains functions to help maintain a stack of modules. 40 */ 41 #include "config.h" 42 #include <ctype.h> 43 #include "services/modstack.h" 44 #include "util/module.h" 45 #include "util/fptr_wlist.h" 46 #include "dns64/dns64.h" 47 #include "iterator/iterator.h" 48 #include "validator/validator.h" 49 #include "respip/respip.h" 50 51 #ifdef WITH_PYTHONMODULE 52 #include "pythonmod/pythonmod.h" 53 #endif 54 #ifdef USE_CACHEDB 55 #include "cachedb/cachedb.h" 56 #endif 57 #ifdef USE_IPSECMOD 58 #include "ipsecmod/ipsecmod.h" 59 #endif 60 #ifdef CLIENT_SUBNET 61 #include "edns-subnet/subnetmod.h" 62 #endif 63 64 /** count number of modules (words) in the string */ 65 static int 66 count_modules(const char* s) 67 { 68 int num = 0; 69 if(!s) 70 return 0; 71 while(*s) { 72 /* skip whitespace */ 73 while(*s && isspace((unsigned char)*s)) 74 s++; 75 if(*s && !isspace((unsigned char)*s)) { 76 /* skip identifier */ 77 num++; 78 while(*s && !isspace((unsigned char)*s)) 79 s++; 80 } 81 } 82 return num; 83 } 84 85 void 86 modstack_init(struct module_stack* stack) 87 { 88 stack->num = 0; 89 stack->mod = NULL; 90 } 91 92 int 93 modstack_config(struct module_stack* stack, const char* module_conf) 94 { 95 int i; 96 verbose(VERB_QUERY, "module config: \"%s\"", module_conf); 97 stack->num = count_modules(module_conf); 98 if(stack->num == 0) { 99 log_err("error: no modules specified"); 100 return 0; 101 } 102 if(stack->num > MAX_MODULE) { 103 log_err("error: too many modules (%d max %d)", 104 stack->num, MAX_MODULE); 105 return 0; 106 } 107 stack->mod = (struct module_func_block**)calloc((size_t) 108 stack->num, sizeof(struct module_func_block*)); 109 if(!stack->mod) { 110 log_err("out of memory"); 111 return 0; 112 } 113 for(i=0; i<stack->num; i++) { 114 stack->mod[i] = module_factory(&module_conf); 115 if(!stack->mod[i]) { 116 log_err("Unknown value for next module: '%s'", 117 module_conf); 118 return 0; 119 } 120 } 121 return 1; 122 } 123 124 /** The list of module names */ 125 const char** 126 module_list_avail(void) 127 { 128 /* these are the modules available */ 129 static const char* names[] = { 130 "dns64", 131 #ifdef WITH_PYTHONMODULE 132 "python", 133 #endif 134 #ifdef USE_CACHEDB 135 "cachedb", 136 #endif 137 #ifdef USE_IPSECMOD 138 "ipsecmod", 139 #endif 140 #ifdef CLIENT_SUBNET 141 "subnetcache", 142 #endif 143 "respip", 144 "validator", 145 "iterator", 146 NULL}; 147 return names; 148 } 149 150 /** func block get function type */ 151 typedef struct module_func_block* (*fbgetfunctype)(void); 152 153 /** The list of module func blocks */ 154 static fbgetfunctype* 155 module_funcs_avail(void) 156 { 157 static struct module_func_block* (*fb[])(void) = { 158 &dns64_get_funcblock, 159 #ifdef WITH_PYTHONMODULE 160 &pythonmod_get_funcblock, 161 #endif 162 #ifdef USE_CACHEDB 163 &cachedb_get_funcblock, 164 #endif 165 #ifdef USE_IPSECMOD 166 &ipsecmod_get_funcblock, 167 #endif 168 #ifdef CLIENT_SUBNET 169 &subnetmod_get_funcblock, 170 #endif 171 &respip_get_funcblock, 172 &val_get_funcblock, 173 &iter_get_funcblock, 174 NULL}; 175 return fb; 176 } 177 178 struct 179 module_func_block* module_factory(const char** str) 180 { 181 int i = 0; 182 const char* s = *str; 183 const char** names = module_list_avail(); 184 fbgetfunctype* fb = module_funcs_avail(); 185 while(*s && isspace((unsigned char)*s)) 186 s++; 187 while(names[i]) { 188 if(strncmp(names[i], s, strlen(names[i])) == 0) { 189 s += strlen(names[i]); 190 *str = s; 191 return (*fb[i])(); 192 } 193 i++; 194 } 195 return NULL; 196 } 197 198 int 199 modstack_setup(struct module_stack* stack, const char* module_conf, 200 struct module_env* env) 201 { 202 int i; 203 if(stack->num != 0) 204 modstack_desetup(stack, env); 205 /* fixed setup of the modules */ 206 if(!modstack_config(stack, module_conf)) { 207 return 0; 208 } 209 env->need_to_validate = 0; /* set by module init below */ 210 for(i=0; i<stack->num; i++) { 211 verbose(VERB_OPS, "init module %d: %s", 212 i, stack->mod[i]->name); 213 fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 214 if(!(*stack->mod[i]->init)(env, i)) { 215 log_err("module init for module %s failed", 216 stack->mod[i]->name); 217 return 0; 218 } 219 } 220 return 1; 221 } 222 223 void 224 modstack_desetup(struct module_stack* stack, struct module_env* env) 225 { 226 int i; 227 for(i=0; i<stack->num; i++) { 228 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 229 (*stack->mod[i]->deinit)(env, i); 230 } 231 stack->num = 0; 232 free(stack->mod); 233 stack->mod = NULL; 234 } 235 236 int 237 modstack_find(struct module_stack* stack, const char* name) 238 { 239 int i; 240 for(i=0; i<stack->num; i++) { 241 if(strcmp(stack->mod[i]->name, name) == 0) 242 return i; 243 } 244 return -1; 245 } 246 247 size_t 248 mod_get_mem(struct module_env* env, const char* name) 249 { 250 int m = modstack_find(&env->mesh->mods, name); 251 if(m != -1) { 252 fptr_ok(fptr_whitelist_mod_get_mem(env->mesh-> 253 mods.mod[m]->get_mem)); 254 return (*env->mesh->mods.mod[m]->get_mem)(env, m); 255 } 256 return 0; 257 } 258