1238106Sdes/* 2238106Sdes * services/modstack.c - stack of modules 3238106Sdes * 4238106Sdes * Copyright (c) 2007, NLnet Labs. All rights reserved. 5238106Sdes * 6238106Sdes * This software is open source. 7238106Sdes * 8238106Sdes * Redistribution and use in source and binary forms, with or without 9238106Sdes * modification, are permitted provided that the following conditions 10238106Sdes * are met: 11238106Sdes * 12238106Sdes * Redistributions of source code must retain the above copyright notice, 13238106Sdes * this list of conditions and the following disclaimer. 14238106Sdes * 15238106Sdes * Redistributions in binary form must reproduce the above copyright notice, 16238106Sdes * this list of conditions and the following disclaimer in the documentation 17238106Sdes * and/or other materials provided with the distribution. 18238106Sdes * 19238106Sdes * Neither the name of the NLNET LABS nor the names of its contributors may 20238106Sdes * be used to endorse or promote products derived from this software without 21238106Sdes * specific prior written permission. 22238106Sdes * 23238106Sdes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24269257Sdes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25269257Sdes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26269257Sdes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27269257Sdes * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28269257Sdes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 29269257Sdes * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30269257Sdes * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31269257Sdes * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32269257Sdes * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33269257Sdes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34238106Sdes */ 35238106Sdes 36238106Sdes/** 37238106Sdes * \file 38238106Sdes * 39238106Sdes * This file contains functions to help maintain a stack of modules. 40238106Sdes */ 41238106Sdes#include "config.h" 42238106Sdes#include <ctype.h> 43238106Sdes#include "services/modstack.h" 44238106Sdes#include "util/module.h" 45238106Sdes#include "util/fptr_wlist.h" 46285206Sdes#include "dns64/dns64.h" 47238106Sdes#include "iterator/iterator.h" 48238106Sdes#include "validator/validator.h" 49238106Sdes 50238106Sdes#ifdef WITH_PYTHONMODULE 51238106Sdes#include "pythonmod/pythonmod.h" 52238106Sdes#endif 53238106Sdes 54238106Sdes/** count number of modules (words) in the string */ 55238106Sdesstatic int 56238106Sdescount_modules(const char* s) 57238106Sdes{ 58238106Sdes int num = 0; 59238106Sdes if(!s) 60238106Sdes return 0; 61238106Sdes while(*s) { 62238106Sdes /* skip whitespace */ 63285206Sdes while(*s && isspace((unsigned char)*s)) 64238106Sdes s++; 65285206Sdes if(*s && !isspace((unsigned char)*s)) { 66238106Sdes /* skip identifier */ 67238106Sdes num++; 68285206Sdes while(*s && !isspace((unsigned char)*s)) 69238106Sdes s++; 70238106Sdes } 71238106Sdes } 72238106Sdes return num; 73238106Sdes} 74238106Sdes 75238106Sdesvoid 76238106Sdesmodstack_init(struct module_stack* stack) 77238106Sdes{ 78238106Sdes stack->num = 0; 79238106Sdes stack->mod = NULL; 80238106Sdes} 81238106Sdes 82238106Sdesint 83238106Sdesmodstack_config(struct module_stack* stack, const char* module_conf) 84238106Sdes{ 85238106Sdes int i; 86238106Sdes verbose(VERB_QUERY, "module config: \"%s\"", module_conf); 87238106Sdes stack->num = count_modules(module_conf); 88238106Sdes if(stack->num == 0) { 89238106Sdes log_err("error: no modules specified"); 90238106Sdes return 0; 91238106Sdes } 92238106Sdes if(stack->num > MAX_MODULE) { 93238106Sdes log_err("error: too many modules (%d max %d)", 94238106Sdes stack->num, MAX_MODULE); 95238106Sdes return 0; 96238106Sdes } 97238106Sdes stack->mod = (struct module_func_block**)calloc((size_t) 98238106Sdes stack->num, sizeof(struct module_func_block*)); 99238106Sdes if(!stack->mod) { 100238106Sdes log_err("out of memory"); 101238106Sdes return 0; 102238106Sdes } 103238106Sdes for(i=0; i<stack->num; i++) { 104238106Sdes stack->mod[i] = module_factory(&module_conf); 105238106Sdes if(!stack->mod[i]) { 106238106Sdes log_err("Unknown value for next module: '%s'", 107238106Sdes module_conf); 108238106Sdes return 0; 109238106Sdes } 110238106Sdes } 111238106Sdes return 1; 112238106Sdes} 113238106Sdes 114238106Sdes/** The list of module names */ 115238106Sdesconst char** 116238106Sdesmodule_list_avail(void) 117238106Sdes{ 118238106Sdes /* these are the modules available */ 119238106Sdes static const char* names[] = { 120285206Sdes "dns64", 121238106Sdes#ifdef WITH_PYTHONMODULE 122238106Sdes "python", 123238106Sdes#endif 124238106Sdes "validator", 125238106Sdes "iterator", 126238106Sdes NULL}; 127238106Sdes return names; 128238106Sdes} 129238106Sdes 130238106Sdes/** func block get function type */ 131238106Sdestypedef struct module_func_block* (*fbgetfunctype)(void); 132238106Sdes 133238106Sdes/** The list of module func blocks */ 134238106Sdesstatic fbgetfunctype* 135238106Sdesmodule_funcs_avail(void) 136238106Sdes{ 137238106Sdes static struct module_func_block* (*fb[])(void) = { 138285206Sdes &dns64_get_funcblock, 139238106Sdes#ifdef WITH_PYTHONMODULE 140238106Sdes &pythonmod_get_funcblock, 141238106Sdes#endif 142238106Sdes &val_get_funcblock, 143238106Sdes &iter_get_funcblock, 144238106Sdes NULL}; 145238106Sdes return fb; 146238106Sdes} 147238106Sdes 148238106Sdesstruct 149238106Sdesmodule_func_block* module_factory(const char** str) 150238106Sdes{ 151238106Sdes int i = 0; 152238106Sdes const char* s = *str; 153238106Sdes const char** names = module_list_avail(); 154238106Sdes fbgetfunctype* fb = module_funcs_avail(); 155285206Sdes while(*s && isspace((unsigned char)*s)) 156238106Sdes s++; 157238106Sdes while(names[i]) { 158238106Sdes if(strncmp(names[i], s, strlen(names[i])) == 0) { 159238106Sdes s += strlen(names[i]); 160238106Sdes *str = s; 161238106Sdes return (*fb[i])(); 162238106Sdes } 163238106Sdes i++; 164238106Sdes } 165238106Sdes return NULL; 166238106Sdes} 167238106Sdes 168238106Sdesint 169238106Sdesmodstack_setup(struct module_stack* stack, const char* module_conf, 170238106Sdes struct module_env* env) 171238106Sdes{ 172238106Sdes int i; 173238106Sdes if(stack->num != 0) 174238106Sdes modstack_desetup(stack, env); 175238106Sdes /* fixed setup of the modules */ 176238106Sdes if(!modstack_config(stack, module_conf)) { 177238106Sdes return 0; 178238106Sdes } 179238106Sdes env->need_to_validate = 0; /* set by module init below */ 180238106Sdes for(i=0; i<stack->num; i++) { 181238106Sdes verbose(VERB_OPS, "init module %d: %s", 182238106Sdes i, stack->mod[i]->name); 183238106Sdes fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 184238106Sdes if(!(*stack->mod[i]->init)(env, i)) { 185238106Sdes log_err("module init for module %s failed", 186238106Sdes stack->mod[i]->name); 187238106Sdes return 0; 188238106Sdes } 189238106Sdes } 190238106Sdes return 1; 191238106Sdes} 192238106Sdes 193238106Sdesvoid 194238106Sdesmodstack_desetup(struct module_stack* stack, struct module_env* env) 195238106Sdes{ 196238106Sdes int i; 197238106Sdes for(i=0; i<stack->num; i++) { 198238106Sdes fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 199238106Sdes (*stack->mod[i]->deinit)(env, i); 200238106Sdes } 201238106Sdes stack->num = 0; 202238106Sdes free(stack->mod); 203238106Sdes stack->mod = NULL; 204238106Sdes} 205238106Sdes 206238106Sdesint 207238106Sdesmodstack_find(struct module_stack* stack, const char* name) 208238106Sdes{ 209238106Sdes int i; 210238106Sdes for(i=0; i<stack->num; i++) { 211238106Sdes if(strcmp(stack->mod[i]->name, name) == 0) 212238106Sdes return i; 213238106Sdes } 214238106Sdes return -1; 215238106Sdes} 216