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