xref: /openbsd-src/usr.sbin/unbound/services/modstack.c (revision 98bc733b08604094f4138174a0ee0bb9faaca4bd)
1933707f3Ssthen /*
2933707f3Ssthen  * services/modstack.c - stack of modules
3933707f3Ssthen  *
4933707f3Ssthen  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5933707f3Ssthen  *
6933707f3Ssthen  * This software is open source.
7933707f3Ssthen  *
8933707f3Ssthen  * Redistribution and use in source and binary forms, with or without
9933707f3Ssthen  * modification, are permitted provided that the following conditions
10933707f3Ssthen  * are met:
11933707f3Ssthen  *
12933707f3Ssthen  * Redistributions of source code must retain the above copyright notice,
13933707f3Ssthen  * this list of conditions and the following disclaimer.
14933707f3Ssthen  *
15933707f3Ssthen  * Redistributions in binary form must reproduce the above copyright notice,
16933707f3Ssthen  * this list of conditions and the following disclaimer in the documentation
17933707f3Ssthen  * and/or other materials provided with the distribution.
18933707f3Ssthen  *
19933707f3Ssthen  * Neither the name of the NLNET LABS nor the names of its contributors may
20933707f3Ssthen  * be used to endorse or promote products derived from this software without
21933707f3Ssthen  * specific prior written permission.
22933707f3Ssthen  *
23933707f3Ssthen  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
245d76a658Ssthen  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
255d76a658Ssthen  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
265d76a658Ssthen  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
275d76a658Ssthen  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
285d76a658Ssthen  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
295d76a658Ssthen  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
305d76a658Ssthen  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
315d76a658Ssthen  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
325d76a658Ssthen  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
335d76a658Ssthen  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34933707f3Ssthen  */
35933707f3Ssthen 
36933707f3Ssthen /**
37933707f3Ssthen  * \file
38933707f3Ssthen  *
39933707f3Ssthen  * This file contains functions to help maintain a stack of modules.
40933707f3Ssthen  */
41933707f3Ssthen #include "config.h"
42933707f3Ssthen #include <ctype.h>
43933707f3Ssthen #include "services/modstack.h"
44933707f3Ssthen #include "util/module.h"
45933707f3Ssthen #include "util/fptr_wlist.h"
4698f3ca02Sbrad #include "dns64/dns64.h"
47933707f3Ssthen #include "iterator/iterator.h"
48933707f3Ssthen #include "validator/validator.h"
492be9e038Ssthen #include "respip/respip.h"
50933707f3Ssthen 
51933707f3Ssthen #ifdef WITH_PYTHONMODULE
52933707f3Ssthen #include "pythonmod/pythonmod.h"
53933707f3Ssthen #endif
54a3167c07Ssthen #ifdef WITH_DYNLIBMODULE
55a3167c07Ssthen #include "dynlibmod/dynlibmod.h"
56a3167c07Ssthen #endif
572ee382b6Ssthen #ifdef USE_CACHEDB
582ee382b6Ssthen #include "cachedb/cachedb.h"
592ee382b6Ssthen #endif
602be9e038Ssthen #ifdef USE_IPSECMOD
612be9e038Ssthen #include "ipsecmod/ipsecmod.h"
622be9e038Ssthen #endif
632be9e038Ssthen #ifdef CLIENT_SUBNET
642be9e038Ssthen #include "edns-subnet/subnetmod.h"
652be9e038Ssthen #endif
668240c1b9Ssthen #ifdef USE_IPSET
678240c1b9Ssthen #include "ipset/ipset.h"
688240c1b9Ssthen #endif
69933707f3Ssthen 
70933707f3Ssthen /** count number of modules (words) in the string */
71933707f3Ssthen static int
72933707f3Ssthen count_modules(const char* s)
73933707f3Ssthen {
74933707f3Ssthen         int num = 0;
75933707f3Ssthen         if(!s)
76933707f3Ssthen                 return 0;
77933707f3Ssthen         while(*s) {
78933707f3Ssthen                 /* skip whitespace */
7998f3ca02Sbrad                 while(*s && isspace((unsigned char)*s))
80933707f3Ssthen                         s++;
8198f3ca02Sbrad                 if(*s && !isspace((unsigned char)*s)) {
82933707f3Ssthen                         /* skip identifier */
83933707f3Ssthen                         num++;
8498f3ca02Sbrad                         while(*s && !isspace((unsigned char)*s))
85933707f3Ssthen                                 s++;
86933707f3Ssthen                 }
87933707f3Ssthen         }
88933707f3Ssthen         return num;
89933707f3Ssthen }
90933707f3Ssthen 
91933707f3Ssthen void
92933707f3Ssthen modstack_init(struct module_stack* stack)
93933707f3Ssthen {
94933707f3Ssthen 	stack->num = 0;
95933707f3Ssthen 	stack->mod = NULL;
96933707f3Ssthen }
97933707f3Ssthen 
98*98bc733bSsthen void
99*98bc733bSsthen modstack_free(struct module_stack* stack)
100*98bc733bSsthen {
101*98bc733bSsthen 	if(!stack)
102*98bc733bSsthen 		return;
103*98bc733bSsthen         stack->num = 0;
104*98bc733bSsthen         free(stack->mod);
105*98bc733bSsthen         stack->mod = NULL;
106*98bc733bSsthen }
107*98bc733bSsthen 
108933707f3Ssthen int
109933707f3Ssthen modstack_config(struct module_stack* stack, const char* module_conf)
110933707f3Ssthen {
111933707f3Ssthen 	int i;
112933707f3Ssthen 	verbose(VERB_QUERY, "module config: \"%s\"", module_conf);
113933707f3Ssthen 	stack->num = count_modules(module_conf);
114933707f3Ssthen 	if(stack->num == 0) {
115933707f3Ssthen 		log_err("error: no modules specified");
116933707f3Ssthen 		return 0;
117933707f3Ssthen 	}
118933707f3Ssthen 	if(stack->num > MAX_MODULE) {
119933707f3Ssthen 		log_err("error: too many modules (%d max %d)",
120933707f3Ssthen 			stack->num, MAX_MODULE);
121933707f3Ssthen 		return 0;
122933707f3Ssthen 	}
123933707f3Ssthen 	stack->mod = (struct module_func_block**)calloc((size_t)
124933707f3Ssthen 		stack->num, sizeof(struct module_func_block*));
125933707f3Ssthen 	if(!stack->mod) {
126933707f3Ssthen 		log_err("out of memory");
127933707f3Ssthen 		return 0;
128933707f3Ssthen 	}
129933707f3Ssthen 	for(i=0; i<stack->num; i++) {
130933707f3Ssthen 		stack->mod[i] = module_factory(&module_conf);
131933707f3Ssthen 		if(!stack->mod[i]) {
132c3b38330Ssthen 			char md[256];
1338b7325afSsthen 			char * s = md;
134c3b38330Ssthen 			snprintf(md, sizeof(md), "%s", module_conf);
1358b7325afSsthen 			/* Leading spaces are present on errors. */
1368b7325afSsthen 			while (*s && isspace((unsigned char)*s))
1378b7325afSsthen 				s++;
1388b7325afSsthen 			if(strchr(s, ' ')) *(strchr(s, ' ')) = 0;
1398b7325afSsthen 			if(strchr(s, '\t')) *(strchr(s, '\t')) = 0;
140c3b38330Ssthen 			log_err("Unknown value in module-config, module: '%s'."
141c3b38330Ssthen 				" This module is not present (not compiled in),"
1428b7325afSsthen 				" See the list of linked modules with unbound -V", s);
143933707f3Ssthen 			return 0;
144933707f3Ssthen 		}
145933707f3Ssthen 	}
146933707f3Ssthen 	return 1;
147933707f3Ssthen }
148933707f3Ssthen 
149933707f3Ssthen /** The list of module names */
150933707f3Ssthen const char**
151933707f3Ssthen module_list_avail(void)
152933707f3Ssthen {
153933707f3Ssthen 	/* these are the modules available */
154933707f3Ssthen 	static const char* names[] = {
15598f3ca02Sbrad 		"dns64",
156933707f3Ssthen #ifdef WITH_PYTHONMODULE
157933707f3Ssthen 		"python",
158933707f3Ssthen #endif
159a3167c07Ssthen #ifdef WITH_DYNLIBMODULE
160a3167c07Ssthen 		"dynlib",
161a3167c07Ssthen #endif
1622ee382b6Ssthen #ifdef USE_CACHEDB
1632ee382b6Ssthen 		"cachedb",
1642ee382b6Ssthen #endif
1652be9e038Ssthen #ifdef USE_IPSECMOD
1662be9e038Ssthen 		"ipsecmod",
1672be9e038Ssthen #endif
1682be9e038Ssthen #ifdef CLIENT_SUBNET
1692be9e038Ssthen 		"subnetcache",
1702be9e038Ssthen #endif
1718240c1b9Ssthen #ifdef USE_IPSET
1728240c1b9Ssthen 		"ipset",
1738240c1b9Ssthen #endif
1742be9e038Ssthen 		"respip",
175933707f3Ssthen 		"validator",
176933707f3Ssthen 		"iterator",
177933707f3Ssthen 		NULL};
178933707f3Ssthen 	return names;
179933707f3Ssthen }
180933707f3Ssthen 
181933707f3Ssthen /** func block get function type */
182933707f3Ssthen typedef struct module_func_block* (*fbgetfunctype)(void);
183933707f3Ssthen 
184933707f3Ssthen /** The list of module func blocks */
185933707f3Ssthen static fbgetfunctype*
186933707f3Ssthen module_funcs_avail(void)
187933707f3Ssthen {
188933707f3Ssthen         static struct module_func_block* (*fb[])(void) = {
18998f3ca02Sbrad 		&dns64_get_funcblock,
190933707f3Ssthen #ifdef WITH_PYTHONMODULE
191933707f3Ssthen 		&pythonmod_get_funcblock,
192933707f3Ssthen #endif
193a3167c07Ssthen #ifdef WITH_DYNLIBMODULE
194a3167c07Ssthen 		&dynlibmod_get_funcblock,
195a3167c07Ssthen #endif
1962ee382b6Ssthen #ifdef USE_CACHEDB
1972ee382b6Ssthen 		&cachedb_get_funcblock,
1982ee382b6Ssthen #endif
1992be9e038Ssthen #ifdef USE_IPSECMOD
2002be9e038Ssthen 		&ipsecmod_get_funcblock,
2012be9e038Ssthen #endif
2022be9e038Ssthen #ifdef CLIENT_SUBNET
2032be9e038Ssthen 		&subnetmod_get_funcblock,
2042be9e038Ssthen #endif
2058240c1b9Ssthen #ifdef USE_IPSET
2068240c1b9Ssthen 		&ipset_get_funcblock,
2078240c1b9Ssthen #endif
2082be9e038Ssthen 		&respip_get_funcblock,
209933707f3Ssthen 		&val_get_funcblock,
210933707f3Ssthen 		&iter_get_funcblock,
211933707f3Ssthen 		NULL};
212933707f3Ssthen 	return fb;
213933707f3Ssthen }
214933707f3Ssthen 
215933707f3Ssthen struct
216933707f3Ssthen module_func_block* module_factory(const char** str)
217933707f3Ssthen {
218933707f3Ssthen         int i = 0;
219933707f3Ssthen         const char* s = *str;
220933707f3Ssthen 	const char** names = module_list_avail();
221933707f3Ssthen 	fbgetfunctype* fb = module_funcs_avail();
22298f3ca02Sbrad         while(*s && isspace((unsigned char)*s))
223933707f3Ssthen                 s++;
224933707f3Ssthen 	while(names[i]) {
225933707f3Ssthen                 if(strncmp(names[i], s, strlen(names[i])) == 0) {
226933707f3Ssthen                         s += strlen(names[i]);
227933707f3Ssthen                         *str = s;
228933707f3Ssthen                         return (*fb[i])();
229933707f3Ssthen                 }
230933707f3Ssthen 		i++;
231933707f3Ssthen         }
232933707f3Ssthen         return NULL;
233933707f3Ssthen }
234933707f3Ssthen 
235933707f3Ssthen int
236*98bc733bSsthen modstack_call_startup(struct module_stack* stack, const char* module_conf,
237933707f3Ssthen 	struct module_env* env)
238933707f3Ssthen {
239933707f3Ssthen         int i;
240933707f3Ssthen         if(stack->num != 0)
241*98bc733bSsthen 		fatal_exit("unexpected already initialised modules");
242933707f3Ssthen         /* fixed setup of the modules */
243933707f3Ssthen         if(!modstack_config(stack, module_conf)) {
244933707f3Ssthen 		return 0;
245933707f3Ssthen         }
246*98bc733bSsthen         for(i=0; i<stack->num; i++) {
247*98bc733bSsthen 		if(stack->mod[i]->startup == NULL)
248*98bc733bSsthen 			continue;
249*98bc733bSsthen                 verbose(VERB_OPS, "startup module %d: %s",
250*98bc733bSsthen                         i, stack->mod[i]->name);
251*98bc733bSsthen                 fptr_ok(fptr_whitelist_mod_startup(stack->mod[i]->startup));
252*98bc733bSsthen                 if(!(*stack->mod[i]->startup)(env, i)) {
253*98bc733bSsthen                         log_err("module startup for module %s failed",
254*98bc733bSsthen                                 stack->mod[i]->name);
255*98bc733bSsthen 			return 0;
256*98bc733bSsthen                 }
257*98bc733bSsthen         }
258*98bc733bSsthen 	return 1;
259*98bc733bSsthen }
260*98bc733bSsthen 
261*98bc733bSsthen int
262*98bc733bSsthen modstack_call_init(struct module_stack* stack, const char* module_conf,
263*98bc733bSsthen 	struct module_env* env)
264*98bc733bSsthen {
265*98bc733bSsthen         int i, changed = 0;
266933707f3Ssthen         env->need_to_validate = 0; /* set by module init below */
267933707f3Ssthen         for(i=0; i<stack->num; i++) {
268*98bc733bSsthen 		while(*module_conf && isspace(*module_conf))
269*98bc733bSsthen 			module_conf++;
270*98bc733bSsthen                 if(strncmp(stack->mod[i]->name, module_conf,
271*98bc733bSsthen 			strlen(stack->mod[i]->name))) {
272*98bc733bSsthen 			if(stack->mod[i]->startup || stack->mod[i]->destartup) {
273*98bc733bSsthen 				log_err("changed module ordering during reload not supported, for module that needs startup");
274*98bc733bSsthen 				return 0;
275*98bc733bSsthen 			} else {
276*98bc733bSsthen 				changed = 1;
277*98bc733bSsthen 			}
278*98bc733bSsthen 		}
279*98bc733bSsthen 		module_conf += strlen(stack->mod[i]->name);
280*98bc733bSsthen 	}
281*98bc733bSsthen 	if(changed) {
282*98bc733bSsthen 		modstack_free(stack);
283*98bc733bSsthen 		if(!modstack_config(stack, module_conf)) {
284*98bc733bSsthen 			return 0;
285*98bc733bSsthen 		}
286*98bc733bSsthen 	}
287*98bc733bSsthen 
288*98bc733bSsthen         for(i=0; i<stack->num; i++) {
289933707f3Ssthen                 verbose(VERB_OPS, "init module %d: %s",
290933707f3Ssthen                         i, stack->mod[i]->name);
291933707f3Ssthen                 fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init));
292933707f3Ssthen                 if(!(*stack->mod[i]->init)(env, i)) {
293933707f3Ssthen                         log_err("module init for module %s failed",
294933707f3Ssthen                                 stack->mod[i]->name);
295933707f3Ssthen 			return 0;
296933707f3Ssthen                 }
297933707f3Ssthen         }
298933707f3Ssthen 	return 1;
299933707f3Ssthen }
300933707f3Ssthen 
301933707f3Ssthen void
302*98bc733bSsthen modstack_call_deinit(struct module_stack* stack, struct module_env* env)
303933707f3Ssthen {
304933707f3Ssthen         int i;
305933707f3Ssthen         for(i=0; i<stack->num; i++) {
306933707f3Ssthen                 fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
307933707f3Ssthen                 (*stack->mod[i]->deinit)(env, i);
308933707f3Ssthen         }
309*98bc733bSsthen }
310*98bc733bSsthen 
311*98bc733bSsthen void
312*98bc733bSsthen modstack_call_destartup(struct module_stack* stack, struct module_env* env)
313*98bc733bSsthen {
314*98bc733bSsthen         int i;
315*98bc733bSsthen         for(i=0; i<stack->num; i++) {
316*98bc733bSsthen 		if(stack->mod[i]->destartup == NULL)
317*98bc733bSsthen 			continue;
318*98bc733bSsthen                 fptr_ok(fptr_whitelist_mod_destartup(stack->mod[i]->destartup));
319*98bc733bSsthen                 (*stack->mod[i]->destartup)(env, i);
320*98bc733bSsthen         }
321933707f3Ssthen }
322933707f3Ssthen 
323933707f3Ssthen int
324933707f3Ssthen modstack_find(struct module_stack* stack, const char* name)
325933707f3Ssthen {
326933707f3Ssthen 	int i;
327933707f3Ssthen 	for(i=0; i<stack->num; i++) {
328933707f3Ssthen 		if(strcmp(stack->mod[i]->name, name) == 0)
329933707f3Ssthen 			return i;
330933707f3Ssthen 	}
331933707f3Ssthen 	return -1;
332933707f3Ssthen }
3332be9e038Ssthen 
3342be9e038Ssthen size_t
3352be9e038Ssthen mod_get_mem(struct module_env* env, const char* name)
3362be9e038Ssthen {
3372be9e038Ssthen 	int m = modstack_find(&env->mesh->mods, name);
3382be9e038Ssthen 	if(m != -1) {
3392be9e038Ssthen 		fptr_ok(fptr_whitelist_mod_get_mem(env->mesh->
3402be9e038Ssthen 			mods.mod[m]->get_mem));
3412be9e038Ssthen 		return (*env->mesh->mods.mod[m]->get_mem)(env, m);
3422be9e038Ssthen 	}
3432be9e038Ssthen 	return 0;
3442be9e038Ssthen }
345