Home | History | Annotate | Line # | Download | only in util
      1 /*
      2  * util/module.c - module interface
      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  * \file
     37  * Implementation of module.h.
     38  */
     39 
     40 #include "config.h"
     41 #include "util/module.h"
     42 #include "sldns/wire2str.h"
     43 #include "util/config_file.h"
     44 #include "util/regional.h"
     45 #include "util/data/dname.h"
     46 #include "util/net_help.h"
     47 
     48 const char*
     49 strextstate(enum module_ext_state s)
     50 {
     51 	switch(s) {
     52 	case module_state_initial: return "module_state_initial";
     53 	case module_wait_reply: return "module_wait_reply";
     54 	case module_wait_module: return "module_wait_module";
     55 	case module_restart_next: return "module_restart_next";
     56 	case module_wait_subquery: return "module_wait_subquery";
     57 	case module_error: return "module_error";
     58 	case module_finished: return "module_finished";
     59 	}
     60 	return "bad_extstate_value";
     61 }
     62 
     63 const char*
     64 strmodulevent(enum module_ev e)
     65 {
     66 	switch(e) {
     67 	case module_event_new: return "module_event_new";
     68 	case module_event_pass: return "module_event_pass";
     69 	case module_event_reply: return "module_event_reply";
     70 	case module_event_noreply: return "module_event_noreply";
     71 	case module_event_capsfail: return "module_event_capsfail";
     72 	case module_event_moddone: return "module_event_moddone";
     73 	case module_event_error: return "module_event_error";
     74 	}
     75 	return "bad_event_value";
     76 }
     77 
     78 void errinf(struct module_qstate* qstate, const char* str)
     79 {
     80 	errinf_ede(qstate, str, LDNS_EDE_NONE);
     81 }
     82 
     83 void errinf_ede(struct module_qstate* qstate,
     84 	const char* str, sldns_ede_code reason_bogus)
     85 {
     86 	struct errinf_strlist* p;
     87 	if(!str || (qstate->env->cfg->val_log_level < 2 &&
     88 		!qstate->env->cfg->log_servfail)) {
     89 		return;
     90 	}
     91 	p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
     92 	if(!p) {
     93 		log_err("malloc failure in validator-error-info string");
     94 		return;
     95 	}
     96 	p->next = NULL;
     97 	p->str = regional_strdup(qstate->region, str);
     98 	p->reason_bogus = reason_bogus;
     99 	if(!p->str) {
    100 		log_err("malloc failure in validator-error-info string");
    101 		return;
    102 	}
    103 	/* add at end */
    104 	if(qstate->errinf) {
    105 		struct errinf_strlist* q = qstate->errinf;
    106 		while(q->next)
    107 			q = q->next;
    108 		q->next = p;
    109 	} else	qstate->errinf = p;
    110 }
    111 
    112 void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)
    113 {
    114 	struct sock_list* p;
    115 	if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
    116 		return;
    117 	for(p=origin; p; p=p->next) {
    118 		char buf[256];
    119 		if(p == origin)
    120 			snprintf(buf, sizeof(buf), "from ");
    121 		else	snprintf(buf, sizeof(buf), "and ");
    122 		if(p->len == 0)
    123 			snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
    124 				"cache");
    125 		else
    126 			addr_to_str(&p->addr, p->len, buf+strlen(buf),
    127 				sizeof(buf)-strlen(buf));
    128 		errinf(qstate, buf);
    129 	}
    130 }
    131 
    132 char* errinf_to_str_bogus(struct module_qstate* qstate, struct regional* region)
    133 {
    134 	char buf[20480];
    135 	char* p = buf;
    136 	size_t left = sizeof(buf);
    137 	struct errinf_strlist* s;
    138 	char dname[LDNS_MAX_DOMAINLEN];
    139 	char t[16], c[16];
    140 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
    141 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
    142 	dname_str(qstate->qinfo.qname, dname);
    143 	snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
    144 	left -= strlen(p); p += strlen(p);
    145 	if(!qstate->errinf)
    146 		snprintf(p, left, " misc failure");
    147 	else for(s=qstate->errinf; s; s=s->next) {
    148 		snprintf(p, left, " %s", s->str);
    149 		left -= strlen(p); p += strlen(p);
    150 	}
    151 	if(region)
    152 		p = regional_strdup(region, buf);
    153 	else
    154 		p = strdup(buf);
    155 	if(!p)
    156 		log_err("malloc failure in errinf_to_str");
    157 	return p;
    158 }
    159 
    160 /* Try to find the latest (most specific) dnssec failure */
    161 sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
    162 {
    163 	struct errinf_strlist* s;
    164 	sldns_ede_code ede = LDNS_EDE_NONE;
    165 	for(s=qstate->errinf; s; s=s->next) {
    166 		if(s->reason_bogus == LDNS_EDE_NONE) continue;
    167 		if(ede != LDNS_EDE_NONE
    168 			&& ede != LDNS_EDE_DNSSEC_BOGUS
    169 			&& s->reason_bogus == LDNS_EDE_DNSSEC_BOGUS) continue;
    170 		ede = s->reason_bogus;
    171 	}
    172 	return ede;
    173 }
    174 
    175 char* errinf_to_str_servfail(struct module_qstate* qstate)
    176 {
    177 	char buf[20480];
    178 	char* p = buf;
    179 	size_t left = sizeof(buf);
    180 	struct errinf_strlist* s;
    181 	char dname[LDNS_MAX_DOMAINLEN];
    182 	char t[16], c[16];
    183 	sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));
    184 	sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));
    185 	dname_str(qstate->qinfo.qname, dname);
    186 	snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);
    187 	left -= strlen(p); p += strlen(p);
    188 	if(!qstate->errinf)
    189 		snprintf(p, left, " misc failure");
    190 	else for(s=qstate->errinf; s; s=s->next) {
    191 		snprintf(p, left, " %s", s->str);
    192 		left -= strlen(p); p += strlen(p);
    193 	}
    194 	p = regional_strdup(qstate->region, buf);
    195 	if(!p)
    196 		log_err("malloc failure in errinf_to_str");
    197 	return p;
    198 }
    199 
    200 char* errinf_to_str_misc(struct module_qstate* qstate)
    201 {
    202 	char buf[20480];
    203 	char* p = buf;
    204 	size_t left = sizeof(buf);
    205 	struct errinf_strlist* s;
    206 	if(!qstate->errinf)
    207 		snprintf(p, left, "misc failure");
    208 	else for(s=qstate->errinf; s; s=s->next) {
    209 		snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str);
    210 		left -= strlen(p); p += strlen(p);
    211 	}
    212 	p = regional_strdup(qstate->region, buf);
    213 	if(!p)
    214 		log_err("malloc failure in errinf_to_str");
    215 	return p;
    216 }
    217 
    218 void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)
    219 {
    220 	char buf[1024];
    221 	char dname[LDNS_MAX_DOMAINLEN];
    222 	char t[16], c[16];
    223 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !rr)
    224 		return;
    225 	sldns_wire2str_type_buf(ntohs(rr->rk.type), t, sizeof(t));
    226 	sldns_wire2str_class_buf(ntohs(rr->rk.rrset_class), c, sizeof(c));
    227 	dname_str(rr->rk.dname, dname);
    228 	snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
    229 	errinf(qstate, buf);
    230 }
    231 
    232 void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
    233 {
    234 	char b[1024];
    235 	char buf[LDNS_MAX_DOMAINLEN];
    236 	if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str || !dname)
    237 		return;
    238 	dname_str(dname, buf);
    239 	snprintf(b, sizeof(b), "%s %s", str, buf);
    240 	errinf(qstate, b);
    241 }
    242 
    243 int
    244 edns_known_options_init(struct module_env* env)
    245 {
    246 	env->edns_known_options_num = 0;
    247 	env->edns_known_options = (struct edns_known_option*)calloc(
    248 		MAX_KNOWN_EDNS_OPTS, sizeof(struct edns_known_option));
    249 	if(!env->edns_known_options) return 0;
    250 	return 1;
    251 }
    252 
    253 void
    254 edns_known_options_delete(struct module_env* env)
    255 {
    256 	free(env->edns_known_options);
    257 	env->edns_known_options = NULL;
    258 	env->edns_known_options_num = 0;
    259 }
    260 
    261 int
    262 edns_register_option(uint16_t opt_code, int bypass_cache_stage,
    263 	int no_aggregation, struct module_env* env)
    264 {
    265 	size_t i;
    266 	if(env->worker) {
    267 		log_err("invalid edns registration: "
    268 			"trying to register option after module init phase");
    269 		return 0;
    270 	}
    271 
    272 	/**
    273 	 * Checking if we are full first is faster but it does not provide
    274 	 * the option to change the flags when the array is full.
    275 	 * It only impacts unbound initialization, leave it for now.
    276 	 */
    277 	/* Check if the option is already registered. */
    278 	for(i=0; i<env->edns_known_options_num; i++)
    279 		if(env->edns_known_options[i].opt_code == opt_code)
    280 			break;
    281 	/* If it is not yet registered check if we have space to add a new one. */
    282 	if(i == env->edns_known_options_num) {
    283 		if(env->edns_known_options_num >= MAX_KNOWN_EDNS_OPTS) {
    284 			log_err("invalid edns registration: maximum options reached");
    285 			return 0;
    286 		}
    287 		env->edns_known_options_num++;
    288 	}
    289 	env->edns_known_options[i].opt_code = opt_code;
    290 	env->edns_known_options[i].bypass_cache_stage = bypass_cache_stage;
    291 	env->edns_known_options[i].no_aggregation = no_aggregation;
    292 	return 1;
    293 }
    294 
    295 int
    296 inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
    297 	struct module_env* env, int id)
    298 {
    299 	struct inplace_cb* callback;
    300 	struct inplace_cb** prevp;
    301 	if(env->worker) {
    302 		log_err("invalid edns callback registration: "
    303 			"trying to register callback after module init phase");
    304 		return 0;
    305 	}
    306 
    307 	callback = (struct inplace_cb*)calloc(1, sizeof(*callback));
    308 	if(callback == NULL) {
    309 		log_err("out of memory during edns callback registration.");
    310 		return 0;
    311 	}
    312 	callback->id = id;
    313 	callback->next = NULL;
    314 	callback->cb = cb;
    315 	callback->cb_arg = cbarg;
    316 
    317 	prevp = (struct inplace_cb**) &env->inplace_cb_lists[type];
    318 	/* append at end of list */
    319 	while(*prevp != NULL)
    320 		prevp = &((*prevp)->next);
    321 	*prevp = callback;
    322 	return 1;
    323 }
    324 
    325 void
    326 inplace_cb_delete(struct module_env* env, enum inplace_cb_list_type type,
    327 	int id)
    328 {
    329 	struct inplace_cb* temp = env->inplace_cb_lists[type];
    330 	struct inplace_cb* prev = NULL;
    331 
    332 	while(temp) {
    333 		if(temp->id == id) {
    334 			if(!prev) {
    335 				env->inplace_cb_lists[type] = temp->next;
    336 				free(temp);
    337 				temp = env->inplace_cb_lists[type];
    338 			}
    339 			else {
    340 				prev->next = temp->next;
    341 				free(temp);
    342 				temp = prev->next;
    343 			}
    344 		}
    345 		else {
    346 			prev = temp;
    347 			temp = temp->next;
    348 		}
    349 	}
    350 }
    351 
    352 struct edns_known_option*
    353 edns_option_is_known(uint16_t opt_code, struct module_env* env)
    354 {
    355 	size_t i;
    356 	for(i=0; i<env->edns_known_options_num; i++)
    357 		if(env->edns_known_options[i].opt_code == opt_code)
    358 			return env->edns_known_options + i;
    359 	return NULL;
    360 }
    361 
    362 int
    363 edns_bypass_cache_stage(struct edns_option* list, struct module_env* env)
    364 {
    365 	size_t i;
    366 	for(; list; list=list->next)
    367 		for(i=0; i<env->edns_known_options_num; i++)
    368 			if(env->edns_known_options[i].opt_code == list->opt_code &&
    369 				env->edns_known_options[i].bypass_cache_stage == 1)
    370 					return 1;
    371 	return 0;
    372 }
    373 
    374 int
    375 unique_mesh_state(struct edns_option* list, struct module_env* env)
    376 {
    377 	size_t i;
    378 	if(env->unique_mesh)
    379 		return 1;
    380 	for(; list; list=list->next)
    381 		for(i=0; i<env->edns_known_options_num; i++)
    382 			if(env->edns_known_options[i].opt_code == list->opt_code &&
    383 				env->edns_known_options[i].no_aggregation == 1)
    384 					return 1;
    385 	return 0;
    386 }
    387 
    388 void
    389 log_edns_known_options(enum verbosity_value level, struct module_env* env)
    390 {
    391 	size_t i;
    392 	char str[32], *s;
    393 	size_t slen;
    394 	if(env->edns_known_options_num > 0 && verbosity >= level) {
    395 		verbose(level, "EDNS known options:");
    396 		verbose(level, "  Code:    Bypass_cache_stage: Aggregate_mesh:");
    397 		for(i=0; i<env->edns_known_options_num; i++) {
    398 			s = str;
    399 			slen = sizeof(str);
    400 			(void)sldns_wire2str_edns_option_code_print(&s, &slen,
    401 				env->edns_known_options[i].opt_code);
    402 			verbose(level, "  %-8.8s %-19s %-15s", str,
    403 				env->edns_known_options[i].bypass_cache_stage?"YES":"NO",
    404 				env->edns_known_options[i].no_aggregation?"NO":"YES");
    405 		}
    406 	}
    407 }
    408 
    409 void
    410 copy_state_to_super(struct module_qstate* qstate, int ATTR_UNUSED(id),
    411 	struct module_qstate* super)
    412 {
    413 	/* Overwrite super's was_ratelimited only when it was not set */
    414 	if(!super->was_ratelimited) {
    415 		super->was_ratelimited = qstate->was_ratelimited;
    416 	}
    417 }
    418