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