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