1 /* 2 * services/mesh.c - deal with mesh of query states and handle events for that. 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 /** 37 * \file 38 * 39 * This file contains functions to assist in dealing with a mesh of 40 * query states. This mesh is supposed to be thread-specific. 41 * It consists of query states (per qname, qtype, qclass) and connections 42 * between query states and the super and subquery states, and replies to 43 * send back to clients. 44 */ 45 #include "config.h" 46 #include "services/mesh.h" 47 #include "services/outbound_list.h" 48 #include "services/cache/dns.h" 49 #include "services/cache/rrset.h" 50 #include "services/cache/infra.h" 51 #include "util/log.h" 52 #include "util/net_help.h" 53 #include "util/module.h" 54 #include "util/regional.h" 55 #include "util/data/msgencode.h" 56 #include "util/timehist.h" 57 #include "util/fptr_wlist.h" 58 #include "util/alloc.h" 59 #include "util/config_file.h" 60 #include "util/edns.h" 61 #include "sldns/sbuffer.h" 62 #include "sldns/wire2str.h" 63 #include "services/localzone.h" 64 #include "util/data/dname.h" 65 #include "respip/respip.h" 66 #include "services/listen_dnsport.h" 67 #include "util/timeval_func.h" 68 69 #ifdef CLIENT_SUBNET 70 #include "edns-subnet/subnetmod.h" 71 #include "edns-subnet/edns-subnet.h" 72 #endif 73 #ifdef HAVE_SYS_TYPES_H 74 # include <sys/types.h> 75 #endif 76 #ifdef HAVE_NETDB_H 77 #include <netdb.h> 78 #endif 79 80 /** Compare two views by name */ 81 static int 82 view_name_compare(const char* v_a, const char* v_b) 83 { 84 if(v_a == NULL && v_b == NULL) 85 return 0; 86 /* The NULL name is smaller than if the name is set. */ 87 if(v_a == NULL) 88 return -1; 89 if(v_b == NULL) 90 return 1; 91 return strcmp(v_a, v_b); 92 } 93 94 /** 95 * Compare two response-ip client info entries for the purpose of mesh state 96 * compare. It returns 0 if ci_a and ci_b are considered equal; otherwise 97 * 1 or -1 (they mean 'ci_a is larger/smaller than ci_b', respectively, but 98 * in practice it should be only used to mean they are different). 99 * We cannot share the mesh state for two queries if different response-ip 100 * actions can apply in the end, even if those queries are otherwise identical. 101 * For this purpose we compare tag lists and tag action lists; they should be 102 * identical to share the same state. 103 * For tag data, we don't look into the data content, as it can be 104 * expensive; unless tag data are not defined for both or they point to the 105 * exact same data in memory (i.e., they come from the same ACL entry), we 106 * consider these data different. 107 * Likewise, if the client info is associated with views, we don't look into 108 * the views. They are considered different unless they are exactly the same 109 * even if the views only differ in the names. 110 */ 111 static int 112 client_info_compare(const struct respip_client_info* ci_a, 113 const struct respip_client_info* ci_b) 114 { 115 int cmp; 116 117 if(!ci_a && !ci_b) 118 return 0; 119 if(ci_a && !ci_b) 120 return -1; 121 if(!ci_a && ci_b) 122 return 1; 123 if(ci_a->taglen != ci_b->taglen) 124 return (ci_a->taglen < ci_b->taglen) ? -1 : 1; 125 if(ci_a->taglist && !ci_b->taglist) 126 return -1; 127 if(!ci_a->taglist && ci_b->taglist) 128 return 1; 129 if(ci_a->taglist && ci_b->taglist) { 130 cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen); 131 if(cmp != 0) 132 return cmp; 133 } 134 if(ci_a->tag_actions_size != ci_b->tag_actions_size) 135 return (ci_a->tag_actions_size < ci_b->tag_actions_size) ? 136 -1 : 1; 137 if(ci_a->tag_actions && !ci_b->tag_actions) 138 return -1; 139 if(!ci_a->tag_actions && ci_b->tag_actions) 140 return 1; 141 if(ci_a->tag_actions && ci_b->tag_actions) { 142 cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions, 143 ci_a->tag_actions_size); 144 if(cmp != 0) 145 return cmp; 146 } 147 if(ci_a->tag_datas != ci_b->tag_datas) 148 return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1; 149 if(ci_a->view || ci_a->view_name || ci_b->view || ci_b->view_name) { 150 /* Compare the views by name. */ 151 cmp = view_name_compare( 152 (ci_a->view?ci_a->view->name:ci_a->view_name), 153 (ci_b->view?ci_b->view->name:ci_b->view_name)); 154 if(cmp != 0) 155 return cmp; 156 } 157 return 0; 158 } 159 160 int 161 mesh_state_compare(const void* ap, const void* bp) 162 { 163 struct mesh_state* a = (struct mesh_state*)ap; 164 struct mesh_state* b = (struct mesh_state*)bp; 165 int cmp; 166 167 if(a->unique < b->unique) 168 return -1; 169 if(a->unique > b->unique) 170 return 1; 171 172 if(a->s.is_priming && !b->s.is_priming) 173 return -1; 174 if(!a->s.is_priming && b->s.is_priming) 175 return 1; 176 177 if(a->s.is_valrec && !b->s.is_valrec) 178 return -1; 179 if(!a->s.is_valrec && b->s.is_valrec) 180 return 1; 181 182 if((a->s.query_flags&BIT_RD) && !(b->s.query_flags&BIT_RD)) 183 return -1; 184 if(!(a->s.query_flags&BIT_RD) && (b->s.query_flags&BIT_RD)) 185 return 1; 186 187 if((a->s.query_flags&BIT_CD) && !(b->s.query_flags&BIT_CD)) 188 return -1; 189 if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD)) 190 return 1; 191 192 cmp = query_info_compare(&a->s.qinfo, &b->s.qinfo); 193 if(cmp != 0) 194 return cmp; 195 return client_info_compare(a->s.client_info, b->s.client_info); 196 } 197 198 int 199 mesh_state_ref_compare(const void* ap, const void* bp) 200 { 201 struct mesh_state_ref* a = (struct mesh_state_ref*)ap; 202 struct mesh_state_ref* b = (struct mesh_state_ref*)bp; 203 return mesh_state_compare(a->s, b->s); 204 } 205 206 struct mesh_area* 207 mesh_create(struct module_stack* stack, struct module_env* env) 208 { 209 struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area)); 210 if(!mesh) { 211 log_err("mesh area alloc: out of memory"); 212 return NULL; 213 } 214 mesh->histogram = timehist_setup(); 215 mesh->qbuf_bak = sldns_buffer_new(env->cfg->msg_buffer_size); 216 if(!mesh->histogram || !mesh->qbuf_bak) { 217 free(mesh); 218 log_err("mesh area alloc: out of memory"); 219 return NULL; 220 } 221 mesh->mods = *stack; 222 mesh->env = env; 223 rbtree_init(&mesh->run, &mesh_state_compare); 224 rbtree_init(&mesh->all, &mesh_state_compare); 225 mesh->num_reply_addrs = 0; 226 mesh->num_reply_states = 0; 227 mesh->num_detached_states = 0; 228 mesh->num_forever_states = 0; 229 mesh->stats_jostled = 0; 230 mesh->stats_dropped = 0; 231 mesh->ans_expired = 0; 232 mesh->ans_cachedb = 0; 233 mesh->num_queries_discard_timeout = 0; 234 mesh->num_queries_replyaddr_limit = 0; 235 mesh->num_queries_wait_limit = 0; 236 mesh->num_dns_error_reports = 0; 237 mesh->max_reply_states = env->cfg->num_queries_per_thread; 238 mesh->max_forever_states = (mesh->max_reply_states+1)/2; 239 #ifndef S_SPLINT_S 240 mesh->jostle_max.tv_sec = (time_t)(env->cfg->jostle_time / 1000); 241 mesh->jostle_max.tv_usec = (time_t)((env->cfg->jostle_time % 1000) 242 *1000); 243 #endif 244 return mesh; 245 } 246 247 /** help mesh delete delete mesh states */ 248 static void 249 mesh_delete_helper(rbnode_type* n) 250 { 251 struct mesh_state* mstate = (struct mesh_state*)n->key; 252 /* perform a full delete, not only 'cleanup' routine, 253 * because other callbacks expect a clean state in the mesh. 254 * For 're-entrant' calls */ 255 mesh_state_delete(&mstate->s); 256 /* but because these delete the items from the tree, postorder 257 * traversal and rbtree rebalancing do not work together */ 258 } 259 260 void 261 mesh_delete(struct mesh_area* mesh) 262 { 263 if(!mesh) 264 return; 265 /* free all query states */ 266 while(mesh->all.count) 267 mesh_delete_helper(mesh->all.root); 268 timehist_delete(mesh->histogram); 269 sldns_buffer_free(mesh->qbuf_bak); 270 free(mesh); 271 } 272 273 void 274 mesh_delete_all(struct mesh_area* mesh) 275 { 276 /* free all query states */ 277 while(mesh->all.count) 278 mesh_delete_helper(mesh->all.root); 279 mesh->stats_dropped += mesh->num_reply_addrs; 280 /* clear mesh area references */ 281 rbtree_init(&mesh->run, &mesh_state_compare); 282 rbtree_init(&mesh->all, &mesh_state_compare); 283 mesh->num_reply_addrs = 0; 284 mesh->num_reply_states = 0; 285 mesh->num_detached_states = 0; 286 mesh->num_forever_states = 0; 287 mesh->forever_first = NULL; 288 mesh->forever_last = NULL; 289 mesh->jostle_first = NULL; 290 mesh->jostle_last = NULL; 291 } 292 293 int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf) 294 { 295 struct mesh_state* m = mesh->jostle_first; 296 /* free space is available */ 297 if(mesh->num_reply_states < mesh->max_reply_states) 298 return 1; 299 /* try to kick out a jostle-list item */ 300 if(m && m->list_select == mesh_jostle_list) { 301 /* how old is it? */ 302 struct timeval age; 303 if(m->has_first_reply_time) 304 timeval_subtract(&age, mesh->env->now_tv, 305 &m->first_reply_time); 306 if(!m->has_first_reply_time || 307 timeval_smaller(&mesh->jostle_max, &age)) { 308 /* its a goner */ 309 log_nametypeclass(VERB_ALGO, "query jostled out to " 310 "make space for a new one", 311 m->s.qinfo.qname, m->s.qinfo.qtype, 312 m->s.qinfo.qclass); 313 /* backup the query */ 314 if(qbuf) sldns_buffer_copy(mesh->qbuf_bak, qbuf); 315 /* notify supers */ 316 if(m->super_set.count > 0) { 317 verbose(VERB_ALGO, "notify supers of failure"); 318 m->s.return_msg = NULL; 319 m->s.return_rcode = LDNS_RCODE_SERVFAIL; 320 mesh_walk_supers(mesh, m); 321 } 322 mesh->stats_jostled ++; 323 mesh_state_delete(&m->s); 324 /* restore the query - note that the qinfo ptr to 325 * the querybuffer is then correct again. */ 326 if(qbuf) sldns_buffer_copy(qbuf, mesh->qbuf_bak); 327 return 1; 328 } 329 } 330 /* no space for new item */ 331 return 0; 332 } 333 334 struct dns_msg* 335 mesh_serve_expired_lookup(struct module_qstate* qstate, 336 struct query_info* lookup_qinfo, int* is_expired) 337 { 338 hashvalue_type h; 339 struct lruhash_entry* e; 340 struct dns_msg* msg; 341 struct reply_info* data; 342 struct msgreply_entry* key; 343 time_t timenow = *qstate->env->now; 344 int must_validate = (!(qstate->query_flags&BIT_CD) 345 || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate; 346 *is_expired = 0; 347 /* Lookup cache */ 348 h = query_info_hash(lookup_qinfo, qstate->query_flags); 349 e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0); 350 if(!e) return NULL; 351 352 key = (struct msgreply_entry*)e->key; 353 data = (struct reply_info*)e->data; 354 if(TTL_IS_EXPIRED(data->ttl, timenow)) *is_expired = 1; 355 msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow, 356 qstate->env->cfg->serve_expired, qstate->env->scratch); 357 if(!msg) 358 goto bail_out; 359 360 /* Check CNAME chain (if any) 361 * This is part of tomsg above; no need to check now. */ 362 363 /* Check security status of the cached answer. 364 * tomsg above has a subset of these checks, so we are leaving 365 * these as is. 366 * In case of bogus or revalidation we don't care to reply here. */ 367 if(must_validate && (msg->rep->security == sec_status_bogus || 368 msg->rep->security == sec_status_secure_sentinel_fail)) { 369 verbose(VERB_ALGO, "Serve expired: bogus answer found in cache"); 370 goto bail_out; 371 } else if(msg->rep->security == sec_status_unchecked && must_validate) { 372 verbose(VERB_ALGO, "Serve expired: unchecked entry needs " 373 "validation"); 374 goto bail_out; /* need to validate cache entry first */ 375 } else if(msg->rep->security == sec_status_secure && 376 !reply_an_ns_rrsets_secure(msg->rep) && must_validate) { 377 verbose(VERB_ALGO, "Serve expired: secure entry" 378 " changed status"); 379 goto bail_out; /* rrset changed, re-verify */ 380 } 381 382 lock_rw_unlock(&e->lock); 383 return msg; 384 385 bail_out: 386 lock_rw_unlock(&e->lock); 387 return NULL; 388 } 389 390 391 /** Init the serve expired data structure */ 392 static int 393 mesh_serve_expired_init(struct mesh_state* mstate, int timeout) 394 { 395 struct timeval t; 396 397 /* Create serve_expired_data if not there yet */ 398 if(!mstate->s.serve_expired_data) { 399 mstate->s.serve_expired_data = (struct serve_expired_data*) 400 regional_alloc_zero( 401 mstate->s.region, sizeof(struct serve_expired_data)); 402 if(!mstate->s.serve_expired_data) 403 return 0; 404 } 405 406 /* Don't overwrite the function if already set */ 407 mstate->s.serve_expired_data->get_cached_answer = 408 mstate->s.serve_expired_data->get_cached_answer? 409 mstate->s.serve_expired_data->get_cached_answer: 410 &mesh_serve_expired_lookup; 411 412 /* In case this timer already popped, start it again */ 413 if(!mstate->s.serve_expired_data->timer && timeout != -1) { 414 mstate->s.serve_expired_data->timer = comm_timer_create( 415 mstate->s.env->worker_base, mesh_serve_expired_callback, mstate); 416 if(!mstate->s.serve_expired_data->timer) 417 return 0; 418 #ifndef S_SPLINT_S 419 t.tv_sec = timeout/1000; 420 t.tv_usec = (timeout%1000)*1000; 421 #endif 422 comm_timer_set(mstate->s.serve_expired_data->timer, &t); 423 } 424 return 1; 425 } 426 427 /** remove a reply without accounting, rollback the add reply. */ 428 static void 429 mesh_remove_reply_without_accounting(struct mesh_state* s, 430 struct mesh_reply* todel) 431 { 432 struct mesh_reply* r, *prev = NULL; 433 for(r = s->reply_list; r; r = r->next) { 434 if(r == todel) { 435 if(prev) 436 prev->next = r->next; 437 else s->reply_list = r->next; 438 r->next = NULL; 439 /* todel is allocated in region */ 440 return; 441 } 442 prev = r; 443 } 444 } 445 446 /** remove a callback without accounting, rollback the add reply. */ 447 static void 448 mesh_remove_callback_without_accounting(struct mesh_state* s, 449 struct mesh_cb* todel) 450 { 451 struct mesh_cb* r, *prev = NULL; 452 for(r = s->cb_list; r; r = r->next) { 453 if(r == todel) { 454 if(prev) 455 prev->next = r->next; 456 else s->cb_list = r->next; 457 r->next = NULL; 458 /* todel is allocated in region */ 459 return; 460 } 461 prev = r; 462 } 463 } 464 465 void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, 466 struct respip_client_info* cinfo, uint16_t qflags, 467 struct edns_data* edns, struct comm_reply* rep, uint16_t qid, 468 int rpz_passthru) 469 { 470 struct mesh_state* s = NULL; 471 int unique = unique_mesh_state(edns->opt_list_in, mesh->env); 472 int was_detached = 0; 473 int was_noreply = 0; 474 int added = 0, added_reply_without_accounting = 0, added_tcp = 0; 475 struct mesh_reply* repadded = NULL; 476 int timeout = mesh->env->cfg->serve_expired? 477 mesh->env->cfg->serve_expired_client_timeout:0; 478 struct sldns_buffer* r_buffer = rep->c->buffer; 479 uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD); 480 if(rep->c->tcp_req_info) { 481 r_buffer = rep->c->tcp_req_info->spool_buffer; 482 } 483 if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep, 484 edns->cookie_valid, mesh->env->cfg)) { 485 verbose(VERB_ALGO, "Too many queries waiting from the IP. " 486 "servfail incoming query."); 487 mesh->num_queries_wait_limit++; 488 edns_opt_list_append_ede(&edns->opt_list_out, 489 mesh->env->scratch, LDNS_EDE_OTHER, 490 "Too many queries queued up and waiting from the IP"); 491 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, 492 LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) 493 edns->opt_list_inplace_cb_out = NULL; 494 error_encode(r_buffer, LDNS_RCODE_SERVFAIL, 495 qinfo, qid, qflags, edns); 496 regional_free_all(mesh->env->scratch); 497 comm_point_send_reply(rep); 498 return; 499 } 500 if(!unique) 501 s = mesh_area_find(mesh, cinfo, qinfo, mesh_flags, 0, 0); 502 /* does this create a new reply state? */ 503 if(!s || s->list_select == mesh_no_list) { 504 if(!mesh_make_new_space(mesh, rep->c->buffer)) { 505 verbose(VERB_ALGO, "Too many queries. dropping " 506 "incoming query."); 507 if(rep->c->use_h2) 508 http2_stream_remove_mesh_state(rep->c->h2_stream); 509 else if(rep->c->type == comm_doq && rep->doq_stream) 510 doq_stream_remove_mesh_state(rep->doq_stream); 511 comm_point_drop_reply(rep); 512 mesh->stats_dropped++; 513 return; 514 } 515 /* for this new reply state, the reply address is free, 516 * so the limit of reply addresses does not stop reply states*/ 517 } else { 518 /* protect our memory usage from storing reply addresses */ 519 if(mesh->num_reply_addrs > mesh->max_reply_states*16) { 520 verbose(VERB_ALGO, "Too many requests queued. " 521 "dropping incoming query."); 522 if(rep->c->use_h2) 523 http2_stream_remove_mesh_state(rep->c->h2_stream); 524 else if(rep->c->type == comm_doq && rep->doq_stream) 525 doq_stream_remove_mesh_state(rep->doq_stream); 526 comm_point_drop_reply(rep); 527 mesh->num_queries_replyaddr_limit++; 528 return; 529 } 530 } 531 /* see if it already exists, if not, create one */ 532 if(!s) { 533 #ifdef UNBOUND_DEBUG 534 struct rbnode_type* n; 535 #endif 536 s = mesh_state_create(mesh->env, qinfo, cinfo, 537 mesh_flags, 0, 0); 538 if(!s) { 539 log_err("mesh_state_create: out of memory; SERVFAIL"); 540 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, 541 LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) 542 edns->opt_list_inplace_cb_out = NULL; 543 error_encode(r_buffer, LDNS_RCODE_SERVFAIL, 544 qinfo, qid, qflags, edns); 545 comm_point_send_reply(rep); 546 return; 547 } 548 /* set detached (it is now) */ 549 mesh->num_detached_states++; 550 if(unique) 551 mesh_state_make_unique(s); 552 s->s.rpz_passthru = rpz_passthru; 553 /* copy the edns options we got from the front */ 554 if(edns->opt_list_in) { 555 s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, 556 s->s.region); 557 if(!s->s.edns_opts_front_in) { 558 log_err("edns_opt_copy_region: out of memory; SERVFAIL"); 559 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, 560 NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) 561 edns->opt_list_inplace_cb_out = NULL; 562 error_encode(r_buffer, LDNS_RCODE_SERVFAIL, 563 qinfo, qid, qflags, edns); 564 comm_point_send_reply(rep); 565 mesh_state_delete(&s->s); 566 return; 567 } 568 } 569 570 #ifdef UNBOUND_DEBUG 571 n = 572 #else 573 (void) 574 #endif 575 rbtree_insert(&mesh->all, &s->node); 576 log_assert(n != NULL); 577 added = 1; 578 } 579 if(!s->reply_list && !s->cb_list) { 580 was_noreply = 1; 581 if(s->super_set.count == 0) { 582 was_detached = 1; 583 } 584 } 585 /* add reply to s */ 586 if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo, &repadded)) { 587 log_err("mesh_new_client: out of memory; SERVFAIL"); 588 goto servfail_mem; 589 } 590 added_reply_without_accounting = 1; 591 if(rep->c->tcp_req_info) { 592 if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) { 593 log_err("mesh_new_client: out of memory add tcpreqinfo"); 594 goto servfail_mem; 595 } 596 } 597 added_tcp = 1; 598 if(rep->c->use_h2) { 599 http2_stream_add_meshstate(rep->c->h2_stream, mesh, s); 600 } else if(rep->c->type == comm_doq && rep->doq_stream) { 601 doq_stream_add_meshstate(rep->doq_stream, mesh, s); 602 } 603 /* add serve expired timer if required and not already there */ 604 if(timeout && !mesh_serve_expired_init(s, timeout)) { 605 log_err("mesh_new_client: out of memory initializing serve expired"); 606 goto servfail_mem; 607 } 608 #ifdef USE_CACHEDB 609 if(!timeout && mesh->env->cfg->serve_expired && 610 !mesh->env->cfg->serve_expired_client_timeout && 611 (mesh->env->cachedb_enabled && 612 mesh->env->cfg->cachedb_check_when_serve_expired)) { 613 if(!mesh_serve_expired_init(s, -1)) { 614 log_err("mesh_new_client: out of memory initializing serve expired"); 615 goto servfail_mem; 616 } 617 } 618 #endif 619 /* Since the acccounting now happens, 620 * added_reply_without_accounting = 0; but that is not used. */ 621 infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now, 622 mesh->env->cfg); 623 /* update statistics */ 624 if(was_detached) { 625 log_assert(mesh->num_detached_states > 0); 626 mesh->num_detached_states--; 627 } 628 if(was_noreply) { 629 mesh->num_reply_states ++; 630 } 631 mesh->num_reply_addrs++; 632 if(s->list_select == mesh_no_list) { 633 /* move to either the forever or the jostle_list */ 634 if(mesh->num_forever_states < mesh->max_forever_states) { 635 mesh->num_forever_states ++; 636 mesh_list_insert(s, &mesh->forever_first, 637 &mesh->forever_last); 638 s->list_select = mesh_forever_list; 639 } else { 640 mesh_list_insert(s, &mesh->jostle_first, 641 &mesh->jostle_last); 642 s->list_select = mesh_jostle_list; 643 } 644 } 645 if(added) 646 mesh_run(mesh, s, module_event_new, NULL); 647 return; 648 649 servfail_mem: 650 if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s, 651 NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) 652 edns->opt_list_inplace_cb_out = NULL; 653 error_encode(r_buffer, LDNS_RCODE_SERVFAIL, 654 qinfo, qid, qflags, edns); 655 if(rep->c->use_h2) 656 http2_stream_remove_mesh_state(rep->c->h2_stream); 657 else if(rep->c->type == comm_doq && rep->doq_stream) 658 doq_stream_remove_mesh_state(rep->doq_stream); 659 comm_point_send_reply(rep); 660 if(added_reply_without_accounting) { 661 mesh_remove_reply_without_accounting(s, repadded); 662 if(added_tcp && rep->c->tcp_req_info) 663 tcp_req_info_remove_mesh_state(rep->c->tcp_req_info, s); 664 } 665 if(added) 666 mesh_state_delete(&s->s); 667 return; 668 } 669 670 int 671 mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, 672 uint16_t qflags, struct edns_data* edns, sldns_buffer* buf, 673 uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru, 674 void** unique_info) 675 { 676 struct mesh_state* s = NULL; 677 int unique = unique_mesh_state(edns->opt_list_in, mesh->env); 678 int timeout = mesh->env->cfg->serve_expired? 679 mesh->env->cfg->serve_expired_client_timeout:0; 680 int was_detached = 0; 681 int was_noreply = 0; 682 int added = 0; 683 struct mesh_cb* add_cb = NULL; 684 uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD); 685 if(!unique) 686 s = mesh_area_find(mesh, NULL, qinfo, mesh_flags, 0, 0); 687 688 /* there are no limits on the number of callbacks */ 689 690 /* see if it already exists, if not, create one */ 691 if(!s) { 692 #ifdef UNBOUND_DEBUG 693 struct rbnode_type* n; 694 #endif 695 s = mesh_state_create(mesh->env, qinfo, NULL, 696 mesh_flags, 0, 0); 697 if(!s) { 698 return 0; 699 } 700 /* set detached (it is now) */ 701 mesh->num_detached_states++; 702 if(unique) 703 mesh_state_make_unique(s); 704 s->s.rpz_passthru = rpz_passthru; 705 if(edns->opt_list_in) { 706 s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, 707 s->s.region); 708 if(!s->s.edns_opts_front_in) { 709 mesh_state_delete(&s->s); 710 return 0; 711 } 712 } 713 #ifdef UNBOUND_DEBUG 714 n = 715 #else 716 (void) 717 #endif 718 rbtree_insert(&mesh->all, &s->node); 719 log_assert(n != NULL); 720 added = 1; 721 } 722 if(!s->reply_list && !s->cb_list) { 723 was_noreply = 1; 724 if(s->super_set.count == 0) { 725 was_detached = 1; 726 } 727 } 728 /* add reply to s */ 729 if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags, &add_cb)) { 730 if(added) 731 mesh_state_delete(&s->s); 732 return 0; 733 } 734 /* add serve expired timer if not already there */ 735 if(timeout && !mesh_serve_expired_init(s, timeout)) { 736 mesh_remove_callback_without_accounting(s, add_cb); 737 if(added) 738 mesh_state_delete(&s->s); 739 return 0; 740 } 741 #ifdef USE_CACHEDB 742 if(!timeout && mesh->env->cfg->serve_expired && 743 !mesh->env->cfg->serve_expired_client_timeout && 744 (mesh->env->cachedb_enabled && 745 mesh->env->cfg->cachedb_check_when_serve_expired)) { 746 if(!mesh_serve_expired_init(s, -1)) { 747 mesh_remove_callback_without_accounting(s, add_cb); 748 if(added) 749 mesh_state_delete(&s->s); 750 return 0; 751 } 752 } 753 #endif 754 /* update statistics */ 755 if(was_detached) { 756 log_assert(mesh->num_detached_states > 0); 757 mesh->num_detached_states--; 758 } 759 if(was_noreply) { 760 mesh->num_reply_states ++; 761 } 762 mesh->num_reply_addrs++; 763 if(unique_info) 764 *unique_info = s->unique; 765 if(added) 766 mesh_run(mesh, s, module_event_new, NULL); 767 return 1; 768 } 769 770 /* Internal backend routine of mesh_new_prefetch(). It takes one additional 771 * parameter, 'run', which controls whether to run the prefetch state 772 * immediately. When this function is called internally 'run' could be 773 * 0 (false), in which case the new state is only made runnable so it 774 * will not be run recursively on top of the current state. */ 775 static void mesh_schedule_prefetch(struct mesh_area* mesh, 776 struct query_info* qinfo, uint16_t qflags, time_t leeway, int run, 777 int rpz_passthru) 778 { 779 /* Explicitly set the BIT_RD regardless of the client's flags. This is 780 * for a prefetch query (no client attached) but it needs to be treated 781 * as a recursion query. */ 782 uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD); 783 struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo, 784 mesh_flags, 0, 0); 785 #ifdef UNBOUND_DEBUG 786 struct rbnode_type* n; 787 #endif 788 /* already exists, and for a different purpose perhaps. 789 * if mesh_no_list, keep it that way. */ 790 if(s) { 791 /* make it ignore the cache from now on */ 792 if(!s->s.blacklist) 793 sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); 794 if(s->s.prefetch_leeway < leeway) 795 s->s.prefetch_leeway = leeway; 796 return; 797 } 798 if(!mesh_make_new_space(mesh, NULL)) { 799 verbose(VERB_ALGO, "Too many queries. dropped prefetch."); 800 mesh->stats_dropped ++; 801 return; 802 } 803 804 s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0); 805 if(!s) { 806 log_err("prefetch mesh_state_create: out of memory"); 807 return; 808 } 809 #ifdef UNBOUND_DEBUG 810 n = 811 #else 812 (void) 813 #endif 814 rbtree_insert(&mesh->all, &s->node); 815 log_assert(n != NULL); 816 /* set detached (it is now) */ 817 mesh->num_detached_states++; 818 /* make it ignore the cache */ 819 sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); 820 s->s.prefetch_leeway = leeway; 821 822 if(s->list_select == mesh_no_list) { 823 /* move to either the forever or the jostle_list */ 824 if(mesh->num_forever_states < mesh->max_forever_states) { 825 mesh->num_forever_states ++; 826 mesh_list_insert(s, &mesh->forever_first, 827 &mesh->forever_last); 828 s->list_select = mesh_forever_list; 829 } else { 830 mesh_list_insert(s, &mesh->jostle_first, 831 &mesh->jostle_last); 832 s->list_select = mesh_jostle_list; 833 } 834 } 835 s->s.rpz_passthru = rpz_passthru; 836 837 if(!run) { 838 #ifdef UNBOUND_DEBUG 839 n = 840 #else 841 (void) 842 #endif 843 rbtree_insert(&mesh->run, &s->run_node); 844 log_assert(n != NULL); 845 return; 846 } 847 848 mesh_run(mesh, s, module_event_new, NULL); 849 } 850 851 #ifdef CLIENT_SUBNET 852 /* Same logic as mesh_schedule_prefetch but tailored to the subnet module logic 853 * like passing along the comm_reply info. This will be faked into an EDNS 854 * option for processing by the subnet module if the client has not already 855 * attached its own ECS data. */ 856 static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh, 857 struct query_info* qinfo, uint16_t qflags, time_t leeway, int run, 858 int rpz_passthru, struct sockaddr_storage* addr, struct edns_option* edns_list) 859 { 860 struct mesh_state* s = NULL; 861 struct edns_option* opt = NULL; 862 #ifdef UNBOUND_DEBUG 863 struct rbnode_type* n; 864 #endif 865 /* Explicitly set the BIT_RD regardless of the client's flags. This is 866 * for a prefetch query (no client attached) but it needs to be treated 867 * as a recursion query. */ 868 uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD); 869 if(!mesh_make_new_space(mesh, NULL)) { 870 verbose(VERB_ALGO, "Too many queries. dropped prefetch."); 871 mesh->stats_dropped ++; 872 return; 873 } 874 875 s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0); 876 if(!s) { 877 log_err("prefetch_subnet mesh_state_create: out of memory"); 878 return; 879 } 880 mesh_state_make_unique(s); 881 882 opt = edns_opt_list_find(edns_list, mesh->env->cfg->client_subnet_opcode); 883 if(opt) { 884 /* Use the client's ECS data */ 885 if(!edns_opt_list_append(&s->s.edns_opts_front_in, opt->opt_code, 886 opt->opt_len, opt->opt_data, s->s.region)) { 887 log_err("prefetch_subnet edns_opt_list_append: out of memory"); 888 return; 889 } 890 } else { 891 /* Store the client's address. Later in the subnet module, 892 * it is decided whether to include an ECS option or not. 893 */ 894 s->s.client_addr = *addr; 895 } 896 #ifdef UNBOUND_DEBUG 897 n = 898 #else 899 (void) 900 #endif 901 rbtree_insert(&mesh->all, &s->node); 902 log_assert(n != NULL); 903 /* set detached (it is now) */ 904 mesh->num_detached_states++; 905 /* make it ignore the cache */ 906 sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region); 907 s->s.prefetch_leeway = leeway; 908 909 if(s->list_select == mesh_no_list) { 910 /* move to either the forever or the jostle_list */ 911 if(mesh->num_forever_states < mesh->max_forever_states) { 912 mesh->num_forever_states ++; 913 mesh_list_insert(s, &mesh->forever_first, 914 &mesh->forever_last); 915 s->list_select = mesh_forever_list; 916 } else { 917 mesh_list_insert(s, &mesh->jostle_first, 918 &mesh->jostle_last); 919 s->list_select = mesh_jostle_list; 920 } 921 } 922 s->s.rpz_passthru = rpz_passthru; 923 924 if(!run) { 925 #ifdef UNBOUND_DEBUG 926 n = 927 #else 928 (void) 929 #endif 930 rbtree_insert(&mesh->run, &s->run_node); 931 log_assert(n != NULL); 932 return; 933 } 934 935 mesh_run(mesh, s, module_event_new, NULL); 936 } 937 #endif /* CLIENT_SUBNET */ 938 939 void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo, 940 uint16_t qflags, time_t leeway, int rpz_passthru, 941 struct sockaddr_storage* addr, struct edns_option* opt_list) 942 { 943 (void)addr; 944 (void)opt_list; 945 #ifdef CLIENT_SUBNET 946 if(addr) 947 mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1, 948 rpz_passthru, addr, opt_list); 949 else 950 #endif 951 mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1, 952 rpz_passthru); 953 } 954 955 void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e, 956 struct comm_reply* reply, int what) 957 { 958 enum module_ev event = module_event_reply; 959 e->qstate->reply = reply; 960 if(what != NETEVENT_NOERROR) { 961 event = module_event_noreply; 962 if(what == NETEVENT_CAPSFAIL) 963 event = module_event_capsfail; 964 } 965 mesh_run(mesh, e->qstate->mesh_info, event, e); 966 } 967 968 struct respip_client_info* 969 mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo) 970 { 971 struct respip_client_info* client_info; 972 client_info = regional_alloc_init(region, cinfo, sizeof(*cinfo)); 973 if(!client_info) 974 return NULL; 975 /* Copy the client_info so that if the configuration changes, 976 * then the data stays valid. */ 977 if(cinfo->taglist) { 978 client_info->taglist = regional_alloc_init(region, cinfo->taglist, 979 cinfo->taglen); 980 if(!client_info->taglist) 981 return NULL; 982 } 983 if(cinfo->tag_actions) { 984 client_info->tag_actions = regional_alloc_init(region, cinfo->tag_actions, 985 cinfo->tag_actions_size); 986 if(!client_info->tag_actions) 987 return NULL; 988 } 989 /* tag_datas is owned by the matched acl_addr in config_file; its 990 * lifetime is until config reload, which tears down all mesh states 991 * first. Keep the original pointer so client_info_compare() 992 * can recognise two states from the same ACL entry. */ 993 /* fast reload insists on dropping the queries when interface-tag-data 994 * or access-control-tag-data are changed. */ 995 /* client_info->tag_datas already copied by regional_alloc_init above */ 996 if(cinfo->view) { 997 /* Do not copy the view pointer but store a name instead. 998 * The name is looked up later when done, this means that 999 * the view tree can be changed, by reloads. */ 1000 client_info->view = NULL; 1001 client_info->view_name = regional_strdup(region, 1002 cinfo->view->name); 1003 if(!client_info->view_name) 1004 return NULL; 1005 } else if(cinfo->view_name) { 1006 client_info->view_name = regional_strdup(region, 1007 cinfo->view_name); 1008 if(!client_info->view_name) 1009 return NULL; 1010 } 1011 return client_info; 1012 } 1013 1014 struct mesh_state* 1015 mesh_state_create(struct module_env* env, struct query_info* qinfo, 1016 struct respip_client_info* cinfo, uint16_t qflags, int prime, 1017 int valrec) 1018 { 1019 struct regional* region = alloc_reg_obtain(env->alloc); 1020 struct mesh_state* mstate; 1021 int i; 1022 if(!region) 1023 return NULL; 1024 mstate = (struct mesh_state*)regional_alloc(region, 1025 sizeof(struct mesh_state)); 1026 if(!mstate) { 1027 alloc_reg_release(env->alloc, region); 1028 return NULL; 1029 } 1030 memset(mstate, 0, sizeof(*mstate)); 1031 mstate->node = *RBTREE_NULL; 1032 mstate->run_node = *RBTREE_NULL; 1033 mstate->node.key = mstate; 1034 mstate->run_node.key = mstate; 1035 mstate->reply_list = NULL; 1036 mstate->list_select = mesh_no_list; 1037 mstate->replies_sent = 0; 1038 rbtree_init(&mstate->super_set, &mesh_state_ref_compare); 1039 rbtree_init(&mstate->sub_set, &mesh_state_ref_compare); 1040 mstate->num_activated = 0; 1041 mstate->unique = NULL; 1042 /* init module qstate */ 1043 mstate->s.qinfo.qtype = qinfo->qtype; 1044 mstate->s.qinfo.qclass = qinfo->qclass; 1045 mstate->s.qinfo.local_alias = NULL; 1046 mstate->s.qinfo.qname_len = qinfo->qname_len; 1047 mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname, 1048 qinfo->qname_len); 1049 if(!mstate->s.qinfo.qname) { 1050 alloc_reg_release(env->alloc, region); 1051 return NULL; 1052 } 1053 if(cinfo) { 1054 mstate->s.client_info = mesh_copy_client_info(region, cinfo); 1055 if(!mstate->s.client_info) { 1056 alloc_reg_release(env->alloc, region); 1057 return NULL; 1058 } 1059 } 1060 /* remove all weird bits from qflags */ 1061 mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD)); 1062 mstate->s.is_priming = prime; 1063 mstate->s.is_valrec = valrec; 1064 mstate->s.reply = NULL; 1065 mstate->s.region = region; 1066 mstate->s.curmod = 0; 1067 mstate->s.return_msg = 0; 1068 mstate->s.return_rcode = LDNS_RCODE_NOERROR; 1069 mstate->s.env = env; 1070 mstate->s.mesh_info = mstate; 1071 mstate->s.prefetch_leeway = 0; 1072 mstate->s.serve_expired_data = NULL; 1073 mstate->s.no_cache_lookup = 0; 1074 mstate->s.no_cache_store = 0; 1075 mstate->s.need_refetch = 0; 1076 mstate->s.was_ratelimited = 0; 1077 mstate->s.error_response_cache = 0; 1078 mstate->s.qstarttime = *env->now; 1079 1080 /* init modules */ 1081 for(i=0; i<env->mesh->mods.num; i++) { 1082 mstate->s.minfo[i] = NULL; 1083 mstate->s.ext_state[i] = module_state_initial; 1084 } 1085 /* init edns option lists */ 1086 mstate->s.edns_opts_front_in = NULL; 1087 mstate->s.edns_opts_back_out = NULL; 1088 mstate->s.edns_opts_back_in = NULL; 1089 mstate->s.edns_opts_front_out = NULL; 1090 1091 return mstate; 1092 } 1093 1094 void 1095 mesh_state_make_unique(struct mesh_state* mstate) 1096 { 1097 mstate->unique = mstate; 1098 } 1099 1100 /** pop a reply from the reply list, if there are any. */ 1101 static struct mesh_reply* 1102 mesh_reply_list_pop_first(struct mesh_state* mstate) 1103 { 1104 if(mstate->reply_list) { 1105 struct mesh_reply* r = mstate->reply_list; 1106 mstate->reply_list = r->next; 1107 return r; 1108 } 1109 return NULL; 1110 } 1111 1112 void 1113 mesh_state_cleanup(struct mesh_state* mstate) 1114 { 1115 struct mesh_area* mesh; 1116 int i; 1117 if(!mstate) 1118 return; 1119 mesh = mstate->s.env->mesh; 1120 /* Stop and delete the serve expired timer */ 1121 if(mstate->s.serve_expired_data && mstate->s.serve_expired_data->timer) { 1122 comm_timer_delete(mstate->s.serve_expired_data->timer); 1123 mstate->s.serve_expired_data->timer = NULL; 1124 } 1125 /* drop unsent replies */ 1126 if(!mstate->replies_sent) { 1127 struct mesh_reply* rep; 1128 struct mesh_cb* cb; 1129 /* Pop items from the list, that means there is no iterator. 1130 * And then items can be removed from the reply list, from 1131 * like comm_point_drop_reply and comm_point_close calls. 1132 * As the tcp_req_info and http2 code drops the entire 1133 * connection. That could delete mesh_reply items previous and 1134 * after the current state. The previous items are already 1135 * popped. And the next items can be altered, like to when a 1136 * connection has more replies on the reply list. 1137 * The current item is also popped so the code needs to 1138 * remove its references. */ 1139 while((rep = mesh_reply_list_pop_first(mstate)) != NULL) { 1140 infra_wait_limit_dec(mesh->env->infra_cache, 1141 &rep->query_reply, mesh->env->cfg); 1142 if(rep->query_reply.c->tcp_req_info) 1143 tcp_req_info_remove_mesh_state( 1144 rep->query_reply.c->tcp_req_info, 1145 mstate); 1146 else if(rep->query_reply.c->use_h2) 1147 http2_stream_remove_mesh_state(rep->h2_stream); 1148 else if(rep->query_reply.doq_stream) 1149 doq_stream_remove_mesh_state( 1150 rep->query_reply.doq_stream); 1151 comm_point_drop_reply(&rep->query_reply); 1152 log_assert(mesh->num_reply_addrs > 0); 1153 mesh->num_reply_addrs--; 1154 } 1155 while((cb = mstate->cb_list)!=NULL) { 1156 mstate->cb_list = cb->next; 1157 fptr_ok(fptr_whitelist_mesh_cb(cb->cb)); 1158 (*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL, 1159 sec_status_unchecked, NULL, 0); 1160 log_assert(mesh->num_reply_addrs > 0); 1161 mesh->num_reply_addrs--; 1162 } 1163 } 1164 1165 /* de-init modules */ 1166 for(i=0; i<mesh->mods.num; i++) { 1167 fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear)); 1168 (*mesh->mods.mod[i]->clear)(&mstate->s, i); 1169 mstate->s.minfo[i] = NULL; 1170 mstate->s.ext_state[i] = module_finished; 1171 } 1172 alloc_reg_release(mstate->s.env->alloc, mstate->s.region); 1173 } 1174 1175 void 1176 mesh_state_delete(struct module_qstate* qstate) 1177 { 1178 struct mesh_area* mesh; 1179 struct mesh_state_ref* super, ref; 1180 struct mesh_state* mstate; 1181 if(!qstate) 1182 return; 1183 mstate = qstate->mesh_info; 1184 mesh = mstate->s.env->mesh; 1185 mesh_detach_subs(&mstate->s); 1186 if(mstate->list_select == mesh_forever_list) { 1187 mesh->num_forever_states --; 1188 mesh_list_remove(mstate, &mesh->forever_first, 1189 &mesh->forever_last); 1190 } else if(mstate->list_select == mesh_jostle_list) { 1191 mesh_list_remove(mstate, &mesh->jostle_first, 1192 &mesh->jostle_last); 1193 } 1194 if(!mstate->reply_list && !mstate->cb_list 1195 && mstate->super_set.count == 0) { 1196 log_assert(mesh->num_detached_states > 0); 1197 mesh->num_detached_states--; 1198 } 1199 if(mstate->reply_list || mstate->cb_list) { 1200 log_assert(mesh->num_reply_states > 0); 1201 mesh->num_reply_states--; 1202 } 1203 ref.node.key = &ref; 1204 ref.s = mstate; 1205 RBTREE_FOR(super, struct mesh_state_ref*, &mstate->super_set) { 1206 (void)rbtree_delete(&super->s->sub_set, &ref); 1207 } 1208 (void)rbtree_delete(&mesh->run, mstate); 1209 (void)rbtree_delete(&mesh->all, mstate); 1210 mesh_state_cleanup(mstate); 1211 } 1212 1213 /** helper recursive rbtree find routine */ 1214 static int 1215 find_in_subsub(struct mesh_state* m, struct mesh_state* tofind, size_t *c) 1216 { 1217 struct mesh_state_ref* r; 1218 if((*c)++ > MESH_MAX_SUBSUB) 1219 return 1; 1220 RBTREE_FOR(r, struct mesh_state_ref*, &m->sub_set) { 1221 if(r->s == tofind || find_in_subsub(r->s, tofind, c)) 1222 return 1; 1223 } 1224 return 0; 1225 } 1226 1227 /** find cycle for already looked up mesh_state */ 1228 static int 1229 mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m) 1230 { 1231 struct mesh_state* cyc_m = qstate->mesh_info; 1232 size_t counter = 0; 1233 log_assert(dep_m); 1234 if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m, &counter)) { 1235 if(counter > MESH_MAX_SUBSUB) 1236 return 2; 1237 return 1; 1238 } 1239 return 0; 1240 } 1241 1242 void mesh_detach_subs(struct module_qstate* qstate) 1243 { 1244 struct mesh_area* mesh = qstate->env->mesh; 1245 struct mesh_state_ref* ref, lookup; 1246 #ifdef UNBOUND_DEBUG 1247 struct rbnode_type* n; 1248 #endif 1249 lookup.node.key = &lookup; 1250 lookup.s = qstate->mesh_info; 1251 RBTREE_FOR(ref, struct mesh_state_ref*, &qstate->mesh_info->sub_set) { 1252 #ifdef UNBOUND_DEBUG 1253 n = 1254 #else 1255 (void) 1256 #endif 1257 rbtree_delete(&ref->s->super_set, &lookup); 1258 log_assert(n != NULL); /* must have been present */ 1259 if(!ref->s->reply_list && !ref->s->cb_list 1260 && ref->s->super_set.count == 0) { 1261 mesh->num_detached_states++; 1262 log_assert(mesh->num_detached_states + 1263 mesh->num_reply_states <= mesh->all.count); 1264 } 1265 } 1266 rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare); 1267 } 1268 1269 int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, 1270 struct respip_client_info* cinfo, uint16_t qflags, int prime, 1271 int valrec, struct module_qstate** newq, struct mesh_state** sub) 1272 { 1273 /* find it, if not, create it */ 1274 struct mesh_area* mesh = qstate->env->mesh; 1275 *sub = mesh_area_find(mesh, cinfo, qinfo, qflags, prime, valrec); 1276 if(!*sub) { 1277 #ifdef UNBOUND_DEBUG 1278 struct rbnode_type* n; 1279 #endif 1280 /* create a new one */ 1281 *sub = mesh_state_create(qstate->env, qinfo, cinfo, qflags, 1282 prime, valrec); 1283 if(!*sub) { 1284 log_err("mesh_attach_sub: out of memory"); 1285 return 0; 1286 } 1287 /* inherit RPZ passthru from the parent so respip on the sub 1288 * sees the same client-IP/qname PASSTHRU decision */ 1289 (*sub)->s.rpz_passthru = qstate->rpz_passthru; 1290 #ifdef UNBOUND_DEBUG 1291 n = 1292 #else 1293 (void) 1294 #endif 1295 rbtree_insert(&mesh->all, &(*sub)->node); 1296 log_assert(n != NULL); 1297 /* set detached (it is now) */ 1298 mesh->num_detached_states++; 1299 /* set new query state to run */ 1300 #ifdef UNBOUND_DEBUG 1301 n = 1302 #else 1303 (void) 1304 #endif 1305 rbtree_insert(&mesh->run, &(*sub)->run_node); 1306 log_assert(n != NULL); 1307 *newq = &(*sub)->s; 1308 } else { 1309 *newq = NULL; 1310 if(mesh_detect_cycle_found(qstate, *sub)) { 1311 verbose(VERB_ALGO, "attach failed, cycle detected"); 1312 return 0; 1313 } 1314 } 1315 return 1; 1316 } 1317 1318 int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, 1319 struct respip_client_info* cinfo, uint16_t qflags, int prime, 1320 int valrec, struct module_qstate** newq) 1321 { 1322 struct mesh_area* mesh = qstate->env->mesh; 1323 struct mesh_state* sub = NULL; 1324 int was_detached; 1325 if(!mesh_add_sub(qstate, qinfo, cinfo, qflags, prime, valrec, newq, 1326 &sub)) 1327 return 0; 1328 was_detached = (sub->super_set.count == 0); 1329 if(!mesh_state_attachment(qstate->mesh_info, sub)) 1330 return 0; 1331 /* if it was a duplicate attachment, the count was not zero before */ 1332 if(!sub->reply_list && !sub->cb_list && was_detached && 1333 sub->super_set.count == 1) { 1334 /* it used to be detached, before this one got added */ 1335 log_assert(mesh->num_detached_states > 0); 1336 mesh->num_detached_states--; 1337 } 1338 /* *newq will be run when inited after the current module stops */ 1339 return 1; 1340 } 1341 1342 int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub) 1343 { 1344 #ifdef UNBOUND_DEBUG 1345 struct rbnode_type* n; 1346 #endif 1347 struct mesh_state_ref* subref; /* points to sub, inserted in super */ 1348 struct mesh_state_ref* superref; /* points to super, inserted in sub */ 1349 if( !(subref = regional_alloc(super->s.region, 1350 sizeof(struct mesh_state_ref))) || 1351 !(superref = regional_alloc(sub->s.region, 1352 sizeof(struct mesh_state_ref))) ) { 1353 log_err("mesh_state_attachment: out of memory"); 1354 return 0; 1355 } 1356 superref->node.key = superref; 1357 superref->s = super; 1358 subref->node.key = subref; 1359 subref->s = sub; 1360 if(!rbtree_insert(&sub->super_set, &superref->node)) { 1361 /* this should not happen, iterator and validator do not 1362 * attach subqueries that are identical. */ 1363 /* already attached, we are done, nothing todo. 1364 * since superref and subref already allocated in region, 1365 * we cannot free them */ 1366 return 1; 1367 } 1368 #ifdef UNBOUND_DEBUG 1369 n = 1370 #else 1371 (void) 1372 #endif 1373 rbtree_insert(&super->sub_set, &subref->node); 1374 log_assert(n != NULL); /* we checked above if statement, the reverse 1375 administration should not fail now, unless they are out of sync */ 1376 return 1; 1377 } 1378 1379 /** 1380 * callback results to mesh cb entry 1381 * @param m: mesh state to send it for. 1382 * @param rcode: if not 0, error code. 1383 * @param rep: reply to send (or NULL if rcode is set). 1384 * @param r: callback entry 1385 * @param start_time: the time to pass to callback functions, it is 0 or 1386 * a value from one of the packets if the mesh state had packets. 1387 */ 1388 static void 1389 mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, 1390 struct mesh_cb* r, struct timeval* start_time) 1391 { 1392 int secure; 1393 char* reason = NULL; 1394 int was_ratelimited = m->s.was_ratelimited; 1395 /* bogus messages are not made into servfail, sec_status passed 1396 * to the callback function */ 1397 if(rep && rep->security == sec_status_secure) 1398 secure = 1; 1399 else secure = 0; 1400 if(!rep && rcode == LDNS_RCODE_NOERROR) 1401 rcode = LDNS_RCODE_SERVFAIL; 1402 if(!rcode && rep && (rep->security == sec_status_bogus || 1403 rep->security == sec_status_secure_sentinel_fail)) { 1404 if(!(reason = errinf_to_str_bogus(&m->s, NULL))) 1405 rcode = LDNS_RCODE_SERVFAIL; 1406 } 1407 /* send the reply */ 1408 if(rcode) { 1409 if(rcode == LDNS_RCODE_SERVFAIL) { 1410 if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 1411 rep, rcode, &r->edns, NULL, m->s.region, start_time)) 1412 r->edns.opt_list_inplace_cb_out = NULL; 1413 } else { 1414 if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, 1415 &r->edns, NULL, m->s.region, start_time)) 1416 r->edns.opt_list_inplace_cb_out = NULL; 1417 } 1418 fptr_ok(fptr_whitelist_mesh_cb(r->cb)); 1419 (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL, 1420 was_ratelimited); 1421 } else { 1422 size_t udp_size = r->edns.udp_size; 1423 sldns_buffer_clear(r->buf); 1424 r->edns.edns_version = EDNS_ADVERTISED_VERSION; 1425 r->edns.udp_size = EDNS_ADVERTISED_SIZE; 1426 r->edns.ext_rcode = 0; 1427 r->edns.bits &= EDNS_DO; 1428 if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) 1429 r->edns.edns_present = 0; 1430 1431 if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, 1432 LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) || 1433 !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 1434 r->qflags, r->buf, 0, 1, 1435 m->s.env->scratch, udp_size, &r->edns, 1436 (int)(r->edns.bits & EDNS_DO), secure)) 1437 { 1438 fptr_ok(fptr_whitelist_mesh_cb(r->cb)); 1439 (*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf, 1440 sec_status_unchecked, NULL, 0); 1441 } else { 1442 fptr_ok(fptr_whitelist_mesh_cb(r->cb)); 1443 (*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf, 1444 (rep?rep->security:sec_status_unchecked), 1445 reason, was_ratelimited); 1446 } 1447 } 1448 free(reason); 1449 log_assert(m->s.env->mesh->num_reply_addrs > 0); 1450 m->s.env->mesh->num_reply_addrs--; 1451 } 1452 1453 static inline int 1454 mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m) 1455 { 1456 struct respip_action_info const* respip_info = m->s.respip_action_info; 1457 return (respip_info == NULL 1458 ? 0 1459 : (respip_info->rpz_used 1460 && !respip_info->rpz_disabled 1461 && respip_info->action == respip_truncate)) 1462 || m->s.tcp_required; 1463 } 1464 1465 static inline int 1466 mesh_is_udp(struct mesh_reply const* r) 1467 { 1468 return r->query_reply.c->type == comm_udp; 1469 } 1470 1471 static inline void 1472 mesh_find_and_attach_ede_and_reason(struct mesh_state* m, 1473 struct reply_info* rep, struct mesh_reply* r) 1474 { 1475 /* OLD note: 1476 * During validation the EDE code can be received via two 1477 * code paths. One code path fills the reply_info EDE, and 1478 * the other fills it in the errinf_strlist. These paths 1479 * intersect at some points, but where is opaque due to 1480 * the complexity of the validator. At the time of writing 1481 * we make the choice to prefer the EDE from errinf_strlist 1482 * but a compelling reason to do otherwise is just as valid 1483 * NEW note: 1484 * The compelling reason is that with caching support, the value 1485 * in the reply_info is cached. 1486 * The reason members of the reply_info struct should be 1487 * updated as they are already cached. No reason to 1488 * try and find the EDE information in errinf anymore. 1489 */ 1490 if(rep->reason_bogus != LDNS_EDE_NONE) { 1491 edns_opt_list_append_ede(&r->edns.opt_list_out, 1492 m->s.region, rep->reason_bogus, rep->reason_bogus_str); 1493 } 1494 } 1495 1496 /** 1497 * Send reply to mesh reply entry 1498 * @param m: mesh state to send it for. 1499 * @param rcode: if not 0, error code. 1500 * @param rep: reply to send (or NULL if rcode is set). 1501 * @param r: reply entry 1502 * @param r_buffer: buffer to use for reply entry. 1503 * @param prev: previous reply, already has its answer encoded in buffer. 1504 * @param prev_buffer: buffer for previous reply. 1505 */ 1506 static void 1507 mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, 1508 struct mesh_reply* r, struct sldns_buffer* r_buffer, 1509 struct mesh_reply* prev, struct sldns_buffer* prev_buffer) 1510 { 1511 struct timeval end_time; 1512 struct timeval duration; 1513 int secure; 1514 1515 /* rpz: apply actions */ 1516 rcode = mesh_is_udp(r) && mesh_is_rpz_respip_tcponly_action(m) 1517 ? (rcode|BIT_TC) : rcode; 1518 1519 /* examine security status */ 1520 if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || 1521 m->s.env->cfg->ignore_cd) && rep && 1522 (rep->security <= sec_status_bogus || 1523 rep->security == sec_status_secure_sentinel_fail)) { 1524 rcode = LDNS_RCODE_SERVFAIL; 1525 if(m->s.env->cfg->stat_extended) 1526 m->s.env->mesh->ans_bogus++; 1527 } 1528 if(rep && rep->security == sec_status_secure) 1529 secure = 1; 1530 else secure = 0; 1531 if(!rep && rcode == LDNS_RCODE_NOERROR) 1532 rcode = LDNS_RCODE_SERVFAIL; 1533 if(r->query_reply.c->use_h2) { 1534 r->query_reply.c->h2_stream = r->h2_stream; 1535 /* Mesh reply won't exist for long anymore. Make it impossible 1536 * for HTTP/2 stream to refer to mesh state, in case 1537 * connection gets cleanup before HTTP/2 stream close. */ 1538 r->h2_stream->mesh_state = NULL; 1539 #ifdef HAVE_NGTCP2 1540 } else if(r->query_reply.doq_stream) { 1541 r->query_reply.doq_stream->mesh_state = NULL; 1542 #endif 1543 } 1544 /* send the reply */ 1545 /* We don't reuse the encoded answer if: 1546 * - either the previous or current response has a local alias. We could 1547 * compare the alias records and still reuse the previous answer if they 1548 * are the same, but that would be complicated and error prone for the 1549 * relatively minor case. So we err on the side of safety. 1550 * - there are registered callback functions for the given rcode, as these 1551 * need to be called for each reply. */ 1552 if(((rcode != LDNS_RCODE_SERVFAIL && 1553 !m->s.env->inplace_cb_lists[inplace_cb_reply]) || 1554 (rcode == LDNS_RCODE_SERVFAIL && 1555 !m->s.env->inplace_cb_lists[inplace_cb_reply_servfail])) && 1556 prev && prev_buffer && prev->qflags == r->qflags && 1557 !prev->local_alias && !r->local_alias && 1558 prev->edns.edns_present == r->edns.edns_present && 1559 prev->edns.bits == r->edns.bits && 1560 prev->edns.udp_size == r->edns.udp_size && 1561 edns_opt_list_compare(prev->edns.opt_list_out, r->edns.opt_list_out) == 0 && 1562 edns_opt_list_compare(prev->edns.opt_list_inplace_cb_out, r->edns.opt_list_inplace_cb_out) == 0 1563 ) { 1564 /* if the previous reply is identical to this one, fix ID */ 1565 if(prev_buffer != r_buffer) 1566 sldns_buffer_copy(r_buffer, prev_buffer); 1567 sldns_buffer_write_at(r_buffer, 0, &r->qid, sizeof(uint16_t)); 1568 sldns_buffer_write_at(r_buffer, 12, r->qname, 1569 m->s.qinfo.qname_len); 1570 comm_point_send_reply(&r->query_reply); 1571 } else if(rcode) { 1572 m->s.qinfo.qname = r->qname; 1573 m->s.qinfo.local_alias = r->local_alias; 1574 if(rcode == LDNS_RCODE_SERVFAIL) { 1575 if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 1576 rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time)) 1577 r->edns.opt_list_inplace_cb_out = NULL; 1578 } else { 1579 if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, 1580 &r->edns, &r->query_reply, m->s.region, &r->start_time)) 1581 r->edns.opt_list_inplace_cb_out = NULL; 1582 } 1583 /* Send along EDE EDNS0 option when SERVFAILing; usually 1584 * DNSSEC validation failures */ 1585 /* Since we are SERVFAILing here, CD bit and rep->security 1586 * is already handled. */ 1587 if(m->s.env->cfg->ede && rep) { 1588 mesh_find_and_attach_ede_and_reason(m, rep, r); 1589 } 1590 error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, 1591 r->qflags, &r->edns); 1592 comm_point_send_reply(&r->query_reply); 1593 } else { 1594 size_t udp_size = r->edns.udp_size; 1595 r->edns.edns_version = EDNS_ADVERTISED_VERSION; 1596 r->edns.udp_size = EDNS_ADVERTISED_SIZE; 1597 r->edns.ext_rcode = 0; 1598 r->edns.bits &= EDNS_DO; 1599 if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) 1600 r->edns.edns_present = 0; 1601 m->s.qinfo.qname = r->qname; 1602 m->s.qinfo.local_alias = r->local_alias; 1603 1604 /* Attach EDE without SERVFAIL if the validation failed. 1605 * Need to explicitly check for rep->security otherwise failed 1606 * validation paths may attach to a secure answer. */ 1607 if(m->s.env->cfg->ede && rep && 1608 (rep->security <= sec_status_bogus || 1609 rep->security == sec_status_secure_sentinel_fail)) { 1610 mesh_find_and_attach_ede_and_reason(m, rep, r); 1611 } 1612 1613 if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, 1614 LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) || 1615 !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 1616 r->qflags, r_buffer, 0, 1, m->s.env->scratch, 1617 udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO), 1618 secure)) 1619 { 1620 if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, 1621 rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time)) 1622 r->edns.opt_list_inplace_cb_out = NULL; 1623 /* internal server error (probably malloc failure) so no 1624 * EDE (RFC8914) needed */ 1625 error_encode(r_buffer, LDNS_RCODE_SERVFAIL, 1626 &m->s.qinfo, r->qid, r->qflags, &r->edns); 1627 } 1628 comm_point_send_reply(&r->query_reply); 1629 } 1630 infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply, 1631 m->s.env->cfg); 1632 /* account */ 1633 log_assert(m->s.env->mesh->num_reply_addrs > 0); 1634 m->s.env->mesh->num_reply_addrs--; 1635 end_time = *m->s.env->now_tv; 1636 timeval_subtract(&duration, &end_time, &r->start_time); 1637 verbose(VERB_ALGO, "query took " ARG_LL "d.%6.6d sec", 1638 (long long)duration.tv_sec, (int)duration.tv_usec); 1639 m->s.env->mesh->replies_sent++; 1640 timeval_add(&m->s.env->mesh->replies_sum_wait, &duration); 1641 timehist_insert(m->s.env->mesh->histogram, &duration); 1642 if(m->s.env->cfg->stat_extended) { 1643 uint16_t rc = FLAGS_GET_RCODE(sldns_buffer_read_u16_at( 1644 r_buffer, 2)); 1645 if(secure) m->s.env->mesh->ans_secure++; 1646 m->s.env->mesh->ans_rcode[ rc ] ++; 1647 if(rc == 0 && LDNS_ANCOUNT(sldns_buffer_begin(r_buffer)) == 0) 1648 m->s.env->mesh->ans_nodata++; 1649 } 1650 /* Log reply sent */ 1651 if(m->s.env->cfg->log_replies) { 1652 log_reply_info(NO_VERBOSE, &m->s.qinfo, 1653 &r->query_reply.client_addr, 1654 r->query_reply.client_addrlen, duration, 0, r_buffer, 1655 (m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL), 1656 r->query_reply.c->type, r->query_reply.c->ssl); 1657 } 1658 } 1659 1660 /** 1661 * Generate the DNS Error Report (RFC9567). 1662 * If there is an EDE attached for this reply and there was a Report-Channel 1663 * EDNS0 option from the upstream, fire up a report query. 1664 * @param qstate: module qstate. 1665 * @param rep: prepared reply to be sent. 1666 */ 1667 static void dns_error_reporting(struct module_qstate* qstate, 1668 struct reply_info* rep) 1669 { 1670 struct query_info qinfo; 1671 struct mesh_state* sub; 1672 struct module_qstate* newq; 1673 uint8_t buf[LDNS_MAX_DOMAINLEN]; 1674 size_t count = 0; 1675 int written; 1676 size_t expected_length; 1677 struct edns_option* opt; 1678 sldns_ede_code reason_bogus = LDNS_EDE_NONE; 1679 sldns_rr_type qtype = qstate->qinfo.qtype; 1680 uint8_t* qname = qstate->qinfo.qname; 1681 size_t qname_len = qstate->qinfo.qname_len-1; /* skip the trailing \0 */ 1682 uint8_t* agent_domain; 1683 size_t agent_domain_len; 1684 1685 /* We need a valid reporting agent; 1686 * this is based on qstate->edns_opts_back_in that will probably have 1687 * the latest reporting agent we found while iterating */ 1688 opt = edns_opt_list_find(qstate->edns_opts_back_in, 1689 LDNS_EDNS_REPORT_CHANNEL); 1690 if(!opt) return; 1691 agent_domain = opt->opt_data; 1692 agent_domain_len = dname_valid(agent_domain, opt->opt_len); 1693 if(agent_domain_len < 3) { 1694 /* The agent domain needs to be a valid dname that is not the 1695 * root; from RFC9567. */ 1696 return; 1697 } 1698 1699 /* Get the EDE generated from the mesh state, these are mostly 1700 * validator errors. If other errors are produced in the future (e.g., 1701 * RPZ) we would not want them to result in error reports. */ 1702 reason_bogus = errinf_to_reason_bogus(qstate); 1703 if(rep && ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS && 1704 rep->reason_bogus != LDNS_EDE_NONE) || 1705 reason_bogus == LDNS_EDE_NONE)) { 1706 reason_bogus = rep->reason_bogus; 1707 } 1708 if(reason_bogus == LDNS_EDE_NONE || 1709 /* other, does not make sense without the text that comes 1710 * with it */ 1711 reason_bogus == LDNS_EDE_OTHER) return; 1712 1713 /* Synthesize the error report query in the format: 1714 * "_er.$qtype.$qname.$ede._er.$reporting-agent-domain" */ 1715 /* First check if the static length parts fit in the buffer. 1716 * That is everything except for qtype and ede that need to be 1717 * converted to decimal and checked further on. */ 1718 expected_length = 4/*_er*/+qname_len+4/*_er*/+agent_domain_len; 1719 if(expected_length > LDNS_MAX_DOMAINLEN) goto skip; 1720 1721 memmove(buf+count, "\3_er", 4); 1722 count += 4; 1723 1724 written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count, 1725 "X%d", qtype); 1726 expected_length += written; 1727 /* Skip on error, truncation or long expected length */ 1728 if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count || 1729 expected_length > LDNS_MAX_DOMAINLEN ) goto skip; 1730 /* Put in the label length */ 1731 *(buf+count) = (char)(written - 1); 1732 count += written; 1733 1734 memmove(buf+count, qname, qname_len); 1735 count += qname_len; 1736 1737 written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count, 1738 "X%d", reason_bogus); 1739 expected_length += written; 1740 /* Skip on error, truncation or long expected length */ 1741 if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count || 1742 expected_length > LDNS_MAX_DOMAINLEN ) goto skip; 1743 *(buf+count) = (char)(written - 1); 1744 count += written; 1745 1746 memmove(buf+count, "\3_er", 4); 1747 count += 4; 1748 1749 /* Copy the agent domain */ 1750 memmove(buf+count, agent_domain, agent_domain_len); 1751 count += agent_domain_len; 1752 1753 qinfo.qname = buf; 1754 qinfo.qname_len = count; 1755 qinfo.qtype = LDNS_RR_TYPE_TXT; 1756 qinfo.qclass = qstate->qinfo.qclass; 1757 qinfo.local_alias = NULL; 1758 1759 log_query_info(VERB_ALGO, "DNS Error Reporting: generating report " 1760 "query for", &qinfo); 1761 if(mesh_add_sub(qstate, &qinfo, NULL, BIT_RD, 0, 0, &newq, &sub)) { 1762 qstate->env->mesh->num_dns_error_reports++; 1763 } 1764 return; 1765 skip: 1766 verbose(VERB_ALGO, "DNS Error Reporting: report query qname too long; " 1767 "skip"); 1768 return; 1769 } 1770 1771 void mesh_query_done(struct mesh_state* mstate) 1772 { 1773 struct mesh_reply* r; 1774 struct mesh_reply* prev = NULL; 1775 struct sldns_buffer* prev_buffer = NULL; 1776 struct mesh_cb* c; 1777 struct reply_info* rep = (mstate->s.return_msg? 1778 mstate->s.return_msg->rep:NULL); 1779 struct timeval tv = {0, 0}; 1780 struct mesh_area* mesh = mstate->s.env->mesh; 1781 int i = 0; 1782 /* No need for the serve expired timer anymore; we are going to reply. */ 1783 if(mstate->s.serve_expired_data) { 1784 comm_timer_delete(mstate->s.serve_expired_data->timer); 1785 mstate->s.serve_expired_data->timer = NULL; 1786 } 1787 if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL || 1788 (rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) { 1789 if(mstate->s.env->cfg->serve_expired) { 1790 /* we are SERVFAILing; check for expired answer here */ 1791 mesh_respond_serve_expired(mstate); 1792 } 1793 if((mstate->reply_list || mstate->cb_list) 1794 && mstate->s.env->cfg->log_servfail 1795 && !mstate->s.env->cfg->val_log_squelch) { 1796 char* err = errinf_to_str_servfail(&mstate->s); 1797 if(err) { log_err("%s", err); } 1798 } 1799 } 1800 1801 if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting 1802 && (!rep || rep->security != sec_status_secure)) 1803 dns_error_reporting(&mstate->s, rep); 1804 1805 while((r = mesh_reply_list_pop_first(mstate)) != NULL) { 1806 1807 /* it was not detached (because it had a reply list), could be now */ 1808 if(!mstate->reply_list && !mstate->cb_list 1809 && mstate->super_set.count == 0) { 1810 mesh->num_detached_states++; 1811 } 1812 /* if not replies any more in mstate, it is no longer a reply_state */ 1813 if(!mstate->reply_list && !mstate->cb_list) { 1814 log_assert(mesh->num_reply_states > 0); 1815 mesh->num_reply_states--; 1816 } 1817 if(mesh_is_udp(r)) { 1818 /* For UDP queries, the old replies are discarded. 1819 * This stops a large volume of old replies from 1820 * building up. 1821 * The stream replies, are not discarded. The 1822 * stream is open, the other side is waiting. 1823 * Some answer is needed, even if servfail, but the 1824 * real reply is ready to go, so that is given. */ 1825 struct timeval old; 1826 timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time); 1827 if(mstate->s.env->cfg->discard_timeout != 0 && 1828 ((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 > 1829 mstate->s.env->cfg->discard_timeout) { 1830 /* Drop the reply, it is too old */ 1831 verbose(VERB_ALGO, "drop reply, it is older than discard-timeout"); 1832 infra_wait_limit_dec(mstate->s.env->infra_cache, 1833 &r->query_reply, mstate->s.env->cfg); 1834 if(r->query_reply.c->tcp_req_info) 1835 tcp_req_info_remove_mesh_state( 1836 r->query_reply.c->tcp_req_info, 1837 mstate); 1838 else if(r->query_reply.c->use_h2) 1839 http2_stream_remove_mesh_state(r->h2_stream); 1840 else if(r->query_reply.doq_stream) 1841 doq_stream_remove_mesh_state(r->query_reply.doq_stream); 1842 comm_point_drop_reply(&r->query_reply); 1843 log_assert(mstate->s.env->mesh->num_reply_addrs > 0); 1844 mstate->s.env->mesh->num_reply_addrs--; 1845 mstate->s.env->mesh->num_queries_discard_timeout++; 1846 continue; 1847 } 1848 } 1849 1850 i++; 1851 tv = r->start_time; 1852 1853 /* if a response-ip address block has been stored the 1854 * information should be logged for each client. */ 1855 if(mstate->s.respip_action_info && 1856 mstate->s.respip_action_info->addrinfo) { 1857 respip_inform_print(mstate->s.respip_action_info, 1858 r->qname, mstate->s.qinfo.qtype, 1859 mstate->s.qinfo.qclass, r->local_alias, 1860 &r->query_reply.client_addr, 1861 r->query_reply.client_addrlen); 1862 } 1863 1864 /* if this query is determined to be dropped during the 1865 * mesh processing, this is the point to take that action. */ 1866 if(mstate->s.is_drop) { 1867 infra_wait_limit_dec(mstate->s.env->infra_cache, 1868 &r->query_reply, mstate->s.env->cfg); 1869 if(r->query_reply.c->tcp_req_info) { 1870 tcp_req_info_remove_mesh_state( 1871 r->query_reply.c->tcp_req_info, mstate); 1872 } else if(r->query_reply.c->use_h2) { 1873 http2_stream_remove_mesh_state(r->h2_stream); 1874 } else if(r->query_reply.doq_stream) { 1875 doq_stream_remove_mesh_state(r->query_reply.doq_stream); 1876 } 1877 comm_point_drop_reply(&r->query_reply); 1878 log_assert(mstate->s.env->mesh->num_reply_addrs > 0); 1879 mstate->s.env->mesh->num_reply_addrs--; 1880 } else { 1881 struct sldns_buffer* r_buffer = r->query_reply.c->buffer; 1882 if(r->query_reply.c->tcp_req_info) { 1883 r_buffer = r->query_reply.c->tcp_req_info->spool_buffer; 1884 prev_buffer = NULL; 1885 } 1886 mesh_send_reply(mstate, mstate->s.return_rcode, rep, 1887 r, r_buffer, prev, prev_buffer); 1888 if(r->query_reply.c->tcp_req_info) { 1889 tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate); 1890 r_buffer = NULL; 1891 } 1892 /* mesh_send_reply removed mesh state from 1893 * http2_stream. */ 1894 prev = r; 1895 prev_buffer = r_buffer; 1896 } 1897 } 1898 /* Account for each reply sent. */ 1899 if(i > 0 && mstate->s.respip_action_info && 1900 mstate->s.respip_action_info->addrinfo && 1901 mstate->s.env->cfg->stat_extended && 1902 mstate->s.respip_action_info->rpz_used) { 1903 if(mstate->s.respip_action_info->rpz_disabled) 1904 mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i; 1905 if(mstate->s.respip_action_info->rpz_cname_override) 1906 mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i; 1907 else 1908 mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action( 1909 mstate->s.respip_action_info->action)] += i; 1910 } 1911 if(!mstate->s.is_drop && i > 0) { 1912 if(mstate->s.env->cfg->stat_extended 1913 && mstate->s.is_cachedb_answer) { 1914 mstate->s.env->mesh->ans_cachedb += i; 1915 } 1916 } 1917 1918 mstate->replies_sent = 1; 1919 1920 while((c = mstate->cb_list) != NULL) { 1921 /* take this cb off the list; so that the list can be 1922 * changed, eg. by adds from the callback routine */ 1923 if(!mstate->reply_list && mstate->cb_list && !c->next) { 1924 /* was a reply state, not anymore */ 1925 log_assert(mstate->s.env->mesh->num_reply_states > 0); 1926 mstate->s.env->mesh->num_reply_states--; 1927 } 1928 mstate->cb_list = c->next; 1929 if(!mstate->reply_list && !mstate->cb_list && 1930 mstate->super_set.count == 0) 1931 mstate->s.env->mesh->num_detached_states++; 1932 mesh_do_callback(mstate, mstate->s.return_rcode, rep, c, &tv); 1933 } 1934 } 1935 1936 void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate) 1937 { 1938 struct mesh_state_ref* ref; 1939 RBTREE_FOR(ref, struct mesh_state_ref*, &mstate->super_set) 1940 { 1941 /* make super runnable */ 1942 (void)rbtree_insert(&mesh->run, &ref->s->run_node); 1943 /* callback the function to inform super of result */ 1944 fptr_ok(fptr_whitelist_mod_inform_super( 1945 mesh->mods.mod[ref->s->s.curmod]->inform_super)); 1946 (*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s, 1947 ref->s->s.curmod, &ref->s->s); 1948 /* copy state that is always relevant to super */ 1949 copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s); 1950 } 1951 } 1952 1953 struct mesh_state* mesh_area_find(struct mesh_area* mesh, 1954 struct respip_client_info* cinfo, struct query_info* qinfo, 1955 uint16_t qflags, int prime, int valrec) 1956 { 1957 struct mesh_state key; 1958 struct mesh_state* result; 1959 1960 key.node.key = &key; 1961 key.s.is_priming = prime; 1962 key.s.is_valrec = valrec; 1963 key.s.qinfo = *qinfo; 1964 key.s.query_flags = qflags; 1965 /* We are searching for a similar mesh state when we DO want to 1966 * aggregate the state. Thus unique is set to NULL. (default when we 1967 * desire aggregation).*/ 1968 key.unique = NULL; 1969 key.s.client_info = cinfo; 1970 1971 result = (struct mesh_state*)rbtree_search(&mesh->all, &key); 1972 return result; 1973 } 1974 1975 struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh, 1976 struct respip_client_info* cinfo, struct query_info* qinfo, 1977 uint16_t qflags, int prime, int valrec, void* unique_info) 1978 { 1979 struct mesh_state key; 1980 struct mesh_state* result; 1981 1982 key.node.key = &key; 1983 key.s.is_priming = prime; 1984 key.s.is_valrec = valrec; 1985 key.s.qinfo = *qinfo; 1986 key.s.query_flags = qflags; 1987 key.unique = (struct mesh_state*)unique_info; 1988 key.s.client_info = cinfo; 1989 1990 result = (struct mesh_state*)rbtree_search(&mesh->all, &key); 1991 return result; 1992 } 1993 1994 /** remove mesh state callback */ 1995 int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg) 1996 { 1997 struct mesh_cb* r, *prev = NULL; 1998 r = s->cb_list; 1999 while(r) { 2000 if(r->cb == cb && r->cb_arg == cb_arg) { 2001 /* Delete this entry. */ 2002 /* It was allocated in the s.region, so no free. */ 2003 if(prev) prev->next = r->next; 2004 else s->cb_list = r->next; 2005 return 1; 2006 } 2007 prev = r; 2008 r = r->next; 2009 } 2010 return 0; 2011 } 2012 2013 int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, 2014 sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg, 2015 uint16_t qid, uint16_t qflags, struct mesh_cb** result) 2016 { 2017 struct mesh_cb* r = regional_alloc(s->s.region, 2018 sizeof(struct mesh_cb)); 2019 if(!r) 2020 return 0; 2021 r->buf = buf; 2022 log_assert(fptr_whitelist_mesh_cb(cb)); /* early failure ifmissing*/ 2023 r->cb = cb; 2024 r->cb_arg = cb_arg; 2025 r->edns = *edns; 2026 if(edns->opt_list_in && !(r->edns.opt_list_in = 2027 edns_opt_copy_region(edns->opt_list_in, s->s.region))) 2028 return 0; 2029 if(edns->opt_list_out && !(r->edns.opt_list_out = 2030 edns_opt_copy_region(edns->opt_list_out, s->s.region))) 2031 return 0; 2032 if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = 2033 edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) 2034 return 0; 2035 r->qid = qid; 2036 r->qflags = qflags; 2037 r->next = s->cb_list; 2038 s->cb_list = r; 2039 *result = r; 2040 return 1; 2041 2042 } 2043 2044 int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, 2045 struct comm_reply* rep, uint16_t qid, uint16_t qflags, 2046 const struct query_info* qinfo, struct mesh_reply** result) 2047 { 2048 struct mesh_reply* r = regional_alloc(s->s.region, 2049 sizeof(struct mesh_reply)); 2050 if(!r) 2051 return 0; 2052 r->query_reply = *rep; 2053 r->edns = *edns; 2054 if(edns->opt_list_in && !(r->edns.opt_list_in = 2055 edns_opt_copy_region(edns->opt_list_in, s->s.region))) 2056 return 0; 2057 if(edns->opt_list_out && !(r->edns.opt_list_out = 2058 edns_opt_copy_region(edns->opt_list_out, s->s.region))) 2059 return 0; 2060 if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = 2061 edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) 2062 return 0; 2063 r->qid = qid; 2064 r->qflags = qflags; 2065 r->start_time = *s->s.env->now_tv; 2066 if(s->reply_list == NULL && !s->has_first_reply_time) { 2067 s->first_reply_time = r->start_time; 2068 s->has_first_reply_time = 1; 2069 } 2070 r->next = s->reply_list; 2071 r->qname = regional_alloc_init(s->s.region, qinfo->qname, 2072 s->s.qinfo.qname_len); 2073 if(!r->qname) 2074 return 0; 2075 if(rep->c->use_h2) 2076 r->h2_stream = rep->c->h2_stream; 2077 else r->h2_stream = NULL; 2078 if(rep->c->type != comm_doq) 2079 r->query_reply.doq_stream = NULL; 2080 2081 /* Data related to local alias stored in 'qinfo' (if any) is ephemeral 2082 * and can be different for different original queries (even if the 2083 * replaced query name is the same). So we need to make a deep copy 2084 * and store the copy for each reply info. */ 2085 if(qinfo->local_alias) { 2086 struct packed_rrset_data* d; 2087 struct packed_rrset_data* dsrc; 2088 r->local_alias = regional_alloc_zero(s->s.region, 2089 sizeof(*qinfo->local_alias)); 2090 if(!r->local_alias) 2091 return 0; 2092 r->local_alias->rrset = regional_alloc_init(s->s.region, 2093 qinfo->local_alias->rrset, 2094 sizeof(*qinfo->local_alias->rrset)); 2095 if(!r->local_alias->rrset) 2096 return 0; 2097 dsrc = qinfo->local_alias->rrset->entry.data; 2098 2099 /* In the current implementation, a local alias must be 2100 * a single CNAME RR (see worker_handle_request()). */ 2101 log_assert(!qinfo->local_alias->next && dsrc->count == 1 && 2102 qinfo->local_alias->rrset->rk.type == 2103 htons(LDNS_RR_TYPE_CNAME)); 2104 /* we should make a local copy for the owner name of 2105 * the RRset */ 2106 r->local_alias->rrset->rk.dname_len = 2107 qinfo->local_alias->rrset->rk.dname_len; 2108 r->local_alias->rrset->rk.dname = regional_alloc_init( 2109 s->s.region, qinfo->local_alias->rrset->rk.dname, 2110 qinfo->local_alias->rrset->rk.dname_len); 2111 if(!r->local_alias->rrset->rk.dname) 2112 return 0; 2113 2114 /* the rrset is not packed, like in the cache, but it is 2115 * individually allocated with an allocator from localzone. */ 2116 d = regional_alloc_zero(s->s.region, sizeof(*d)); 2117 if(!d) 2118 return 0; 2119 r->local_alias->rrset->entry.data = d; 2120 if(!rrset_insert_rr(s->s.region, d, dsrc->rr_data[0], 2121 dsrc->rr_len[0], dsrc->rr_ttl[0], "CNAME local alias")) 2122 return 0; 2123 } else 2124 r->local_alias = NULL; 2125 2126 s->reply_list = r; 2127 *result = r; 2128 return 1; 2129 } 2130 2131 /* Extract the query info and flags from 'mstate' into '*qinfop' and '*qflags'. 2132 * Since this is only used for internal refetch of otherwise-expired answer, 2133 * we simply ignore the rare failure mode when memory allocation fails. */ 2134 static void 2135 mesh_copy_qinfo(struct mesh_state* mstate, struct query_info** qinfop, 2136 uint16_t* qflags) 2137 { 2138 struct regional* region = mstate->s.env->scratch; 2139 struct query_info* qinfo; 2140 2141 qinfo = regional_alloc_init(region, &mstate->s.qinfo, sizeof(*qinfo)); 2142 if(!qinfo) 2143 return; 2144 qinfo->qname = regional_alloc_init(region, qinfo->qname, 2145 qinfo->qname_len); 2146 if(!qinfo->qname) 2147 return; 2148 *qinfop = qinfo; 2149 *qflags = mstate->s.query_flags; 2150 } 2151 2152 /** 2153 * Continue processing the mesh state at another module. 2154 * Handles module to modules transfer of control. 2155 * Handles module finished. 2156 * @param mesh: the mesh area. 2157 * @param mstate: currently active mesh state. 2158 * Deleted if finished, calls _done and _supers to 2159 * send replies to clients and inform other mesh states. 2160 * This in turn may create additional runnable mesh states. 2161 * @param s: state at which the current module exited. 2162 * @param ev: the event sent to the module. 2163 * returned is the event to send to the next module. 2164 * @return true if continue processing at the new module. 2165 * false if not continued processing is needed. 2166 */ 2167 static int 2168 mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate, 2169 enum module_ext_state s, enum module_ev* ev) 2170 { 2171 mstate->num_activated++; 2172 if(mstate->num_activated > MESH_MAX_ACTIVATION) { 2173 /* module is looping. Stop it. */ 2174 log_err("internal error: looping module (%s) stopped", 2175 mesh->mods.mod[mstate->s.curmod]->name); 2176 log_query_info(NO_VERBOSE, "pass error for qstate", 2177 &mstate->s.qinfo); 2178 s = module_error; 2179 } 2180 if(s == module_wait_module || s == module_restart_next) { 2181 /* start next module */ 2182 mstate->s.curmod++; 2183 if(mesh->mods.num == mstate->s.curmod) { 2184 log_err("Cannot pass to next module; at last module"); 2185 log_query_info(VERB_QUERY, "pass error for qstate", 2186 &mstate->s.qinfo); 2187 mstate->s.curmod--; 2188 return mesh_continue(mesh, mstate, module_error, ev); 2189 } 2190 if(s == module_restart_next) { 2191 int curmod = mstate->s.curmod; 2192 for(; mstate->s.curmod < mesh->mods.num; 2193 mstate->s.curmod++) { 2194 fptr_ok(fptr_whitelist_mod_clear( 2195 mesh->mods.mod[mstate->s.curmod]->clear)); 2196 (*mesh->mods.mod[mstate->s.curmod]->clear) 2197 (&mstate->s, mstate->s.curmod); 2198 mstate->s.minfo[mstate->s.curmod] = NULL; 2199 } 2200 mstate->s.curmod = curmod; 2201 } 2202 *ev = module_event_pass; 2203 return 1; 2204 } 2205 if(s == module_wait_subquery && mstate->sub_set.count == 0) { 2206 log_err("module cannot wait for subquery, subquery list empty"); 2207 log_query_info(VERB_QUERY, "pass error for qstate", 2208 &mstate->s.qinfo); 2209 s = module_error; 2210 } 2211 if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) { 2212 /* error is bad, handle pass back up below */ 2213 mstate->s.return_rcode = LDNS_RCODE_SERVFAIL; 2214 } 2215 if(s == module_error) { 2216 mesh_query_done(mstate); 2217 mesh_walk_supers(mesh, mstate); 2218 mesh_state_delete(&mstate->s); 2219 return 0; 2220 } 2221 if(s == module_finished) { 2222 if(mstate->s.curmod == 0) { 2223 struct query_info* qinfo = NULL; 2224 struct edns_option* opt_list = NULL; 2225 struct sockaddr_storage addr; 2226 uint16_t qflags; 2227 int rpz_p = 0; 2228 2229 #ifdef CLIENT_SUBNET 2230 struct edns_option* ecs; 2231 if(mstate->s.need_refetch && mstate->reply_list && 2232 modstack_find(&mesh->mods, "subnetcache") != -1 && 2233 mstate->s.env->unique_mesh) { 2234 addr = mstate->reply_list->query_reply.client_addr; 2235 } else 2236 #endif 2237 memset(&addr, 0, sizeof(addr)); 2238 2239 mesh_query_done(mstate); 2240 mesh_walk_supers(mesh, mstate); 2241 2242 /* If the answer to the query needs to be refetched 2243 * from an external DNS server, we'll need to schedule 2244 * a prefetch after removing the current state, so 2245 * we need to make a copy of the query info here. */ 2246 if(mstate->s.need_refetch) { 2247 mesh_copy_qinfo(mstate, &qinfo, &qflags); 2248 #ifdef CLIENT_SUBNET 2249 /* Make also a copy of the ecs option if any */ 2250 if((ecs = edns_opt_list_find( 2251 mstate->s.edns_opts_front_in, 2252 mstate->s.env->cfg->client_subnet_opcode)) != NULL) { 2253 (void)edns_opt_list_append(&opt_list, 2254 ecs->opt_code, ecs->opt_len, 2255 ecs->opt_data, 2256 mstate->s.env->scratch); 2257 } 2258 #endif 2259 rpz_p = mstate->s.rpz_passthru; 2260 } 2261 2262 if(qinfo) { 2263 mesh_state_delete(&mstate->s); 2264 mesh_new_prefetch(mesh, qinfo, qflags, 0, 2265 rpz_p, 2266 addr.ss_family!=AF_UNSPEC?&addr:NULL, 2267 opt_list); 2268 } else { 2269 mesh_state_delete(&mstate->s); 2270 } 2271 return 0; 2272 } 2273 /* pass along the locus of control */ 2274 mstate->s.curmod --; 2275 *ev = module_event_moddone; 2276 return 1; 2277 } 2278 return 0; 2279 } 2280 2281 void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate, 2282 enum module_ev ev, struct outbound_entry* e) 2283 { 2284 enum module_ext_state s; 2285 int numrun = 0; 2286 verbose(VERB_ALGO, "mesh_run: start"); 2287 while(mstate) { 2288 if(numrun++ > MESH_MAX_RUN_ITER) { 2289 /* These modules are too much to activate, stop them.*/ 2290 log_err("Too many module run iterations, deleting"); 2291 while(mstate) { 2292 /* notify supers */ 2293 if(mstate->super_set.count > 0) { 2294 verbose(VERB_ALGO, "notify supers of failure"); 2295 mstate->s.return_msg = NULL; 2296 mstate->s.return_rcode = LDNS_RCODE_SERVFAIL; 2297 mesh_walk_supers(mesh, mstate); 2298 } 2299 mesh_state_delete(&mstate->s); 2300 if(mesh->run.count > 0) { 2301 /* pop random element off the runnable tree */ 2302 mstate = (struct mesh_state*)mesh->run.root->key; 2303 (void)rbtree_delete(&mesh->run, mstate); 2304 } else mstate = NULL; 2305 } 2306 break; 2307 } 2308 /* run the module */ 2309 fptr_ok(fptr_whitelist_mod_operate( 2310 mesh->mods.mod[mstate->s.curmod]->operate)); 2311 (*mesh->mods.mod[mstate->s.curmod]->operate) 2312 (&mstate->s, ev, mstate->s.curmod, e); 2313 2314 /* examine results */ 2315 mstate->s.reply = NULL; 2316 regional_free_all(mstate->s.env->scratch); 2317 s = mstate->s.ext_state[mstate->s.curmod]; 2318 verbose(VERB_ALGO, "mesh_run: %s module exit state is %s", 2319 mesh->mods.mod[mstate->s.curmod]->name, strextstate(s)); 2320 e = NULL; 2321 if(mesh_continue(mesh, mstate, s, &ev)) 2322 continue; 2323 2324 /* run more modules */ 2325 ev = module_event_pass; 2326 if(mesh->run.count > 0) { 2327 /* pop random element off the runnable tree */ 2328 mstate = (struct mesh_state*)mesh->run.root->key; 2329 (void)rbtree_delete(&mesh->run, mstate); 2330 } else mstate = NULL; 2331 } 2332 if(verbosity >= VERB_ALGO) { 2333 mesh_stats(mesh, "mesh_run: end"); 2334 mesh_log_list(mesh); 2335 } 2336 } 2337 2338 void 2339 mesh_log_list(struct mesh_area* mesh) 2340 { 2341 char buf[30]; 2342 struct mesh_state* m; 2343 int num = 0; 2344 RBTREE_FOR(m, struct mesh_state*, &mesh->all) { 2345 snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s", 2346 num++, (m->s.is_priming)?"p":"", /* prime */ 2347 (m->s.is_valrec)?"v":"", /* prime */ 2348 (m->s.query_flags&BIT_RD)?"RD":"", 2349 (m->s.query_flags&BIT_CD)?"CD":"", 2350 (m->super_set.count==0)?"d":"", /* detached */ 2351 (m->sub_set.count!=0)?"c":"", /* children */ 2352 m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/ 2353 (m->cb_list)?"cb":"" /* callbacks */ 2354 ); 2355 log_query_info(VERB_ALGO, buf, &m->s.qinfo); 2356 } 2357 } 2358 2359 void 2360 mesh_stats(struct mesh_area* mesh, const char* str) 2361 { 2362 verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, " 2363 "%u detached), %u waiting replies, %u recursion replies " 2364 "sent, %d replies dropped, %d states jostled out", 2365 str, (unsigned)mesh->all.count, 2366 (unsigned)mesh->num_reply_states, 2367 (unsigned)mesh->num_detached_states, 2368 (unsigned)mesh->num_reply_addrs, 2369 (unsigned)mesh->replies_sent, 2370 (unsigned)mesh->stats_dropped, 2371 (unsigned)mesh->stats_jostled); 2372 if(mesh->replies_sent > 0) { 2373 struct timeval avg; 2374 timeval_divide(&avg, &mesh->replies_sum_wait, 2375 mesh->replies_sent); 2376 log_info("average recursion processing time " 2377 ARG_LL "d.%6.6d sec", 2378 (long long)avg.tv_sec, (int)avg.tv_usec); 2379 log_info("histogram of recursion processing times"); 2380 timehist_log(mesh->histogram, "recursions"); 2381 } 2382 } 2383 2384 void 2385 mesh_stats_clear(struct mesh_area* mesh) 2386 { 2387 if(!mesh) 2388 return; 2389 mesh->num_query_authzone_up = 0; 2390 mesh->num_query_authzone_down = 0; 2391 mesh->replies_sent = 0; 2392 mesh->replies_sum_wait.tv_sec = 0; 2393 mesh->replies_sum_wait.tv_usec = 0; 2394 mesh->stats_jostled = 0; 2395 mesh->stats_dropped = 0; 2396 timehist_clear(mesh->histogram); 2397 mesh->ans_secure = 0; 2398 mesh->ans_bogus = 0; 2399 mesh->val_ops = 0; 2400 mesh->ans_expired = 0; 2401 mesh->ans_cachedb = 0; 2402 memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM); 2403 memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM); 2404 mesh->ans_nodata = 0; 2405 mesh->num_queries_discard_timeout = 0; 2406 mesh->num_queries_replyaddr_limit = 0; 2407 mesh->num_queries_wait_limit = 0; 2408 mesh->num_dns_error_reports = 0; 2409 } 2410 2411 size_t 2412 mesh_get_mem(struct mesh_area* mesh) 2413 { 2414 struct mesh_state* m; 2415 size_t s = sizeof(*mesh) + sizeof(struct timehist) + 2416 sizeof(struct th_buck)*mesh->histogram->num + 2417 sizeof(sldns_buffer) + sldns_buffer_capacity(mesh->qbuf_bak); 2418 RBTREE_FOR(m, struct mesh_state*, &mesh->all) { 2419 /* all, including m itself allocated in qstate region */ 2420 s += regional_get_mem(m->s.region); 2421 } 2422 return s; 2423 } 2424 2425 int 2426 mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, 2427 uint16_t flags, int prime, int valrec) 2428 { 2429 struct mesh_area* mesh = qstate->env->mesh; 2430 struct mesh_state* dep_m = NULL; 2431 dep_m = mesh_area_find(mesh, NULL, qinfo, flags, prime, valrec); 2432 return dep_m?mesh_detect_cycle_found(qstate, dep_m):0; 2433 } 2434 2435 void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, 2436 struct mesh_state** lp) 2437 { 2438 /* insert as last element */ 2439 m->prev = *lp; 2440 m->next = NULL; 2441 if(*lp) 2442 (*lp)->next = m; 2443 else *fp = m; 2444 *lp = m; 2445 } 2446 2447 void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp, 2448 struct mesh_state** lp) 2449 { 2450 if(m->next) 2451 m->next->prev = m->prev; 2452 else *lp = m->prev; 2453 if(m->prev) 2454 m->prev->next = m->next; 2455 else *fp = m->next; 2456 } 2457 2458 void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m, 2459 struct comm_point* cp, struct http2_stream* h2_stream, 2460 struct doq_stream* doq_stream) 2461 { 2462 struct mesh_reply* n, *prev = NULL; 2463 n = m->reply_list; 2464 /* when in mesh_cleanup, it sets the reply_list to NULL, so that 2465 * there is no accounting twice */ 2466 if(!n) return; /* nothing to remove, also no accounting needed */ 2467 while(n) { 2468 if(n->query_reply.c == cp 2469 && (!h2_stream || n->h2_stream == h2_stream) 2470 && (!doq_stream || n->query_reply.doq_stream == doq_stream)) { 2471 /* unlink it */ 2472 if(prev) prev->next = n->next; 2473 else m->reply_list = n->next; 2474 /* delete it, but allocated in m region */ 2475 log_assert(mesh->num_reply_addrs > 0); 2476 mesh->num_reply_addrs--; 2477 infra_wait_limit_dec(mesh->env->infra_cache, 2478 &n->query_reply, mesh->env->cfg); 2479 /* We may be removing more than one http2 stream (they 2480 * share the same comm_point); make sure the streams 2481 * don't point back. */ 2482 if(n->h2_stream) n->h2_stream->mesh_state = NULL; 2483 #ifdef HAVE_NGTCP2 2484 if(n->query_reply.doq_stream) 2485 n->query_reply.doq_stream->mesh_state = NULL; 2486 #endif 2487 2488 /* prev = prev; */ 2489 n = n->next; 2490 continue; 2491 } 2492 prev = n; 2493 n = n->next; 2494 } 2495 /* it was not detached (because it had a reply list), could be now */ 2496 if(!m->reply_list && !m->cb_list 2497 && m->super_set.count == 0) { 2498 mesh->num_detached_states++; 2499 } 2500 /* if not replies any more in mstate, it is no longer a reply_state */ 2501 if(!m->reply_list && !m->cb_list) { 2502 log_assert(mesh->num_reply_states > 0); 2503 mesh->num_reply_states--; 2504 } 2505 } 2506 2507 static int 2508 apply_respip_action(struct module_qstate* qstate, 2509 const struct query_info* qinfo, struct respip_client_info* cinfo, 2510 struct respip_action_info* actinfo, struct reply_info* rep, 2511 struct ub_packed_rrset_key** alias_rrset, 2512 struct reply_info** encode_repp, struct auth_zones* az) 2513 { 2514 if(qinfo->qtype != LDNS_RR_TYPE_A && 2515 qinfo->qtype != LDNS_RR_TYPE_AAAA && 2516 qinfo->qtype != LDNS_RR_TYPE_ANY) 2517 return 1; 2518 2519 if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo, 2520 alias_rrset, 0, qstate->region, az, NULL, qstate->env->views, 2521 qstate->env->respip_set)) 2522 return 0; 2523 2524 /* xxx_deny actions mean dropping the reply, unless the original reply 2525 * was redirected to response-ip data. */ 2526 if(actinfo->action == respip_always_deny || 2527 ((actinfo->action == respip_deny || 2528 actinfo->action == respip_inform_deny) && 2529 *encode_repp == rep)) 2530 *encode_repp = NULL; 2531 2532 return 1; 2533 } 2534 2535 void 2536 mesh_serve_expired_callback(void* arg) 2537 { 2538 struct mesh_state* mstate = (struct mesh_state*) arg; 2539 struct module_qstate* qstate = &mstate->s; 2540 struct mesh_reply* r; 2541 struct mesh_area* mesh = qstate->env->mesh; 2542 struct dns_msg* msg; 2543 struct mesh_cb* c; 2544 struct mesh_reply* prev = NULL; 2545 struct sldns_buffer* prev_buffer = NULL; 2546 struct sldns_buffer* r_buffer = NULL; 2547 struct reply_info* partial_rep = NULL; 2548 struct ub_packed_rrset_key* alias_rrset = NULL; 2549 struct reply_info* encode_rep = NULL; 2550 struct respip_action_info actinfo; 2551 struct query_info* lookup_qinfo = &qstate->qinfo; 2552 struct query_info qinfo_tmp; 2553 struct timeval tv = {0, 0}; 2554 int must_validate = (!(qstate->query_flags&BIT_CD) 2555 || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate; 2556 int i = 0, for_count; 2557 int is_expired; 2558 if(!qstate->serve_expired_data) return; 2559 verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data"); 2560 comm_timer_delete(qstate->serve_expired_data->timer); 2561 qstate->serve_expired_data->timer = NULL; 2562 /* If is_drop or no_cache_lookup (modules that handle their own cache e.g., 2563 * subnetmod) ignore stale data from the main cache. */ 2564 if(qstate->no_cache_lookup || qstate->is_drop) { 2565 verbose(VERB_ALGO, 2566 "Serve expired: Not allowed to look into cache for stale"); 2567 return; 2568 } 2569 /* The following for is used instead of the `goto lookup_cache` 2570 * like in the worker. This loop should get max 2 passes if we need to 2571 * do any aliasing. */ 2572 for(for_count = 0; for_count < 2; for_count++) { 2573 fptr_ok(fptr_whitelist_serve_expired_lookup( 2574 qstate->serve_expired_data->get_cached_answer)); 2575 msg = (*qstate->serve_expired_data->get_cached_answer)(qstate, 2576 lookup_qinfo, &is_expired); 2577 if(!msg || (FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR 2578 && FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NXDOMAIN 2579 && FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_YXDOMAIN)) { 2580 /* We don't care for cached failure answers at this 2581 * stage. */ 2582 return; 2583 } 2584 /* Reset these in case we pass a second time from here. */ 2585 encode_rep = msg->rep; 2586 memset(&actinfo, 0, sizeof(actinfo)); 2587 actinfo.action = respip_none; 2588 alias_rrset = NULL; 2589 if((mesh->use_response_ip || mesh->use_rpz) && 2590 !partial_rep && !apply_respip_action(qstate, &qstate->qinfo, 2591 qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep, 2592 qstate->env->auth_zones)) { 2593 return; 2594 } else if(partial_rep) { 2595 if(!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep, 2596 qstate->client_info, must_validate, &encode_rep, qstate->region, 2597 qstate->env->auth_zones, qstate->env->views, 2598 qstate->env->respip_set)) { 2599 return; 2600 } 2601 /* merge succeeded; final reply, no further alias pass */ 2602 partial_rep = NULL; 2603 } 2604 if(!encode_rep || alias_rrset) { 2605 if(!encode_rep) { 2606 /* Needs drop */ 2607 return; 2608 } else { 2609 /* A partial CNAME chain is found. */ 2610 partial_rep = encode_rep; 2611 } 2612 } 2613 msg->rep = encode_rep; 2614 /* We've found a partial reply ending with an 2615 * alias. Replace the lookup qinfo for the 2616 * alias target and lookup the cache again to 2617 * (possibly) complete the reply. As we're 2618 * passing the "base" reply, there will be no 2619 * more alias chasing. */ 2620 if(partial_rep) { 2621 memset(&qinfo_tmp, 0, sizeof(qinfo_tmp)); 2622 get_cname_target(alias_rrset, &qinfo_tmp.qname, 2623 &qinfo_tmp.qname_len); 2624 if(!qinfo_tmp.qname) { 2625 log_err("Serve expired: unexpected: invalid answer alias"); 2626 return; 2627 } 2628 qinfo_tmp.qtype = qstate->qinfo.qtype; 2629 qinfo_tmp.qclass = qstate->qinfo.qclass; 2630 lookup_qinfo = &qinfo_tmp; 2631 continue; 2632 } 2633 break; 2634 } 2635 2636 if(verbosity >= VERB_ALGO) 2637 log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep); 2638 2639 while((r = mesh_reply_list_pop_first(mstate)) != NULL) { 2640 2641 /* it was not detached (because it had a reply list), could be now */ 2642 if(!mstate->reply_list && !mstate->cb_list 2643 && mstate->super_set.count == 0) { 2644 mesh->num_detached_states++; 2645 } 2646 /* if not replies any more in mstate, it is no longer a reply_state */ 2647 if(!mstate->reply_list && !mstate->cb_list) { 2648 log_assert(mesh->num_reply_states > 0); 2649 mesh->num_reply_states--; 2650 } 2651 if(mesh_is_udp(r)) { 2652 struct timeval old; 2653 timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time); 2654 if(mstate->s.env->cfg->discard_timeout != 0 && 2655 ((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 > 2656 mstate->s.env->cfg->discard_timeout) { 2657 /* Drop the reply, it is too old */ 2658 verbose(VERB_ALGO, "drop reply, it is older than discard-timeout"); 2659 infra_wait_limit_dec(mstate->s.env->infra_cache, 2660 &r->query_reply, mstate->s.env->cfg); 2661 if(r->query_reply.c->tcp_req_info) 2662 tcp_req_info_remove_mesh_state( 2663 r->query_reply.c->tcp_req_info, mstate); 2664 else if(r->query_reply.c->use_h2) 2665 http2_stream_remove_mesh_state(r->h2_stream); 2666 else if(r->query_reply.doq_stream) 2667 doq_stream_remove_mesh_state(r->query_reply.doq_stream); 2668 comm_point_drop_reply(&r->query_reply); 2669 log_assert(mstate->s.env->mesh->num_reply_addrs > 0); 2670 mstate->s.env->mesh->num_reply_addrs--; 2671 mstate->s.env->mesh->num_queries_discard_timeout++; 2672 continue; 2673 } 2674 } 2675 2676 i++; 2677 tv = r->start_time; 2678 2679 /* If address info is returned, it means the action should be an 2680 * 'inform' variant and the information should be logged. */ 2681 if(actinfo.addrinfo) { 2682 respip_inform_print(&actinfo, r->qname, 2683 qstate->qinfo.qtype, qstate->qinfo.qclass, 2684 r->local_alias, &r->query_reply.client_addr, 2685 r->query_reply.client_addrlen); 2686 } 2687 2688 /* Add EDE Stale Answer (RCF8914). Ignore global ede as this is 2689 * warning instead of an error */ 2690 if(r->edns.edns_present && 2691 qstate->env->cfg->ede_serve_expired && 2692 qstate->env->cfg->ede && 2693 is_expired) { 2694 edns_opt_list_append_ede(&r->edns.opt_list_out, 2695 mstate->s.region, LDNS_EDE_STALE_ANSWER, NULL); 2696 } 2697 2698 r_buffer = r->query_reply.c->buffer; 2699 if(r->query_reply.c->tcp_req_info) 2700 r_buffer = r->query_reply.c->tcp_req_info->spool_buffer; 2701 mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep, 2702 r, r_buffer, prev, prev_buffer); 2703 if(r->query_reply.c->tcp_req_info) 2704 tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate); 2705 /* mesh_send_reply removed mesh state from http2_stream. */ 2706 /* mesh_send_reply decremented wait_limit. */ 2707 prev = r; 2708 prev_buffer = r_buffer; 2709 } 2710 /* Account for each reply sent. */ 2711 if(i > 0) { 2712 mesh->ans_expired += i; 2713 if(actinfo.addrinfo && qstate->env->cfg->stat_extended && 2714 actinfo.rpz_used) { 2715 if(actinfo.rpz_disabled) 2716 qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i; 2717 if(actinfo.rpz_cname_override) 2718 qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i; 2719 else 2720 qstate->env->mesh->rpz_action[ 2721 respip_action_to_rpz_action(actinfo.action)] += i; 2722 } 2723 } 2724 2725 while((c = mstate->cb_list) != NULL) { 2726 /* take this cb off the list; so that the list can be 2727 * changed, eg. by adds from the callback routine */ 2728 if(!mstate->reply_list && mstate->cb_list && !c->next) { 2729 /* was a reply state, not anymore */ 2730 log_assert(qstate->env->mesh->num_reply_states > 0); 2731 qstate->env->mesh->num_reply_states--; 2732 } 2733 mstate->cb_list = c->next; 2734 if(!mstate->reply_list && !mstate->cb_list && 2735 mstate->super_set.count == 0) 2736 qstate->env->mesh->num_detached_states++; 2737 mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c, &tv); 2738 } 2739 } 2740 2741 void 2742 mesh_respond_serve_expired(struct mesh_state* mstate) 2743 { 2744 if(!mstate->s.serve_expired_data) 2745 mesh_serve_expired_init(mstate, -1); 2746 mesh_serve_expired_callback(mstate); 2747 } 2748 2749 int mesh_jostle_exceeded(struct mesh_area* mesh) 2750 { 2751 if(mesh->all.count < mesh->max_reply_states) 2752 return 0; 2753 return 1; 2754 } 2755 2756 void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo, 2757 uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info) 2758 { 2759 struct mesh_state* s = NULL; 2760 s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0); 2761 if(s && mesh_state_del_cb(s, cb, cb_arg)) 2762 goto removed; 2763 if(unique_info) { 2764 s = mesh_area_find_unique(mesh, NULL, qinfo, 2765 qflags&(BIT_RD|BIT_CD), 0, 0, unique_info); 2766 if(s && mesh_state_del_cb(s, cb, cb_arg)) 2767 goto removed; 2768 } 2769 /* mesh_area_find builds key.unique=NULL and cannot match a state 2770 * created with mesh_state_make_unique (e.g. subnetcache sets 2771 * env->unique_mesh). Fall back to a linear scan; cb+cb_arg is an 2772 * exact key (mesh_state_del_cb compares both). 2773 * This works for both lookups for zonemd and for hostname authzone. */ 2774 RBTREE_FOR(s, struct mesh_state*, &mesh->all) { 2775 if(s->cb_list && mesh_state_del_cb(s, cb, cb_arg)) 2776 goto removed; 2777 } 2778 return; 2779 2780 removed: 2781 /* It was in the list and removed. */ 2782 log_assert(mesh->num_reply_addrs > 0); 2783 mesh->num_reply_addrs--; 2784 if(!s->reply_list && !s->cb_list) { 2785 /* was a reply state, not anymore */ 2786 log_assert(mesh->num_reply_states > 0); 2787 mesh->num_reply_states--; 2788 } 2789 if(!s->reply_list && !s->cb_list && 2790 s->super_set.count == 0) { 2791 mesh->num_detached_states++; 2792 } 2793 } 2794