2 * util/module.c - module interface
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
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.
37 * Implementation of module.h.
41 #include "util/module.h"
42 #include "sldns/wire2str.h"
45 strextstate(enum module_ext_state s)
48 case module_state_initial: return "module_state_initial";
49 case module_wait_reply: return "module_wait_reply";
50 case module_wait_module: return "module_wait_module";
51 case module_restart_next: return "module_restart_next";
52 case module_wait_subquery: return "module_wait_subquery";
53 case module_error: return "module_error";
54 case module_finished: return "module_finished";
56 return "bad_extstate_value";
60 strmodulevent(enum module_ev e)
63 case module_event_new: return "module_event_new";
64 case module_event_pass: return "module_event_pass";
65 case module_event_reply: return "module_event_reply";
66 case module_event_noreply: return "module_event_noreply";
67 case module_event_capsfail: return "module_event_capsfail";
68 case module_event_moddone: return "module_event_moddone";
69 case module_event_error: return "module_event_error";
71 return "bad_event_value";
75 edns_known_options_init(struct module_env* env)
77 env->edns_known_options_num = 0;
78 env->edns_known_options = (struct edns_known_option*)calloc(
79 MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
80 if(!env->edns_known_options) return 0;
85 edns_known_options_delete(struct module_env* env)
87 free(env->edns_known_options);
88 env->edns_known_options = NULL;
89 env->edns_known_options_num = 0;
93 edns_register_option(uint16_t opt_code, int bypass_cache_stage,
94 int no_aggregation, struct module_env* env)
98 log_err("invalid edns registration: "
99 "trying to register option after module init phase");
104 * Checking if we are full first is faster but it does not provide
105 * the option to change the flags when the array is full.
106 * It only impacts unbound initialization, leave it for now.
108 /* Check if the option is already registered. */
109 for(i=0; i<env->edns_known_options_num; i++)
110 if(env->edns_known_options[i].opt_code == opt_code)
112 /* If it is not yet registered check if we have space to add a new one. */
113 if(i == env->edns_known_options_num) {
114 if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
115 log_err("invalid edns registration: maximum options reached");
118 env->edns_known_options_num++;
120 env->edns_known_options[i].opt_code = opt_code;
121 env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
122 env->edns_known_options[i].no_aggregation = no_aggregation;
127 inplace_cb_reply_register_generic(inplace_cb_reply_func_type* cb,
128 enum inplace_cb_list_type type, void* cb_arg, struct module_env* env)
130 struct inplace_cb_reply* callback;
131 struct inplace_cb_reply** prevp;
133 log_err("invalid edns callback registration: "
134 "trying to register callback after module init phase");
138 callback = (struct inplace_cb_reply*)calloc(1, sizeof(*callback));
139 if(callback == NULL) {
140 log_err("out of memory during edns callback registration.");
143 callback->next = NULL;
145 callback->cb_arg = cb_arg;
147 prevp = (struct inplace_cb_reply**) &env->inplace_cb_lists[type];
148 /* append at end of list */
149 while(*prevp != NULL)
150 prevp = &((*prevp)->next);
156 inplace_cb_reply_register(inplace_cb_reply_func_type* cb, void* cb_arg,
157 struct module_env* env)
159 return inplace_cb_reply_register_generic(cb, inplace_cb_reply, cb_arg,
164 inplace_cb_reply_cache_register(inplace_cb_reply_func_type* cb, void* cb_arg,
165 struct module_env* env)
167 return inplace_cb_reply_register_generic(cb, inplace_cb_reply_cache,
172 inplace_cb_reply_local_register(inplace_cb_reply_func_type* cb, void* cb_arg,
173 struct module_env* env)
175 return inplace_cb_reply_register_generic(cb, inplace_cb_reply_local,
180 inplace_cb_reply_servfail_register(inplace_cb_reply_func_type* cb, void* cb_arg,
181 struct module_env* env)
183 return inplace_cb_reply_register_generic(cb, inplace_cb_reply_servfail,
188 inplace_cb_reply_delete_generic(struct module_env* env,
189 enum inplace_cb_list_type type)
191 struct inplace_cb_reply* curr = env->inplace_cb_lists[type];
192 struct inplace_cb_reply* tmp;
199 /* update head pointer */
200 env->inplace_cb_lists[type] = NULL;
203 void inplace_cb_reply_delete(struct module_env* env)
205 inplace_cb_reply_delete_generic(env, inplace_cb_reply);
208 void inplace_cb_reply_cache_delete(struct module_env* env)
210 inplace_cb_reply_delete_generic(env, inplace_cb_reply_cache);
213 void inplace_cb_reply_servfail_delete(struct module_env* env)
215 inplace_cb_reply_delete_generic(env, inplace_cb_reply_servfail);
219 inplace_cb_query_register(inplace_cb_query_func_type* cb, void* cb_arg,
220 struct module_env* env)
222 struct inplace_cb_query* callback;
223 struct inplace_cb_query** prevp;
225 log_err("invalid edns callback registration: "
226 "trying to register callback after module init phase");
230 callback = (struct inplace_cb_query*)calloc(1, sizeof(*callback));
231 if(callback == NULL) {
232 log_err("out of memory during edns callback registration.");
235 callback->next = NULL;
237 callback->cb_arg = cb_arg;
239 prevp = (struct inplace_cb_query**)
240 &env->inplace_cb_lists[inplace_cb_query];
241 /* append at end of list */
242 while(*prevp != NULL)
243 prevp = &((*prevp)->next);
249 inplace_cb_query_delete(struct module_env* env)
251 struct inplace_cb_query* curr = env->inplace_cb_lists[inplace_cb_query];
252 struct inplace_cb_query* tmp;
259 /* update head pointer */
260 env->inplace_cb_lists[inplace_cb_query] = NULL;
264 inplace_cb_lists_delete(struct module_env* env)
266 inplace_cb_reply_delete(env);
267 inplace_cb_reply_cache_delete(env);
268 inplace_cb_reply_servfail_delete(env);
269 inplace_cb_query_delete(env);
272 struct edns_known_option*
273 edns_option_is_known(uint16_t opt_code, struct module_env* env)
276 for(i=0; i<env->edns_known_options_num; i++)
277 if(env->edns_known_options[i].opt_code == opt_code)
278 return env->edns_known_options + i;
283 edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
286 for(; list; list=list->next)
287 for(i=0; i<env->edns_known_options_num; i++)
288 if(env->edns_known_options[i].opt_code == list->opt_code &&
289 env->edns_known_options[i].bypass_cache_stage == 1)
295 edns_unique_mesh_state(struct edns_option* list, struct module_env* env)
298 for(; list; list=list->next)
299 for(i=0; i<env->edns_known_options_num; i++)
300 if(env->edns_known_options[i].opt_code == list->opt_code &&
301 env->edns_known_options[i].no_aggregation == 1)
307 log_edns_known_options(enum verbosity_value level, struct module_env* env)
312 if(env->edns_known_options_num > 0 && verbosity >= level) {
313 verbose(level, "EDNS known options:");
314 verbose(level, " Code: Bypass_cache_stage: Aggregate_mesh:");
315 for(i=0; i<env->edns_known_options_num; i++) {
318 (void)sldns_wire2str_edns_option_code_print(&s, &slen,
319 env->edns_known_options[i].opt_code);
320 verbose(level, " %-8.8s %-19s %-15s", str,
321 env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
322 env->edns_known_options[i].no_aggregation?"NO":"YES");