xref: /freebsd/contrib/unbound/util/module.c (revision 65b390aa03158608c95d842609dcc4c7129d6476)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * util/module.c - module interface
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav /**
36b7579f77SDag-Erling Smørgrav  * \file
37b7579f77SDag-Erling Smørgrav  * Implementation of module.h.
38b7579f77SDag-Erling Smørgrav  */
39b7579f77SDag-Erling Smørgrav 
40b7579f77SDag-Erling Smørgrav #include "config.h"
41b7579f77SDag-Erling Smørgrav #include "util/module.h"
42bc892140SDag-Erling Smørgrav #include "sldns/wire2str.h"
43b7579f77SDag-Erling Smørgrav 
44b7579f77SDag-Erling Smørgrav const char*
45b7579f77SDag-Erling Smørgrav strextstate(enum module_ext_state s)
46b7579f77SDag-Erling Smørgrav {
47b7579f77SDag-Erling Smørgrav 	switch(s) {
48b7579f77SDag-Erling Smørgrav 	case module_state_initial: return "module_state_initial";
49b7579f77SDag-Erling Smørgrav 	case module_wait_reply: return "module_wait_reply";
50b7579f77SDag-Erling Smørgrav 	case module_wait_module: return "module_wait_module";
51b7579f77SDag-Erling Smørgrav 	case module_restart_next: return "module_restart_next";
52b7579f77SDag-Erling Smørgrav 	case module_wait_subquery: return "module_wait_subquery";
53b7579f77SDag-Erling Smørgrav 	case module_error: return "module_error";
54b7579f77SDag-Erling Smørgrav 	case module_finished: return "module_finished";
55b7579f77SDag-Erling Smørgrav 	}
56b7579f77SDag-Erling Smørgrav 	return "bad_extstate_value";
57b7579f77SDag-Erling Smørgrav }
58b7579f77SDag-Erling Smørgrav 
59b7579f77SDag-Erling Smørgrav const char*
60b7579f77SDag-Erling Smørgrav strmodulevent(enum module_ev e)
61b7579f77SDag-Erling Smørgrav {
62b7579f77SDag-Erling Smørgrav 	switch(e) {
63b7579f77SDag-Erling Smørgrav 	case module_event_new: return "module_event_new";
64b7579f77SDag-Erling Smørgrav 	case module_event_pass: return "module_event_pass";
65b7579f77SDag-Erling Smørgrav 	case module_event_reply: return "module_event_reply";
66b7579f77SDag-Erling Smørgrav 	case module_event_noreply: return "module_event_noreply";
67b7579f77SDag-Erling Smørgrav 	case module_event_capsfail: return "module_event_capsfail";
68b7579f77SDag-Erling Smørgrav 	case module_event_moddone: return "module_event_moddone";
69b7579f77SDag-Erling Smørgrav 	case module_event_error: return "module_event_error";
70b7579f77SDag-Erling Smørgrav 	}
71b7579f77SDag-Erling Smørgrav 	return "bad_event_value";
72b7579f77SDag-Erling Smørgrav }
73bc892140SDag-Erling Smørgrav 
74bc892140SDag-Erling Smørgrav int
75bc892140SDag-Erling Smørgrav edns_known_options_init(struct module_env* env)
76bc892140SDag-Erling Smørgrav {
77bc892140SDag-Erling Smørgrav 	env->edns_known_options_num = 0;
78bc892140SDag-Erling Smørgrav 	env->edns_known_options = (struct edns_known_option*)calloc(
79bc892140SDag-Erling Smørgrav 		MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
80bc892140SDag-Erling Smørgrav 	if(!env->edns_known_options) return 0;
81bc892140SDag-Erling Smørgrav 	return 1;
82bc892140SDag-Erling Smørgrav }
83bc892140SDag-Erling Smørgrav 
84bc892140SDag-Erling Smørgrav void
85bc892140SDag-Erling Smørgrav edns_known_options_delete(struct module_env* env)
86bc892140SDag-Erling Smørgrav {
87bc892140SDag-Erling Smørgrav 	free(env->edns_known_options);
88bc892140SDag-Erling Smørgrav 	env->edns_known_options = NULL;
89bc892140SDag-Erling Smørgrav 	env->edns_known_options_num = 0;
90bc892140SDag-Erling Smørgrav }
91bc892140SDag-Erling Smørgrav 
92bc892140SDag-Erling Smørgrav int
93bc892140SDag-Erling Smørgrav edns_register_option(uint16_t opt_code, int bypass_cache_stage,
94bc892140SDag-Erling Smørgrav 	int no_aggregation, struct module_env* env)
95bc892140SDag-Erling Smørgrav {
96bc892140SDag-Erling Smørgrav 	size_t i;
97bc892140SDag-Erling Smørgrav 	if(env->worker) {
98bc892140SDag-Erling Smørgrav 		log_err("invalid edns registration: "
99bc892140SDag-Erling Smørgrav 			"trying to register option after module init phase");
100bc892140SDag-Erling Smørgrav 		return 0;
101bc892140SDag-Erling Smørgrav 	}
102bc892140SDag-Erling Smørgrav 
103bc892140SDag-Erling Smørgrav 	/**
104bc892140SDag-Erling Smørgrav 	 * Checking if we are full first is faster but it does not provide
105bc892140SDag-Erling Smørgrav 	 * the option to change the flags when the array is full.
106bc892140SDag-Erling Smørgrav 	 * It only impacts unbound initialization, leave it for now.
107bc892140SDag-Erling Smørgrav 	 */
108bc892140SDag-Erling Smørgrav 	/* Check if the option is already registered. */
109bc892140SDag-Erling Smørgrav 	for(i=0; i<env->edns_known_options_num; i++)
110bc892140SDag-Erling Smørgrav 		if(env->edns_known_options[i].opt_code == opt_code)
111bc892140SDag-Erling Smørgrav 			break;
112bc892140SDag-Erling Smørgrav 	/* If it is not yet registered check if we have space to add a new one. */
113bc892140SDag-Erling Smørgrav 	if(i == env->edns_known_options_num) {
114bc892140SDag-Erling Smørgrav 		if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
115bc892140SDag-Erling Smørgrav 			log_err("invalid edns registration: maximum options reached");
116bc892140SDag-Erling Smørgrav 			return 0;
117bc892140SDag-Erling Smørgrav 		}
118bc892140SDag-Erling Smørgrav 		env->edns_known_options_num++;
119bc892140SDag-Erling Smørgrav 	}
120bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].opt_code = opt_code;
121bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
122bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].no_aggregation = no_aggregation;
123bc892140SDag-Erling Smørgrav 	return 1;
124bc892140SDag-Erling Smørgrav }
125bc892140SDag-Erling Smørgrav 
126*65b390aaSDag-Erling Smørgrav int
127*65b390aaSDag-Erling Smørgrav inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
128*65b390aaSDag-Erling Smørgrav 	struct module_env* env, int id)
129bc892140SDag-Erling Smørgrav {
130*65b390aaSDag-Erling Smørgrav 	struct inplace_cb* callback;
131*65b390aaSDag-Erling Smørgrav 	struct inplace_cb** prevp;
132bc892140SDag-Erling Smørgrav 	if(env->worker) {
133bc892140SDag-Erling Smørgrav 		log_err("invalid edns callback registration: "
134bc892140SDag-Erling Smørgrav 			"trying to register callback after module init phase");
135bc892140SDag-Erling Smørgrav 		return 0;
136bc892140SDag-Erling Smørgrav 	}
137bc892140SDag-Erling Smørgrav 
138*65b390aaSDag-Erling Smørgrav 	callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
139bc892140SDag-Erling Smørgrav 	if(callback == NULL) {
140bc892140SDag-Erling Smørgrav 		log_err("out of memory during edns callback registration.");
141bc892140SDag-Erling Smørgrav 		return 0;
142bc892140SDag-Erling Smørgrav 	}
143*65b390aaSDag-Erling Smørgrav 	callback->id = id;
144bc892140SDag-Erling Smørgrav 	callback->next = NULL;
145bc892140SDag-Erling Smørgrav 	callback->cb = cb;
146*65b390aaSDag-Erling Smørgrav 	callback->cb_arg = cbarg;
147bc892140SDag-Erling Smørgrav 
148*65b390aaSDag-Erling Smørgrav 	prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
149bc892140SDag-Erling Smørgrav 	/* append at end of list */
150bc892140SDag-Erling Smørgrav 	while(*prevp != NULL)
151bc892140SDag-Erling Smørgrav 		prevp = &((*prevp)->next);
152bc892140SDag-Erling Smørgrav 	*prevp = callback;
153bc892140SDag-Erling Smørgrav 	return 1;
154bc892140SDag-Erling Smørgrav }
155bc892140SDag-Erling Smørgrav 
156bc892140SDag-Erling Smørgrav void
157*65b390aaSDag-Erling Smørgrav inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
158*65b390aaSDag-Erling Smørgrav 	int id)
159bc892140SDag-Erling Smørgrav {
160*65b390aaSDag-Erling Smørgrav 	struct inplace_cb* temp = env->inplace_cb_lists[type];
161*65b390aaSDag-Erling Smørgrav 	struct inplace_cb* prev = NULL;
162bc892140SDag-Erling Smørgrav 
163*65b390aaSDag-Erling Smørgrav 	while(temp) {
164*65b390aaSDag-Erling Smørgrav 		if(temp->id == id) {
165*65b390aaSDag-Erling Smørgrav 			if(!prev) {
166*65b390aaSDag-Erling Smørgrav 				env->inplace_cb_lists[type] = temp->next;
167*65b390aaSDag-Erling Smørgrav 				free(temp);
168*65b390aaSDag-Erling Smørgrav 				temp = env->inplace_cb_lists[type];
169*65b390aaSDag-Erling Smørgrav 			}
170*65b390aaSDag-Erling Smørgrav 			else {
171*65b390aaSDag-Erling Smørgrav 				prev->next = temp->next;
172*65b390aaSDag-Erling Smørgrav 				free(temp);
173*65b390aaSDag-Erling Smørgrav 				temp = prev->next;
174*65b390aaSDag-Erling Smørgrav 			}
175*65b390aaSDag-Erling Smørgrav 		}
176*65b390aaSDag-Erling Smørgrav 		else {
177*65b390aaSDag-Erling Smørgrav 			prev = temp;
178*65b390aaSDag-Erling Smørgrav 			temp = temp->next;
179*65b390aaSDag-Erling Smørgrav 		}
180*65b390aaSDag-Erling Smørgrav 	}
181bc892140SDag-Erling Smørgrav }
182bc892140SDag-Erling Smørgrav 
183bc892140SDag-Erling Smørgrav struct edns_known_option*
184bc892140SDag-Erling Smørgrav edns_option_is_known(uint16_t opt_code, struct module_env* env)
185bc892140SDag-Erling Smørgrav {
186bc892140SDag-Erling Smørgrav 	size_t i;
187bc892140SDag-Erling Smørgrav 	for(i=0; i<env->edns_known_options_num; i++)
188bc892140SDag-Erling Smørgrav 		if(env->edns_known_options[i].opt_code == opt_code)
189bc892140SDag-Erling Smørgrav 			return env->edns_known_options + i;
190bc892140SDag-Erling Smørgrav 	return NULL;
191bc892140SDag-Erling Smørgrav }
192bc892140SDag-Erling Smørgrav 
193bc892140SDag-Erling Smørgrav int
194bc892140SDag-Erling Smørgrav edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
195bc892140SDag-Erling Smørgrav {
196bc892140SDag-Erling Smørgrav 	size_t i;
197bc892140SDag-Erling Smørgrav 	for(; list; list=list->next)
198bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++)
199bc892140SDag-Erling Smørgrav 			if(env->edns_known_options[i].opt_code == list->opt_code &&
200bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].bypass_cache_stage == 1)
201bc892140SDag-Erling Smørgrav 					return 1;
202bc892140SDag-Erling Smørgrav 	return 0;
203bc892140SDag-Erling Smørgrav }
204bc892140SDag-Erling Smørgrav 
205bc892140SDag-Erling Smørgrav int
206*65b390aaSDag-Erling Smørgrav unique_mesh_state(struct edns_option* list, struct module_env* env)
207bc892140SDag-Erling Smørgrav {
208bc892140SDag-Erling Smørgrav 	size_t i;
209*65b390aaSDag-Erling Smørgrav 	if(env->unique_mesh)
210*65b390aaSDag-Erling Smørgrav 		return 1;
211bc892140SDag-Erling Smørgrav 	for(; list; list=list->next)
212bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++)
213bc892140SDag-Erling Smørgrav 			if(env->edns_known_options[i].opt_code == list->opt_code &&
214bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].no_aggregation == 1)
215bc892140SDag-Erling Smørgrav 					return 1;
216bc892140SDag-Erling Smørgrav 	return 0;
217bc892140SDag-Erling Smørgrav }
218bc892140SDag-Erling Smørgrav 
219bc892140SDag-Erling Smørgrav void
220bc892140SDag-Erling Smørgrav log_edns_known_options(enum verbosity_value level, struct module_env* env)
221bc892140SDag-Erling Smørgrav {
222bc892140SDag-Erling Smørgrav 	size_t i;
223bc892140SDag-Erling Smørgrav 	char str[32], *s;
224bc892140SDag-Erling Smørgrav 	size_t slen;
225bc892140SDag-Erling Smørgrav 	if(env->edns_known_options_num > 0 && verbosity >= level) {
226bc892140SDag-Erling Smørgrav 		verbose(level, "EDNS known options:");
227bc892140SDag-Erling Smørgrav 		verbose(level, "  Code:    Bypass_cache_stage: Aggregate_mesh:");
228bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++) {
229bc892140SDag-Erling Smørgrav 			s = str;
230bc892140SDag-Erling Smørgrav 			slen = sizeof(str);
231bc892140SDag-Erling Smørgrav 			(void)sldns_wire2str_edns_option_code_print(&s, &slen,
232bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].opt_code);
233bc892140SDag-Erling Smørgrav 			verbose(level, "  %-8.8s %-19s %-15s", str,
234bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
235bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].no_aggregation?"NO":"YES");
236bc892140SDag-Erling Smørgrav 		}
237bc892140SDag-Erling Smørgrav 	}
238bc892140SDag-Erling Smørgrav }
239