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+1]; 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+1]; 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+1]; 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+1]; 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