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