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 char md[256]; 117 snprintf(md, sizeof(md), "%s", module_conf); 118 if(strchr(md, ' ')) *(strchr(md, ' ')) = 0; 119 if(strchr(md, '\t')) *(strchr(md, '\t')) = 0; 120 log_err("Unknown value in module-config, module: '%s'." 121 " This module is not present (not compiled in)," 122 " See the list of linked modules with unbound -h", 123 md); 124 return 0; 125 } 126 } 127 return 1; 128 } 129 130 /** The list of module names */ 131 const char** 132 module_list_avail(void) 133 { 134 /* these are the modules available */ 135 static const char* names[] = { 136 "dns64", 137 #ifdef WITH_PYTHONMODULE 138 "python", 139 #endif 140 #ifdef USE_CACHEDB 141 "cachedb", 142 #endif 143 #ifdef USE_IPSECMOD 144 "ipsecmod", 145 #endif 146 #ifdef CLIENT_SUBNET 147 "subnetcache", 148 #endif 149 "respip", 150 "validator", 151 "iterator", 152 NULL}; 153 return names; 154 } 155 156 /** func block get function type */ 157 typedef struct module_func_block* (*fbgetfunctype)(void); 158 159 /** The list of module func blocks */ 160 static fbgetfunctype* 161 module_funcs_avail(void) 162 { 163 static struct module_func_block* (*fb[])(void) = { 164 &dns64_get_funcblock, 165 #ifdef WITH_PYTHONMODULE 166 &pythonmod_get_funcblock, 167 #endif 168 #ifdef USE_CACHEDB 169 &cachedb_get_funcblock, 170 #endif 171 #ifdef USE_IPSECMOD 172 &ipsecmod_get_funcblock, 173 #endif 174 #ifdef CLIENT_SUBNET 175 &subnetmod_get_funcblock, 176 #endif 177 &respip_get_funcblock, 178 &val_get_funcblock, 179 &iter_get_funcblock, 180 NULL}; 181 return fb; 182 } 183 184 struct 185 module_func_block* module_factory(const char** str) 186 { 187 int i = 0; 188 const char* s = *str; 189 const char** names = module_list_avail(); 190 fbgetfunctype* fb = module_funcs_avail(); 191 while(*s && isspace((unsigned char)*s)) 192 s++; 193 while(names[i]) { 194 if(strncmp(names[i], s, strlen(names[i])) == 0) { 195 s += strlen(names[i]); 196 *str = s; 197 return (*fb[i])(); 198 } 199 i++; 200 } 201 return NULL; 202 } 203 204 int 205 modstack_setup(struct module_stack* stack, const char* module_conf, 206 struct module_env* env) 207 { 208 int i; 209 if(stack->num != 0) 210 modstack_desetup(stack, env); 211 /* fixed setup of the modules */ 212 if(!modstack_config(stack, module_conf)) { 213 return 0; 214 } 215 env->need_to_validate = 0; /* set by module init below */ 216 for(i=0; i<stack->num; i++) { 217 verbose(VERB_OPS, "init module %d: %s", 218 i, stack->mod[i]->name); 219 fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 220 if(!(*stack->mod[i]->init)(env, i)) { 221 log_err("module init for module %s failed", 222 stack->mod[i]->name); 223 return 0; 224 } 225 } 226 return 1; 227 } 228 229 void 230 modstack_desetup(struct module_stack* stack, struct module_env* env) 231 { 232 int i; 233 for(i=0; i<stack->num; i++) { 234 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 235 (*stack->mod[i]->deinit)(env, i); 236 } 237 stack->num = 0; 238 free(stack->mod); 239 stack->mod = NULL; 240 } 241 242 int 243 modstack_find(struct module_stack* stack, const char* name) 244 { 245 int i; 246 for(i=0; i<stack->num; i++) { 247 if(strcmp(stack->mod[i]->name, name) == 0) 248 return i; 249 } 250 return -1; 251 } 252 253 size_t 254 mod_get_mem(struct module_env* env, const char* name) 255 { 256 int m = modstack_find(&env->mesh->mods, name); 257 if(m != -1) { 258 fptr_ok(fptr_whitelist_mod_get_mem(env->mesh-> 259 mods.mod[m]->get_mem)); 260 return (*env->mesh->mods.mod[m]->get_mem)(env, m); 261 } 262 return 0; 263 } 264