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" 46238106Sdes#include "iterator/iterator.h" 47238106Sdes#include "validator/validator.h" 48238106Sdes 49238106Sdes#ifdef WITH_PYTHONMODULE 50238106Sdes#include "pythonmod/pythonmod.h" 51238106Sdes#endif 52238106Sdes 53238106Sdes/** count number of modules (words) in the string */ 54238106Sdesstatic int 55238106Sdescount_modules(const char* s) 56238106Sdes{ 57238106Sdes int num = 0; 58238106Sdes if(!s) 59238106Sdes return 0; 60238106Sdes while(*s) { 61238106Sdes /* skip whitespace */ 62238106Sdes while(*s && isspace((int)*s)) 63238106Sdes s++; 64238106Sdes if(*s && !isspace((int)*s)) { 65238106Sdes /* skip identifier */ 66238106Sdes num++; 67238106Sdes while(*s && !isspace((int)*s)) 68238106Sdes s++; 69238106Sdes } 70238106Sdes } 71238106Sdes return num; 72238106Sdes} 73238106Sdes 74238106Sdesvoid 75238106Sdesmodstack_init(struct module_stack* stack) 76238106Sdes{ 77238106Sdes stack->num = 0; 78238106Sdes stack->mod = NULL; 79238106Sdes} 80238106Sdes 81238106Sdesint 82238106Sdesmodstack_config(struct module_stack* stack, const char* module_conf) 83238106Sdes{ 84238106Sdes int i; 85238106Sdes verbose(VERB_QUERY, "module config: \"%s\"", module_conf); 86238106Sdes stack->num = count_modules(module_conf); 87238106Sdes if(stack->num == 0) { 88238106Sdes log_err("error: no modules specified"); 89238106Sdes return 0; 90238106Sdes } 91238106Sdes if(stack->num > MAX_MODULE) { 92238106Sdes log_err("error: too many modules (%d max %d)", 93238106Sdes stack->num, MAX_MODULE); 94238106Sdes return 0; 95238106Sdes } 96238106Sdes stack->mod = (struct module_func_block**)calloc((size_t) 97238106Sdes stack->num, sizeof(struct module_func_block*)); 98238106Sdes if(!stack->mod) { 99238106Sdes log_err("out of memory"); 100238106Sdes return 0; 101238106Sdes } 102238106Sdes for(i=0; i<stack->num; i++) { 103238106Sdes stack->mod[i] = module_factory(&module_conf); 104238106Sdes if(!stack->mod[i]) { 105238106Sdes log_err("Unknown value for next module: '%s'", 106238106Sdes module_conf); 107238106Sdes return 0; 108238106Sdes } 109238106Sdes } 110238106Sdes return 1; 111238106Sdes} 112238106Sdes 113238106Sdes/** The list of module names */ 114238106Sdesconst char** 115238106Sdesmodule_list_avail(void) 116238106Sdes{ 117238106Sdes /* these are the modules available */ 118238106Sdes static const char* names[] = { 119238106Sdes#ifdef WITH_PYTHONMODULE 120238106Sdes "python", 121238106Sdes#endif 122238106Sdes "validator", 123238106Sdes "iterator", 124238106Sdes NULL}; 125238106Sdes return names; 126238106Sdes} 127238106Sdes 128238106Sdes/** func block get function type */ 129238106Sdestypedef struct module_func_block* (*fbgetfunctype)(void); 130238106Sdes 131238106Sdes/** The list of module func blocks */ 132238106Sdesstatic fbgetfunctype* 133238106Sdesmodule_funcs_avail(void) 134238106Sdes{ 135238106Sdes static struct module_func_block* (*fb[])(void) = { 136238106Sdes#ifdef WITH_PYTHONMODULE 137238106Sdes &pythonmod_get_funcblock, 138238106Sdes#endif 139238106Sdes &val_get_funcblock, 140238106Sdes &iter_get_funcblock, 141238106Sdes NULL}; 142238106Sdes return fb; 143238106Sdes} 144238106Sdes 145238106Sdesstruct 146238106Sdesmodule_func_block* module_factory(const char** str) 147238106Sdes{ 148238106Sdes int i = 0; 149238106Sdes const char* s = *str; 150238106Sdes const char** names = module_list_avail(); 151238106Sdes fbgetfunctype* fb = module_funcs_avail(); 152238106Sdes while(*s && isspace((int)*s)) 153238106Sdes s++; 154238106Sdes while(names[i]) { 155238106Sdes if(strncmp(names[i], s, strlen(names[i])) == 0) { 156238106Sdes s += strlen(names[i]); 157238106Sdes *str = s; 158238106Sdes return (*fb[i])(); 159238106Sdes } 160238106Sdes i++; 161238106Sdes } 162238106Sdes return NULL; 163238106Sdes} 164238106Sdes 165238106Sdesint 166238106Sdesmodstack_setup(struct module_stack* stack, const char* module_conf, 167238106Sdes struct module_env* env) 168238106Sdes{ 169238106Sdes int i; 170238106Sdes if(stack->num != 0) 171238106Sdes modstack_desetup(stack, env); 172238106Sdes /* fixed setup of the modules */ 173238106Sdes if(!modstack_config(stack, module_conf)) { 174238106Sdes return 0; 175238106Sdes } 176238106Sdes env->need_to_validate = 0; /* set by module init below */ 177238106Sdes for(i=0; i<stack->num; i++) { 178238106Sdes verbose(VERB_OPS, "init module %d: %s", 179238106Sdes i, stack->mod[i]->name); 180238106Sdes fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init)); 181238106Sdes if(!(*stack->mod[i]->init)(env, i)) { 182238106Sdes log_err("module init for module %s failed", 183238106Sdes stack->mod[i]->name); 184238106Sdes return 0; 185238106Sdes } 186238106Sdes } 187238106Sdes return 1; 188238106Sdes} 189238106Sdes 190238106Sdesvoid 191238106Sdesmodstack_desetup(struct module_stack* stack, struct module_env* env) 192238106Sdes{ 193238106Sdes int i; 194238106Sdes for(i=0; i<stack->num; i++) { 195238106Sdes fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit)); 196238106Sdes (*stack->mod[i]->deinit)(env, i); 197238106Sdes } 198238106Sdes stack->num = 0; 199238106Sdes free(stack->mod); 200238106Sdes stack->mod = NULL; 201238106Sdes} 202238106Sdes 203238106Sdesint 204238106Sdesmodstack_find(struct module_stack* stack, const char* name) 205238106Sdes{ 206238106Sdes int i; 207238106Sdes for(i=0; i<stack->num; i++) { 208238106Sdes if(strcmp(stack->mod[i]->name, name) == 0) 209238106Sdes return i; 210238106Sdes } 211238106Sdes return -1; 212238106Sdes} 213