xref: /openbsd-src/sbin/unwind/libunbound/util/module.c (revision 096314fef8a8f610abc29edd0a9e7e61b7ff5976)
1ae8c6e27Sflorian /*
2ae8c6e27Sflorian  * util/module.c - module interface
3ae8c6e27Sflorian  *
4ae8c6e27Sflorian  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5ae8c6e27Sflorian  *
6ae8c6e27Sflorian  * This software is open source.
7ae8c6e27Sflorian  *
8ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10ae8c6e27Sflorian  * are met:
11ae8c6e27Sflorian  *
12ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14ae8c6e27Sflorian  *
15ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18ae8c6e27Sflorian  *
19ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21ae8c6e27Sflorian  * specific prior written permission.
22ae8c6e27Sflorian  *
23ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34ae8c6e27Sflorian  */
35ae8c6e27Sflorian /**
36ae8c6e27Sflorian  * \file
37ae8c6e27Sflorian  * Implementation of module.h.
38ae8c6e27Sflorian  */
39ae8c6e27Sflorian 
40ae8c6e27Sflorian #include "config.h"
41ae8c6e27Sflorian #include "util/module.h"
42ae8c6e27Sflorian #include "sldns/wire2str.h"
437a05b9dfSflorian #include "util/config_file.h"
447a05b9dfSflorian #include "util/regional.h"
457a05b9dfSflorian #include "util/data/dname.h"
467a05b9dfSflorian #include "util/net_help.h"
47ae8c6e27Sflorian 
48ae8c6e27Sflorian const char*
strextstate(enum module_ext_state s)49ae8c6e27Sflorian strextstate(enum module_ext_state s)
50ae8c6e27Sflorian {
51ae8c6e27Sflorian 	switch(s) {
52ae8c6e27Sflorian 	case module_state_initial: return "module_state_initial";
53ae8c6e27Sflorian 	case module_wait_reply: return "module_wait_reply";
54ae8c6e27Sflorian 	case module_wait_module: return "module_wait_module";
55ae8c6e27Sflorian 	case module_restart_next: return "module_restart_next";
56ae8c6e27Sflorian 	case module_wait_subquery: return "module_wait_subquery";
57ae8c6e27Sflorian 	case module_error: return "module_error";
58ae8c6e27Sflorian 	case module_finished: return "module_finished";
59ae8c6e27Sflorian 	}
60ae8c6e27Sflorian 	return "bad_extstate_value";
61ae8c6e27Sflorian }
62ae8c6e27Sflorian 
63ae8c6e27Sflorian const char*
strmodulevent(enum module_ev e)64ae8c6e27Sflorian strmodulevent(enum module_ev e)
65ae8c6e27Sflorian {
66ae8c6e27Sflorian 	switch(e) {
67ae8c6e27Sflorian 	case module_event_new: return "module_event_new";
68ae8c6e27Sflorian 	case module_event_pass: return "module_event_pass";
69ae8c6e27Sflorian 	case module_event_reply: return "module_event_reply";
70ae8c6e27Sflorian 	case module_event_noreply: return "module_event_noreply";
71ae8c6e27Sflorian 	case module_event_capsfail: return "module_event_capsfail";
72ae8c6e27Sflorian 	case module_event_moddone: return "module_event_moddone";
73ae8c6e27Sflorian 	case module_event_error: return "module_event_error";
74ae8c6e27Sflorian 	}
75ae8c6e27Sflorian 	return "bad_event_value";
76ae8c6e27Sflorian }
77ae8c6e27Sflorian 
errinf(struct module_qstate * qstate,const char * str)787a05b9dfSflorian void errinf(struct module_qstate* qstate, const char* str)
797a05b9dfSflorian {
807a05b9dfSflorian 	errinf_ede(qstate, str, LDNS_EDE_NONE);
817a05b9dfSflorian }
827a05b9dfSflorian 
errinf_ede(struct module_qstate * qstate,const char * str,sldns_ede_code reason_bogus)837a05b9dfSflorian void errinf_ede(struct module_qstate* qstate,
847a05b9dfSflorian 	const char* str, sldns_ede_code reason_bogus)
857a05b9dfSflorian {
867a05b9dfSflorian 	struct errinf_strlist* p;
87d500c338Sflorian 	if(!str || (qstate->env->cfg->val_log_level < 2 &&
88d500c338Sflorian 		!qstate->env->cfg->log_servfail)) {
897a05b9dfSflorian 		return;
90d500c338Sflorian 	}
917a05b9dfSflorian 	p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
927a05b9dfSflorian 	if(!p) {
937a05b9dfSflorian 		log_err("malloc failure in validator-error-info string");
947a05b9dfSflorian 		return;
957a05b9dfSflorian 	}
967a05b9dfSflorian 	p->next = NULL;
977a05b9dfSflorian 	p->str = regional_strdup(qstate->region, str);
987a05b9dfSflorian 	p->reason_bogus = reason_bogus;
997a05b9dfSflorian 	if(!p->str) {
1007a05b9dfSflorian 		log_err("malloc failure in validator-error-info string");
1017a05b9dfSflorian 		return;
1027a05b9dfSflorian 	}
1037a05b9dfSflorian 	/* add at end */
1047a05b9dfSflorian 	if(qstate->errinf) {
1057a05b9dfSflorian 		struct errinf_strlist* q = qstate->errinf;
1067a05b9dfSflorian 		while(q->next)
1077a05b9dfSflorian 			q = q->next;
1087a05b9dfSflorian 		q->next = p;
1097a05b9dfSflorian 	} else	qstate->errinf = p;
1107a05b9dfSflorian }
1117a05b9dfSflorian 
errinf_origin(struct module_qstate * qstate,struct sock_list * origin)1127a05b9dfSflorian void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
1137a05b9dfSflorian {
1147a05b9dfSflorian 	struct sock_list* p;
1157a05b9dfSflorian 	if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
1167a05b9dfSflorian 		return;
1177a05b9dfSflorian 	for(p=origin; p; p=p->next) {
1187a05b9dfSflorian 		char buf[256];
1197a05b9dfSflorian 		if(p == origin)
1207a05b9dfSflorian 			snprintf(buf, sizeof(buf), "from ");
1217a05b9dfSflorian 		else	snprintf(buf, sizeof(buf), "and ");
1227a05b9dfSflorian 		if(p->len == 0)
1237a05b9dfSflorian 			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
1247a05b9dfSflorian 				"cache");
1257a05b9dfSflorian 		else
1267a05b9dfSflorian 			addr_to_str(&p->addr, p->len, buf+strlen(buf),
1277a05b9dfSflorian 				sizeof(buf)-strlen(buf));
1287a05b9dfSflorian 		errinf(qstate, buf);
1297a05b9dfSflorian 	}
1307a05b9dfSflorian }
1317a05b9dfSflorian 
errinf_to_str_bogus(struct module_qstate * qstate,struct regional * region)132*096314feSflorian char* errinf_to_str_bogus(struct module_qstate* qstate, struct regional* region)
1337a05b9dfSflorian {
1347a05b9dfSflorian 	char buf[20480];
1357a05b9dfSflorian 	char* p = buf;
1367a05b9dfSflorian 	size_t left = sizeof(buf);
1377a05b9dfSflorian 	struct errinf_strlist* s;
1387a05b9dfSflorian 	char dname[LDNS_MAX_DOMAINLEN+1];
1397a05b9dfSflorian 	char t[16], c[16];
1407a05b9dfSflorian 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
1417a05b9dfSflorian 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
1427a05b9dfSflorian 	dname_str(qstate->qinfo.qname, dname);
1437a05b9dfSflorian 	snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
1447a05b9dfSflorian 	left -= strlen(p); p += strlen(p);
1457a05b9dfSflorian 	if(!qstate->errinf)
1467a05b9dfSflorian 		snprintf(p, left, " misc failure");
1477a05b9dfSflorian 	else for(s=qstate->errinf; s; s=s->next) {
1487a05b9dfSflorian 		snprintf(p, left, " %s", s->str);
1497a05b9dfSflorian 		left -= strlen(p); p += strlen(p);
1507a05b9dfSflorian 	}
151*096314feSflorian 	if(region)
152*096314feSflorian 		p = regional_strdup(region, buf);
153*096314feSflorian 	else
1547a05b9dfSflorian 		p = strdup(buf);
1557a05b9dfSflorian 	if(!p)
1567a05b9dfSflorian 		log_err("malloc failure in errinf_to_str");
1577a05b9dfSflorian 	return p;
1587a05b9dfSflorian }
1597a05b9dfSflorian 
160d500c338Sflorian /* Try to find the latest (most specific) dnssec failure */
errinf_to_reason_bogus(struct module_qstate * qstate)1617a05b9dfSflorian sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
1627a05b9dfSflorian {
1637a05b9dfSflorian 	struct errinf_strlist* s;
164d500c338Sflorian 	sldns_ede_code ede = LDNS_EDE_NONE;
1657a05b9dfSflorian 	for(s=qstate->errinf; s; s=s->next) {
166d500c338Sflorian 		if(s->reason_bogus == LDNS_EDE_NONE) continue;
167d500c338Sflorian 		if(ede != LDNS_EDE_NONE
168d500c338Sflorian 			&& ede != LDNS_EDE_DNSSEC_BOGUS
169d500c338Sflorian 			&& s->reason_bogus == LDNS_EDE_DNSSEC_BOGUS) continue;
170d500c338Sflorian 		ede = s->reason_bogus;
1717a05b9dfSflorian 	}
172d500c338Sflorian 	return ede;
1737a05b9dfSflorian }
1747a05b9dfSflorian 
errinf_to_str_servfail(struct module_qstate * qstate)1757a05b9dfSflorian char* errinf_to_str_servfail(struct module_qstate* qstate)
1767a05b9dfSflorian {
1777a05b9dfSflorian 	char buf[20480];
1787a05b9dfSflorian 	char* p = buf;
1797a05b9dfSflorian 	size_t left = sizeof(buf);
1807a05b9dfSflorian 	struct errinf_strlist* s;
1817a05b9dfSflorian 	char dname[LDNS_MAX_DOMAINLEN+1];
1827a05b9dfSflorian 	char t[16], c[16];
1837a05b9dfSflorian 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
1847a05b9dfSflorian 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
1857a05b9dfSflorian 	dname_str(qstate->qinfo.qname, dname);
1867a05b9dfSflorian 	snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
1877a05b9dfSflorian 	left -= strlen(p); p += strlen(p);
1887a05b9dfSflorian 	if(!qstate->errinf)
1897a05b9dfSflorian 		snprintf(p, left, " misc failure");
1907a05b9dfSflorian 	else for(s=qstate->errinf; s; s=s->next) {
1917a05b9dfSflorian 		snprintf(p, left, " %s", s->str);
1927a05b9dfSflorian 		left -= strlen(p); p += strlen(p);
1937a05b9dfSflorian 	}
194*096314feSflorian 	p = regional_strdup(qstate->region, buf);
1957a05b9dfSflorian 	if(!p)
1967a05b9dfSflorian 		log_err("malloc failure in errinf_to_str");
1977a05b9dfSflorian 	return p;
1987a05b9dfSflorian }
1997a05b9dfSflorian 
errinf_to_str_misc(struct module_qstate * qstate)20054cc57acSflorian char* errinf_to_str_misc(struct module_qstate* qstate)
20154cc57acSflorian {
20254cc57acSflorian 	char buf[20480];
20354cc57acSflorian 	char* p = buf;
20454cc57acSflorian 	size_t left = sizeof(buf);
20554cc57acSflorian 	struct errinf_strlist* s;
20654cc57acSflorian 	if(!qstate->errinf)
20754cc57acSflorian 		snprintf(p, left, "misc failure");
20854cc57acSflorian 	else for(s=qstate->errinf; s; s=s->next) {
20954cc57acSflorian 		snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
21054cc57acSflorian 		left -= strlen(p); p += strlen(p);
21154cc57acSflorian 	}
212*096314feSflorian 	p = regional_strdup(qstate->region, buf);
21354cc57acSflorian 	if(!p)
21454cc57acSflorian 		log_err("malloc failure in errinf_to_str");
21554cc57acSflorian 	return p;
21654cc57acSflorian }
21754cc57acSflorian 
errinf_rrset(struct module_qstate * qstate,struct ub_packed_rrset_key * rr)2187a05b9dfSflorian void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
2197a05b9dfSflorian {
2207a05b9dfSflorian 	char buf[1024];
2217a05b9dfSflorian 	char dname[LDNS_MAX_DOMAINLEN+1];
2227a05b9dfSflorian 	char t[16], c[16];
2237a05b9dfSflorian 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
2247a05b9dfSflorian 		return;
2257a05b9dfSflorian 	sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
2267a05b9dfSflorian 	sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
2277a05b9dfSflorian 	dname_str(rr->rk.dname, dname);
2287a05b9dfSflorian 	snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
2297a05b9dfSflorian 	errinf(qstate, buf);
2307a05b9dfSflorian }
2317a05b9dfSflorian 
errinf_dname(struct module_qstate * qstate,const char * str,uint8_t * dname)2327a05b9dfSflorian void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
2337a05b9dfSflorian {
2347a05b9dfSflorian 	char b[1024];
2357a05b9dfSflorian 	char buf[LDNS_MAX_DOMAINLEN+1];
2367a05b9dfSflorian 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
2377a05b9dfSflorian 		return;
2387a05b9dfSflorian 	dname_str(dname, buf);
2397a05b9dfSflorian 	snprintf(b, sizeof(b), "%s %s", str, buf);
2407a05b9dfSflorian 	errinf(qstate, b);
2417a05b9dfSflorian }
2427a05b9dfSflorian 
243ae8c6e27Sflorian int
edns_known_options_init(struct module_env * env)244ae8c6e27Sflorian edns_known_options_init(struct module_env* env)
245ae8c6e27Sflorian {
246ae8c6e27Sflorian 	env->edns_known_options_num = 0;
247ae8c6e27Sflorian 	env->edns_known_options = (struct edns_known_option*)calloc(
248ae8c6e27Sflorian 		MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
249ae8c6e27Sflorian 	if(!env->edns_known_options) return 0;
250ae8c6e27Sflorian 	return 1;
251ae8c6e27Sflorian }
252ae8c6e27Sflorian 
253ae8c6e27Sflorian void
edns_known_options_delete(struct module_env * env)254ae8c6e27Sflorian edns_known_options_delete(struct module_env* env)
255ae8c6e27Sflorian {
256ae8c6e27Sflorian 	free(env->edns_known_options);
257ae8c6e27Sflorian 	env->edns_known_options = NULL;
258ae8c6e27Sflorian 	env->edns_known_options_num = 0;
259ae8c6e27Sflorian }
260ae8c6e27Sflorian 
261ae8c6e27Sflorian int
edns_register_option(uint16_t opt_code,int bypass_cache_stage,int no_aggregation,struct module_env * env)262ae8c6e27Sflorian edns_register_option(uint16_t opt_code, int bypass_cache_stage,
263ae8c6e27Sflorian 	int no_aggregation, struct module_env* env)
264ae8c6e27Sflorian {
265ae8c6e27Sflorian 	size_t i;
266ae8c6e27Sflorian 	if(env->worker) {
267ae8c6e27Sflorian 		log_err("invalid edns registration: "
268ae8c6e27Sflorian 			"trying to register option after module init phase");
269ae8c6e27Sflorian 		return 0;
270ae8c6e27Sflorian 	}
271ae8c6e27Sflorian 
272ae8c6e27Sflorian 	/**
273ae8c6e27Sflorian 	 * Checking if we are full first is faster but it does not provide
274ae8c6e27Sflorian 	 * the option to change the flags when the array is full.
275ae8c6e27Sflorian 	 * It only impacts unbound initialization, leave it for now.
276ae8c6e27Sflorian 	 */
277ae8c6e27Sflorian 	/* Check if the option is already registered. */
278ae8c6e27Sflorian 	for(i=0; i<env->edns_known_options_num; i++)
279ae8c6e27Sflorian 		if(env->edns_known_options[i].opt_code == opt_code)
280ae8c6e27Sflorian 			break;
281ae8c6e27Sflorian 	/* If it is not yet registered check if we have space to add a new one. */
282ae8c6e27Sflorian 	if(i == env->edns_known_options_num) {
283ae8c6e27Sflorian 		if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
284ae8c6e27Sflorian 			log_err("invalid edns registration: maximum options reached");
285ae8c6e27Sflorian 			return 0;
286ae8c6e27Sflorian 		}
287ae8c6e27Sflorian 		env->edns_known_options_num++;
288ae8c6e27Sflorian 	}
289ae8c6e27Sflorian 	env->edns_known_options[i].opt_code = opt_code;
290ae8c6e27Sflorian 	env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
291ae8c6e27Sflorian 	env->edns_known_options[i].no_aggregation = no_aggregation;
292ae8c6e27Sflorian 	return 1;
293ae8c6e27Sflorian }
294ae8c6e27Sflorian 
295ae8c6e27Sflorian int
inplace_cb_register(void * cb,enum inplace_cb_list_type type,void * cbarg,struct module_env * env,int id)296ae8c6e27Sflorian inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
297ae8c6e27Sflorian 	struct module_env* env, int id)
298ae8c6e27Sflorian {
299ae8c6e27Sflorian 	struct inplace_cb* callback;
300ae8c6e27Sflorian 	struct inplace_cb** prevp;
301ae8c6e27Sflorian 	if(env->worker) {
302ae8c6e27Sflorian 		log_err("invalid edns callback registration: "
303ae8c6e27Sflorian 			"trying to register callback after module init phase");
304ae8c6e27Sflorian 		return 0;
305ae8c6e27Sflorian 	}
306ae8c6e27Sflorian 
307ae8c6e27Sflorian 	callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
308ae8c6e27Sflorian 	if(callback == NULL) {
309ae8c6e27Sflorian 		log_err("out of memory during edns callback registration.");
310ae8c6e27Sflorian 		return 0;
311ae8c6e27Sflorian 	}
312ae8c6e27Sflorian 	callback->id = id;
313ae8c6e27Sflorian 	callback->next = NULL;
314ae8c6e27Sflorian 	callback->cb = cb;
315ae8c6e27Sflorian 	callback->cb_arg = cbarg;
316ae8c6e27Sflorian 
317ae8c6e27Sflorian 	prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
318ae8c6e27Sflorian 	/* append at end of list */
319ae8c6e27Sflorian 	while(*prevp != NULL)
320ae8c6e27Sflorian 		prevp = &((*prevp)->next);
321ae8c6e27Sflorian 	*prevp = callback;
322ae8c6e27Sflorian 	return 1;
323ae8c6e27Sflorian }
324ae8c6e27Sflorian 
325ae8c6e27Sflorian void
inplace_cb_delete(struct module_env * env,enum inplace_cb_list_type type,int id)326ae8c6e27Sflorian inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
327ae8c6e27Sflorian 	int id)
328ae8c6e27Sflorian {
329ae8c6e27Sflorian 	struct inplace_cb* temp = env->inplace_cb_lists[type];
330ae8c6e27Sflorian 	struct inplace_cb* prev = NULL;
331ae8c6e27Sflorian 
332ae8c6e27Sflorian 	while(temp) {
333ae8c6e27Sflorian 		if(temp->id == id) {
334ae8c6e27Sflorian 			if(!prev) {
335ae8c6e27Sflorian 				env->inplace_cb_lists[type] = temp->next;
336ae8c6e27Sflorian 				free(temp);
337ae8c6e27Sflorian 				temp = env->inplace_cb_lists[type];
338ae8c6e27Sflorian 			}
339ae8c6e27Sflorian 			else {
340ae8c6e27Sflorian 				prev->next = temp->next;
341ae8c6e27Sflorian 				free(temp);
342ae8c6e27Sflorian 				temp = prev->next;
343ae8c6e27Sflorian 			}
344ae8c6e27Sflorian 		}
345ae8c6e27Sflorian 		else {
346ae8c6e27Sflorian 			prev = temp;
347ae8c6e27Sflorian 			temp = temp->next;
348ae8c6e27Sflorian 		}
349ae8c6e27Sflorian 	}
350ae8c6e27Sflorian }
351ae8c6e27Sflorian 
352ae8c6e27Sflorian struct edns_known_option*
edns_option_is_known(uint16_t opt_code,struct module_env * env)353ae8c6e27Sflorian edns_option_is_known(uint16_t opt_code, struct module_env* env)
354ae8c6e27Sflorian {
355ae8c6e27Sflorian 	size_t i;
356ae8c6e27Sflorian 	for(i=0; i<env->edns_known_options_num; i++)
357ae8c6e27Sflorian 		if(env->edns_known_options[i].opt_code == opt_code)
358ae8c6e27Sflorian 			return env->edns_known_options + i;
359ae8c6e27Sflorian 	return NULL;
360ae8c6e27Sflorian }
361ae8c6e27Sflorian 
362ae8c6e27Sflorian int
edns_bypass_cache_stage(struct edns_option * list,struct module_env * env)363ae8c6e27Sflorian edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
364ae8c6e27Sflorian {
365ae8c6e27Sflorian 	size_t i;
366ae8c6e27Sflorian 	for(; list; list=list->next)
367ae8c6e27Sflorian 		for(i=0; i<env->edns_known_options_num; i++)
368ae8c6e27Sflorian 			if(env->edns_known_options[i].opt_code == list->opt_code &&
369ae8c6e27Sflorian 				env->edns_known_options[i].bypass_cache_stage == 1)
370ae8c6e27Sflorian 					return 1;
371ae8c6e27Sflorian 	return 0;
372ae8c6e27Sflorian }
373ae8c6e27Sflorian 
374ae8c6e27Sflorian int
unique_mesh_state(struct edns_option * list,struct module_env * env)375ae8c6e27Sflorian unique_mesh_state(struct edns_option* list, struct module_env* env)
376ae8c6e27Sflorian {
377ae8c6e27Sflorian 	size_t i;
378ae8c6e27Sflorian 	if(env->unique_mesh)
379ae8c6e27Sflorian 		return 1;
380ae8c6e27Sflorian 	for(; list; list=list->next)
381ae8c6e27Sflorian 		for(i=0; i<env->edns_known_options_num; i++)
382ae8c6e27Sflorian 			if(env->edns_known_options[i].opt_code == list->opt_code &&
383ae8c6e27Sflorian 				env->edns_known_options[i].no_aggregation == 1)
384ae8c6e27Sflorian 					return 1;
385ae8c6e27Sflorian 	return 0;
386ae8c6e27Sflorian }
387ae8c6e27Sflorian 
388ae8c6e27Sflorian void
log_edns_known_options(enum verbosity_value level,struct module_env * env)389ae8c6e27Sflorian log_edns_known_options(enum verbosity_value level, struct module_env* env)
390ae8c6e27Sflorian {
391ae8c6e27Sflorian 	size_t i;
392ae8c6e27Sflorian 	char str[32], *s;
393ae8c6e27Sflorian 	size_t slen;
394ae8c6e27Sflorian 	if(env->edns_known_options_num > 0 && verbosity >= level) {
395ae8c6e27Sflorian 		verbose(level, "EDNS known options:");
396ae8c6e27Sflorian 		verbose(level, "  Code:    Bypass_cache_stage: Aggregate_mesh:");
397ae8c6e27Sflorian 		for(i=0; i<env->edns_known_options_num; i++) {
398ae8c6e27Sflorian 			s = str;
399ae8c6e27Sflorian 			slen = sizeof(str);
400ae8c6e27Sflorian 			(void)sldns_wire2str_edns_option_code_print(&s, &slen,
401ae8c6e27Sflorian 				env->edns_known_options[i].opt_code);
402ae8c6e27Sflorian 			verbose(level, "  %-8.8s %-19s %-15s", str,
403ae8c6e27Sflorian 				env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
404ae8c6e27Sflorian 				env->edns_known_options[i].no_aggregation?"NO":"YES");
405ae8c6e27Sflorian 		}
406ae8c6e27Sflorian 	}
407ae8c6e27Sflorian }
408ae8c6e27Sflorian 
409ae8c6e27Sflorian void
copy_state_to_super(struct module_qstate * qstate,int ATTR_UNUSED (id),struct module_qstate * super)410ae8c6e27Sflorian copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id),
411ae8c6e27Sflorian 	struct module_qstate* super)
412ae8c6e27Sflorian {
413ae8c6e27Sflorian 	/* Overwrite super's was_ratelimited only when it was not set */
414ae8c6e27Sflorian 	if(!super->was_ratelimited) {
415ae8c6e27Sflorian 		super->was_ratelimited = qstate->was_ratelimited;
416ae8c6e27Sflorian 	}
417ae8c6e27Sflorian }
418