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 #ifdef USE_IPSET 64 #include "ipset/ipset.h" 65 #endif 66 67 /** count number of modules (words) in the string */ 68 static int 69 count_modules(const char* s) 70 { 71 int num = 0; 72 if(!s) 73 return 0; 74 while(*s) { 75 /* skip whitespace */ 76 while(*s && isspace((unsigned char)*s)) 77 s++; 78 if(*s && !isspace((unsigned char)*s)) { 79 /* skip identifier */ 80 num++; 81 while(*s && !isspace((unsigned char)*s)) 82 s++; 83 } 84 } 85 return num; 86 } 87 88 void 89 modstack_init(struct module_stack* stack) 90 { 91 stack->num = 0; 92 stack->mod = NULL; 93 } 94 95 int 96 modstack_config(struct module_stack* stack, const char* module_conf) 97 { 98 int i; 99 verbose(VERB_QUERY, "module config: \"%s\"", module_conf); 100 stack->num = count_modules(module_conf); 101 if(stack->num == 0) { 102 log_err("error: no modules specified"); 103 return 0; 104 } 105 if(stack->num > MAX_MODULE) { 106 log_err("error: too many modules (%d max %d)", 107 stack->num, MAX_MODULE); 108 return 0; 109 } 110 stack->mod = (struct module_func_block**)calloc((size_t) 111 stack->num, sizeof(struct module_func_block*)); 112 if(!stack->mod) { 113 log_err("out of memory"); 114 return 0; 115 } 116 for(i=0; i<stack->num; i++) { 117 stack->mod[i] = module_factory(&module_conf); 118 if(!stack->mod[i]) { 119 char md[256]; 120 snprintf(md, sizeof(md), "%s", module_conf); 121 if(strchr(md, ' ')) *(strchr(md, ' ')) = 0; 122 if(strchr(md, '\t')) *(strchr(md, '\t')) = 0; 123 log_err("Unknown value in module-config, module: '%s'." 124 " This module is not present (not compiled in)," 125 " See the list of linked modules with unbound -h", 126 md); 127 return 0; 128 } 129 } 130 return 1; 131 } 132 133 /** The list of module names */ 134 const char** 135 module_list_avail(void) 136 { 137 /* these are the modules available */ 138 static const char* names[] = { 139 "dns64", 140 #ifdef WITH_PYTHONMODULE 141 "python", 142 #endif 143 #ifdef USE_CACHEDB 144 "cachedb", 145 #endif 146 #ifdef USE_IPSECMOD 147 "ipsecmod", 148 #endif 149 #ifdef CLIENT_SUBNET 150 "subnetcache", 151 #endif 152 #ifdef USE_IPSET 153 "ipset", 154 #endif 155 "respip", 156 "validator", 157 "iterator", 158 NULL}; 159 return names; 160 } 161 162 /** func block get function type */ 163 typedef struct module_func_block* (*fbgetfunctype)(void); 164 165 /** The list of module func blocks */ 166 static fbgetfunctype* 167 module_funcs_avail(void) 168 { 169 static struct module_func_block* (*fb[])(void) = { 170 &dns64_get_funcblock, 171 #ifdef WITH_PYTHONMODULE 172 &pythonmod_get_funcblock, 173 #endif 174 #ifdef USE_CACHEDB 175 &cachedb_get_funcblock, 176 #endif 177 #ifdef USE_IPSECMOD 178 &ipsecmod_get_funcblock, 179 #endif 180 #ifdef CLIENT_SUBNET 181 &subnetmod_get_funcblock, 182 #endif 183 #ifdef USE_IPSET 184 &ipset_get_funcblock, 185 #endif 186 &respip_get_funcblock, 187 &val_get_funcblock, 188 &iter_get_funcblock, 189 NULL}; 190 return fb; 191 } 192 193 struct 194 module_func_block* module_factory(const char** str) 195 { 196 int i = 0; 197 const char* s = *str; 198 const char** names = module_list_avail(); 199 fbgetfunctype* fb = module_funcs_avail(); 200 while(*s && isspace((unsigned char)*s)) 201 s++; 202 while(names[i]) { 203 if(strncmp(names[i], s, strlen(names[i])) == 0) { 204 s += strlen(names[i]); 205 *str = s; 206 return (*fb[i])(); 207 } 208 i++; 209 } 210 return NULL; 211 } 212 213 int 214 modstack_setup(struct module_stack* stack, const char* module_conf, 215 struct module_env* env) 216 { 217 int i; 218 if(stack->num != 0) 219 modstack_desetup(stack, env); 220 /* fixed setup of the modules */ 221 if(!modstack_config(stack, module_conf)) { 222 return 0; 223 } 224 env->need_to_validate = 0; /* set by module init below */ 225 for(i=0; i<stack->num; i++) { 226 verbose(VERB_OPS, "init module %d: %s", 227 i, stack->mod[i]->name); 228 fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 229 if(!(*stack->mod[i]->init)(env, i)) { 230 log_err("module init for module %s failed", 231 stack->mod[i]->name); 232 return 0; 233 } 234 } 235 return 1; 236 } 237 238 void 239 modstack_desetup(struct module_stack* stack, struct module_env* env) 240 { 241 int i; 242 for(i=0; i<stack->num; i++) { 243 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 244 (*stack->mod[i]->deinit)(env, i); 245 } 246 stack->num = 0; 247 free(stack->mod); 248 stack->mod = NULL; 249 } 250 251 int 252 modstack_find(struct module_stack* stack, const char* name) 253 { 254 int i; 255 for(i=0; i<stack->num; i++) { 256 if(strcmp(stack->mod[i]->name, name) == 0) 257 return i; 258 } 259 return -1; 260 } 261 262 size_t 263 mod_get_mem(struct module_env* env, const char* name) 264 { 265 int m = modstack_find(&env->mesh->mods, name); 266 if(m != -1) { 267 fptr_ok(fptr_whitelist_mod_get_mem(env->mesh-> 268 mods.mod[m]->get_mem)); 269 return (*env->mesh->mods.mod[m]->get_mem)(env, m); 270 } 271 return 0; 272 } 273