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