Coverage Report

Created: 2023-06-07 06:26

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