xref: /freebsd/contrib/unbound/util/module.c (revision a39a5a6905612447def27b66ffe73b9d11efd80c)
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"
43*a39a5a69SCy Schubert #include "util/config_file.h"
44*a39a5a69SCy Schubert #include "util/regional.h"
45*a39a5a69SCy Schubert #include "util/data/dname.h"
46*a39a5a69SCy Schubert #include "util/net_help.h"
47b7579f77SDag-Erling Smørgrav 
48b7579f77SDag-Erling Smørgrav const char*
49b7579f77SDag-Erling Smørgrav strextstate(enum module_ext_state s)
50b7579f77SDag-Erling Smørgrav {
51b7579f77SDag-Erling Smørgrav 	switch(s) {
52b7579f77SDag-Erling Smørgrav 	case module_state_initial: return "module_state_initial";
53b7579f77SDag-Erling Smørgrav 	case module_wait_reply: return "module_wait_reply";
54b7579f77SDag-Erling Smørgrav 	case module_wait_module: return "module_wait_module";
55b7579f77SDag-Erling Smørgrav 	case module_restart_next: return "module_restart_next";
56b7579f77SDag-Erling Smørgrav 	case module_wait_subquery: return "module_wait_subquery";
57b7579f77SDag-Erling Smørgrav 	case module_error: return "module_error";
58b7579f77SDag-Erling Smørgrav 	case module_finished: return "module_finished";
59b7579f77SDag-Erling Smørgrav 	}
60b7579f77SDag-Erling Smørgrav 	return "bad_extstate_value";
61b7579f77SDag-Erling Smørgrav }
62b7579f77SDag-Erling Smørgrav 
63b7579f77SDag-Erling Smørgrav const char*
64b7579f77SDag-Erling Smørgrav strmodulevent(enum module_ev e)
65b7579f77SDag-Erling Smørgrav {
66b7579f77SDag-Erling Smørgrav 	switch(e) {
67b7579f77SDag-Erling Smørgrav 	case module_event_new: return "module_event_new";
68b7579f77SDag-Erling Smørgrav 	case module_event_pass: return "module_event_pass";
69b7579f77SDag-Erling Smørgrav 	case module_event_reply: return "module_event_reply";
70b7579f77SDag-Erling Smørgrav 	case module_event_noreply: return "module_event_noreply";
71b7579f77SDag-Erling Smørgrav 	case module_event_capsfail: return "module_event_capsfail";
72b7579f77SDag-Erling Smørgrav 	case module_event_moddone: return "module_event_moddone";
73b7579f77SDag-Erling Smørgrav 	case module_event_error: return "module_event_error";
74b7579f77SDag-Erling Smørgrav 	}
75b7579f77SDag-Erling Smørgrav 	return "bad_event_value";
76b7579f77SDag-Erling Smørgrav }
77bc892140SDag-Erling Smørgrav 
78*a39a5a69SCy Schubert void errinf(struct module_qstate* qstate, const char* str)
79*a39a5a69SCy Schubert {
80*a39a5a69SCy Schubert 	errinf_ede(qstate, str, LDNS_EDE_NONE);
81*a39a5a69SCy Schubert }
82*a39a5a69SCy Schubert 
83*a39a5a69SCy Schubert void errinf_ede(struct module_qstate* qstate,
84*a39a5a69SCy Schubert 	const char* str, sldns_ede_code reason_bogus)
85*a39a5a69SCy Schubert {
86*a39a5a69SCy Schubert 	struct errinf_strlist* p;
87*a39a5a69SCy Schubert 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str)
88*a39a5a69SCy Schubert 		return;
89*a39a5a69SCy Schubert 	p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
90*a39a5a69SCy Schubert 	if(!p) {
91*a39a5a69SCy Schubert 		log_err("malloc failure in validator-error-info string");
92*a39a5a69SCy Schubert 		return;
93*a39a5a69SCy Schubert 	}
94*a39a5a69SCy Schubert 	p->next = NULL;
95*a39a5a69SCy Schubert 	p->str = regional_strdup(qstate->region, str);
96*a39a5a69SCy Schubert 	p->reason_bogus = reason_bogus;
97*a39a5a69SCy Schubert 	if(!p->str) {
98*a39a5a69SCy Schubert 		log_err("malloc failure in validator-error-info string");
99*a39a5a69SCy Schubert 		return;
100*a39a5a69SCy Schubert 	}
101*a39a5a69SCy Schubert 	/* add at end */
102*a39a5a69SCy Schubert 	if(qstate->errinf) {
103*a39a5a69SCy Schubert 		struct errinf_strlist* q = qstate->errinf;
104*a39a5a69SCy Schubert 		while(q->next)
105*a39a5a69SCy Schubert 			q = q->next;
106*a39a5a69SCy Schubert 		q->next = p;
107*a39a5a69SCy Schubert 	} else	qstate->errinf = p;
108*a39a5a69SCy Schubert }
109*a39a5a69SCy Schubert 
110*a39a5a69SCy Schubert void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
111*a39a5a69SCy Schubert {
112*a39a5a69SCy Schubert 	struct sock_list* p;
113*a39a5a69SCy Schubert 	if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
114*a39a5a69SCy Schubert 		return;
115*a39a5a69SCy Schubert 	for(p=origin; p; p=p->next) {
116*a39a5a69SCy Schubert 		char buf[256];
117*a39a5a69SCy Schubert 		if(p == origin)
118*a39a5a69SCy Schubert 			snprintf(buf, sizeof(buf), "from ");
119*a39a5a69SCy Schubert 		else	snprintf(buf, sizeof(buf), "and ");
120*a39a5a69SCy Schubert 		if(p->len == 0)
121*a39a5a69SCy Schubert 			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
122*a39a5a69SCy Schubert 				"cache");
123*a39a5a69SCy Schubert 		else
124*a39a5a69SCy Schubert 			addr_to_str(&p->addr, p->len, buf+strlen(buf),
125*a39a5a69SCy Schubert 				sizeof(buf)-strlen(buf));
126*a39a5a69SCy Schubert 		errinf(qstate, buf);
127*a39a5a69SCy Schubert 	}
128*a39a5a69SCy Schubert }
129*a39a5a69SCy Schubert 
130*a39a5a69SCy Schubert char* errinf_to_str_bogus(struct module_qstate* qstate)
131*a39a5a69SCy Schubert {
132*a39a5a69SCy Schubert 	char buf[20480];
133*a39a5a69SCy Schubert 	char* p = buf;
134*a39a5a69SCy Schubert 	size_t left = sizeof(buf);
135*a39a5a69SCy Schubert 	struct errinf_strlist* s;
136*a39a5a69SCy Schubert 	char dname[LDNS_MAX_DOMAINLEN+1];
137*a39a5a69SCy Schubert 	char t[16], c[16];
138*a39a5a69SCy Schubert 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
139*a39a5a69SCy Schubert 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
140*a39a5a69SCy Schubert 	dname_str(qstate->qinfo.qname, dname);
141*a39a5a69SCy Schubert 	snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
142*a39a5a69SCy Schubert 	left -= strlen(p); p += strlen(p);
143*a39a5a69SCy Schubert 	if(!qstate->errinf)
144*a39a5a69SCy Schubert 		snprintf(p, left, " misc failure");
145*a39a5a69SCy Schubert 	else for(s=qstate->errinf; s; s=s->next) {
146*a39a5a69SCy Schubert 		snprintf(p, left, " %s", s->str);
147*a39a5a69SCy Schubert 		left -= strlen(p); p += strlen(p);
148*a39a5a69SCy Schubert 	}
149*a39a5a69SCy Schubert 	p = strdup(buf);
150*a39a5a69SCy Schubert 	if(!p)
151*a39a5a69SCy Schubert 		log_err("malloc failure in errinf_to_str");
152*a39a5a69SCy Schubert 	return p;
153*a39a5a69SCy Schubert }
154*a39a5a69SCy Schubert 
155*a39a5a69SCy Schubert sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
156*a39a5a69SCy Schubert {
157*a39a5a69SCy Schubert 	struct errinf_strlist* s;
158*a39a5a69SCy Schubert 	for(s=qstate->errinf; s; s=s->next) {
159*a39a5a69SCy Schubert 		if (s->reason_bogus != LDNS_EDE_NONE) {
160*a39a5a69SCy Schubert 			return s->reason_bogus;
161*a39a5a69SCy Schubert 		}
162*a39a5a69SCy Schubert 	}
163*a39a5a69SCy Schubert 	return LDNS_EDE_NONE;
164*a39a5a69SCy Schubert }
165*a39a5a69SCy Schubert 
166*a39a5a69SCy Schubert char* errinf_to_str_servfail(struct module_qstate* qstate)
167*a39a5a69SCy Schubert {
168*a39a5a69SCy Schubert 	char buf[20480];
169*a39a5a69SCy Schubert 	char* p = buf;
170*a39a5a69SCy Schubert 	size_t left = sizeof(buf);
171*a39a5a69SCy Schubert 	struct errinf_strlist* s;
172*a39a5a69SCy Schubert 	char dname[LDNS_MAX_DOMAINLEN+1];
173*a39a5a69SCy Schubert 	char t[16], c[16];
174*a39a5a69SCy Schubert 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
175*a39a5a69SCy Schubert 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
176*a39a5a69SCy Schubert 	dname_str(qstate->qinfo.qname, dname);
177*a39a5a69SCy Schubert 	snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
178*a39a5a69SCy Schubert 	left -= strlen(p); p += strlen(p);
179*a39a5a69SCy Schubert 	if(!qstate->errinf)
180*a39a5a69SCy Schubert 		snprintf(p, left, " misc failure");
181*a39a5a69SCy Schubert 	else for(s=qstate->errinf; s; s=s->next) {
182*a39a5a69SCy Schubert 		snprintf(p, left, " %s", s->str);
183*a39a5a69SCy Schubert 		left -= strlen(p); p += strlen(p);
184*a39a5a69SCy Schubert 	}
185*a39a5a69SCy Schubert 	p = strdup(buf);
186*a39a5a69SCy Schubert 	if(!p)
187*a39a5a69SCy Schubert 		log_err("malloc failure in errinf_to_str");
188*a39a5a69SCy Schubert 	return p;
189*a39a5a69SCy Schubert }
190*a39a5a69SCy Schubert 
191*a39a5a69SCy Schubert void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
192*a39a5a69SCy Schubert {
193*a39a5a69SCy Schubert 	char buf[1024];
194*a39a5a69SCy Schubert 	char dname[LDNS_MAX_DOMAINLEN+1];
195*a39a5a69SCy Schubert 	char t[16], c[16];
196*a39a5a69SCy Schubert 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
197*a39a5a69SCy Schubert 		return;
198*a39a5a69SCy Schubert 	sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
199*a39a5a69SCy Schubert 	sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
200*a39a5a69SCy Schubert 	dname_str(rr->rk.dname, dname);
201*a39a5a69SCy Schubert 	snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
202*a39a5a69SCy Schubert 	errinf(qstate, buf);
203*a39a5a69SCy Schubert }
204*a39a5a69SCy Schubert 
205*a39a5a69SCy Schubert void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
206*a39a5a69SCy Schubert {
207*a39a5a69SCy Schubert 	char b[1024];
208*a39a5a69SCy Schubert 	char buf[LDNS_MAX_DOMAINLEN+1];
209*a39a5a69SCy Schubert 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
210*a39a5a69SCy Schubert 		return;
211*a39a5a69SCy Schubert 	dname_str(dname, buf);
212*a39a5a69SCy Schubert 	snprintf(b, sizeof(b), "%s %s", str, buf);
213*a39a5a69SCy Schubert 	errinf(qstate, b);
214*a39a5a69SCy Schubert }
215*a39a5a69SCy Schubert 
216bc892140SDag-Erling Smørgrav int
217bc892140SDag-Erling Smørgrav edns_known_options_init(struct module_env* env)
218bc892140SDag-Erling Smørgrav {
219bc892140SDag-Erling Smørgrav 	env->edns_known_options_num = 0;
220bc892140SDag-Erling Smørgrav 	env->edns_known_options = (struct edns_known_option*)calloc(
221bc892140SDag-Erling Smørgrav 		MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
222bc892140SDag-Erling Smørgrav 	if(!env->edns_known_options) return 0;
223bc892140SDag-Erling Smørgrav 	return 1;
224bc892140SDag-Erling Smørgrav }
225bc892140SDag-Erling Smørgrav 
226bc892140SDag-Erling Smørgrav void
227bc892140SDag-Erling Smørgrav edns_known_options_delete(struct module_env* env)
228bc892140SDag-Erling Smørgrav {
229bc892140SDag-Erling Smørgrav 	free(env->edns_known_options);
230bc892140SDag-Erling Smørgrav 	env->edns_known_options = NULL;
231bc892140SDag-Erling Smørgrav 	env->edns_known_options_num = 0;
232bc892140SDag-Erling Smørgrav }
233bc892140SDag-Erling Smørgrav 
234bc892140SDag-Erling Smørgrav int
235bc892140SDag-Erling Smørgrav edns_register_option(uint16_t opt_code, int bypass_cache_stage,
236bc892140SDag-Erling Smørgrav 	int no_aggregation, struct module_env* env)
237bc892140SDag-Erling Smørgrav {
238bc892140SDag-Erling Smørgrav 	size_t i;
239bc892140SDag-Erling Smørgrav 	if(env->worker) {
240bc892140SDag-Erling Smørgrav 		log_err("invalid edns registration: "
241bc892140SDag-Erling Smørgrav 			"trying to register option after module init phase");
242bc892140SDag-Erling Smørgrav 		return 0;
243bc892140SDag-Erling Smørgrav 	}
244bc892140SDag-Erling Smørgrav 
245bc892140SDag-Erling Smørgrav 	/**
246bc892140SDag-Erling Smørgrav 	 * Checking if we are full first is faster but it does not provide
247bc892140SDag-Erling Smørgrav 	 * the option to change the flags when the array is full.
248bc892140SDag-Erling Smørgrav 	 * It only impacts unbound initialization, leave it for now.
249bc892140SDag-Erling Smørgrav 	 */
250bc892140SDag-Erling Smørgrav 	/* Check if the option is already registered. */
251bc892140SDag-Erling Smørgrav 	for(i=0; i<env->edns_known_options_num; i++)
252bc892140SDag-Erling Smørgrav 		if(env->edns_known_options[i].opt_code == opt_code)
253bc892140SDag-Erling Smørgrav 			break;
254bc892140SDag-Erling Smørgrav 	/* If it is not yet registered check if we have space to add a new one. */
255bc892140SDag-Erling Smørgrav 	if(i == env->edns_known_options_num) {
256bc892140SDag-Erling Smørgrav 		if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
257bc892140SDag-Erling Smørgrav 			log_err("invalid edns registration: maximum options reached");
258bc892140SDag-Erling Smørgrav 			return 0;
259bc892140SDag-Erling Smørgrav 		}
260bc892140SDag-Erling Smørgrav 		env->edns_known_options_num++;
261bc892140SDag-Erling Smørgrav 	}
262bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].opt_code = opt_code;
263bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
264bc892140SDag-Erling Smørgrav 	env->edns_known_options[i].no_aggregation = no_aggregation;
265bc892140SDag-Erling Smørgrav 	return 1;
266bc892140SDag-Erling Smørgrav }
267bc892140SDag-Erling Smørgrav 
26865b390aaSDag-Erling Smørgrav int
26965b390aaSDag-Erling Smørgrav inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
27065b390aaSDag-Erling Smørgrav 	struct module_env* env, int id)
271bc892140SDag-Erling Smørgrav {
27265b390aaSDag-Erling Smørgrav 	struct inplace_cb* callback;
27365b390aaSDag-Erling Smørgrav 	struct inplace_cb** prevp;
274bc892140SDag-Erling Smørgrav 	if(env->worker) {
275bc892140SDag-Erling Smørgrav 		log_err("invalid edns callback registration: "
276bc892140SDag-Erling Smørgrav 			"trying to register callback after module init phase");
277bc892140SDag-Erling Smørgrav 		return 0;
278bc892140SDag-Erling Smørgrav 	}
279bc892140SDag-Erling Smørgrav 
28065b390aaSDag-Erling Smørgrav 	callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
281bc892140SDag-Erling Smørgrav 	if(callback == NULL) {
282bc892140SDag-Erling Smørgrav 		log_err("out of memory during edns callback registration.");
283bc892140SDag-Erling Smørgrav 		return 0;
284bc892140SDag-Erling Smørgrav 	}
28565b390aaSDag-Erling Smørgrav 	callback->id = id;
286bc892140SDag-Erling Smørgrav 	callback->next = NULL;
287bc892140SDag-Erling Smørgrav 	callback->cb = cb;
28865b390aaSDag-Erling Smørgrav 	callback->cb_arg = cbarg;
289bc892140SDag-Erling Smørgrav 
29065b390aaSDag-Erling Smørgrav 	prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
291bc892140SDag-Erling Smørgrav 	/* append at end of list */
292bc892140SDag-Erling Smørgrav 	while(*prevp != NULL)
293bc892140SDag-Erling Smørgrav 		prevp = &((*prevp)->next);
294bc892140SDag-Erling Smørgrav 	*prevp = callback;
295bc892140SDag-Erling Smørgrav 	return 1;
296bc892140SDag-Erling Smørgrav }
297bc892140SDag-Erling Smørgrav 
298bc892140SDag-Erling Smørgrav void
29965b390aaSDag-Erling Smørgrav inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
30065b390aaSDag-Erling Smørgrav 	int id)
301bc892140SDag-Erling Smørgrav {
30265b390aaSDag-Erling Smørgrav 	struct inplace_cb* temp = env->inplace_cb_lists[type];
30365b390aaSDag-Erling Smørgrav 	struct inplace_cb* prev = NULL;
304bc892140SDag-Erling Smørgrav 
30565b390aaSDag-Erling Smørgrav 	while(temp) {
30665b390aaSDag-Erling Smørgrav 		if(temp->id == id) {
30765b390aaSDag-Erling Smørgrav 			if(!prev) {
30865b390aaSDag-Erling Smørgrav 				env->inplace_cb_lists[type] = temp->next;
30965b390aaSDag-Erling Smørgrav 				free(temp);
31065b390aaSDag-Erling Smørgrav 				temp = env->inplace_cb_lists[type];
31165b390aaSDag-Erling Smørgrav 			}
31265b390aaSDag-Erling Smørgrav 			else {
31365b390aaSDag-Erling Smørgrav 				prev->next = temp->next;
31465b390aaSDag-Erling Smørgrav 				free(temp);
31565b390aaSDag-Erling Smørgrav 				temp = prev->next;
31665b390aaSDag-Erling Smørgrav 			}
31765b390aaSDag-Erling Smørgrav 		}
31865b390aaSDag-Erling Smørgrav 		else {
31965b390aaSDag-Erling Smørgrav 			prev = temp;
32065b390aaSDag-Erling Smørgrav 			temp = temp->next;
32165b390aaSDag-Erling Smørgrav 		}
32265b390aaSDag-Erling Smørgrav 	}
323bc892140SDag-Erling Smørgrav }
324bc892140SDag-Erling Smørgrav 
325bc892140SDag-Erling Smørgrav struct edns_known_option*
326bc892140SDag-Erling Smørgrav edns_option_is_known(uint16_t opt_code, struct module_env* env)
327bc892140SDag-Erling Smørgrav {
328bc892140SDag-Erling Smørgrav 	size_t i;
329bc892140SDag-Erling Smørgrav 	for(i=0; i<env->edns_known_options_num; i++)
330bc892140SDag-Erling Smørgrav 		if(env->edns_known_options[i].opt_code == opt_code)
331bc892140SDag-Erling Smørgrav 			return env->edns_known_options + i;
332bc892140SDag-Erling Smørgrav 	return NULL;
333bc892140SDag-Erling Smørgrav }
334bc892140SDag-Erling Smørgrav 
335bc892140SDag-Erling Smørgrav int
336bc892140SDag-Erling Smørgrav edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
337bc892140SDag-Erling Smørgrav {
338bc892140SDag-Erling Smørgrav 	size_t i;
339bc892140SDag-Erling Smørgrav 	for(; list; list=list->next)
340bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++)
341bc892140SDag-Erling Smørgrav 			if(env->edns_known_options[i].opt_code == list->opt_code &&
342bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].bypass_cache_stage == 1)
343bc892140SDag-Erling Smørgrav 					return 1;
344bc892140SDag-Erling Smørgrav 	return 0;
345bc892140SDag-Erling Smørgrav }
346bc892140SDag-Erling Smørgrav 
347bc892140SDag-Erling Smørgrav int
34865b390aaSDag-Erling Smørgrav unique_mesh_state(struct edns_option* list, struct module_env* env)
349bc892140SDag-Erling Smørgrav {
350bc892140SDag-Erling Smørgrav 	size_t i;
35165b390aaSDag-Erling Smørgrav 	if(env->unique_mesh)
35265b390aaSDag-Erling Smørgrav 		return 1;
353bc892140SDag-Erling Smørgrav 	for(; list; list=list->next)
354bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++)
355bc892140SDag-Erling Smørgrav 			if(env->edns_known_options[i].opt_code == list->opt_code &&
356bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].no_aggregation == 1)
357bc892140SDag-Erling Smørgrav 					return 1;
358bc892140SDag-Erling Smørgrav 	return 0;
359bc892140SDag-Erling Smørgrav }
360bc892140SDag-Erling Smørgrav 
361bc892140SDag-Erling Smørgrav void
362bc892140SDag-Erling Smørgrav log_edns_known_options(enum verbosity_value level, struct module_env* env)
363bc892140SDag-Erling Smørgrav {
364bc892140SDag-Erling Smørgrav 	size_t i;
365bc892140SDag-Erling Smørgrav 	char str[32], *s;
366bc892140SDag-Erling Smørgrav 	size_t slen;
367bc892140SDag-Erling Smørgrav 	if(env->edns_known_options_num > 0 && verbosity >= level) {
368bc892140SDag-Erling Smørgrav 		verbose(level, "EDNS known options:");
369bc892140SDag-Erling Smørgrav 		verbose(level, "  Code:    Bypass_cache_stage: Aggregate_mesh:");
370bc892140SDag-Erling Smørgrav 		for(i=0; i<env->edns_known_options_num; i++) {
371bc892140SDag-Erling Smørgrav 			s = str;
372bc892140SDag-Erling Smørgrav 			slen = sizeof(str);
373bc892140SDag-Erling Smørgrav 			(void)sldns_wire2str_edns_option_code_print(&s, &slen,
374bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].opt_code);
375bc892140SDag-Erling Smørgrav 			verbose(level, "  %-8.8s %-19s %-15s", str,
376bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
377bc892140SDag-Erling Smørgrav 				env->edns_known_options[i].no_aggregation?"NO":"YES");
378bc892140SDag-Erling Smørgrav 		}
379bc892140SDag-Erling Smørgrav 	}
380bc892140SDag-Erling Smørgrav }
3814c75e3aaSDag-Erling Smørgrav 
3824c75e3aaSDag-Erling Smørgrav void
3834c75e3aaSDag-Erling Smørgrav copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id),
3844c75e3aaSDag-Erling Smørgrav 	struct module_qstate* super)
3854c75e3aaSDag-Erling Smørgrav {
3864c75e3aaSDag-Erling Smørgrav 	/* Overwrite super's was_ratelimited only when it was not set */
3874c75e3aaSDag-Erling Smørgrav 	if(!super->was_ratelimited) {
3884c75e3aaSDag-Erling Smørgrav 		super->was_ratelimited = qstate->was_ratelimited;
3894c75e3aaSDag-Erling Smørgrav 	}
3904c75e3aaSDag-Erling Smørgrav }
391