1 /* 2 * edns-subnet/subnetmod.c - edns subnet module. Must be called before validator 3 * and iterator. 4 * 5 * Copyright (c) 2013, NLnet Labs. All rights reserved. 6 * 7 * This software is open source. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 16 * Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 20 * Neither the name of the NLNET LABS nor the names of its contributors may 21 * be used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 /** 37 * \file 38 * subnet module for unbound. 39 */ 40 41 #include "config.h" 42 43 #ifdef CLIENT_SUBNET /* keeps splint happy */ 44 45 #include "edns-subnet/subnetmod.h" 46 #include "edns-subnet/edns-subnet.h" 47 #include "edns-subnet/addrtree.h" 48 #include "edns-subnet/subnet-whitelist.h" 49 50 #include "services/mesh.h" 51 #include "services/cache/dns.h" 52 #include "util/module.h" 53 #include "util/regional.h" 54 #include "util/fptr_wlist.h" 55 #include "util/storage/slabhash.h" 56 #include "util/config_file.h" 57 #include "util/data/msgreply.h" 58 #include "sldns/sbuffer.h" 59 #include "sldns/wire2str.h" 60 #include "iterator/iter_utils.h" 61 #ifdef USE_CACHEDB 62 #include "cachedb/cachedb.h" 63 #endif 64 65 /** externally called */ 66 void 67 subnet_data_delete(void *d, void *ATTR_UNUSED(arg)) 68 { 69 struct subnet_msg_cache_data *r; 70 r = (struct subnet_msg_cache_data*)d; 71 addrtree_delete(r->tree4); 72 addrtree_delete(r->tree6); 73 free(r->reason_fail); 74 free(r); 75 } 76 77 /** externally called */ 78 size_t 79 msg_cache_sizefunc(void *k, void *d) 80 { 81 struct msgreply_entry *q = (struct msgreply_entry*)k; 82 struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d; 83 size_t s = sizeof(struct msgreply_entry) 84 + sizeof(struct subnet_msg_cache_data) 85 + q->key.qname_len + lock_get_mem(&q->entry.lock); 86 s += addrtree_size(r->tree4); 87 s += addrtree_size(r->tree6); 88 if(r->reason_fail) 89 s += strlen(r->reason_fail)+1; 90 return s; 91 } 92 93 /** new query for ecs module */ 94 static int 95 subnet_new_qstate(struct module_qstate *qstate, int id) 96 { 97 struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc( 98 qstate->region, sizeof(struct subnet_qstate)); 99 if(!sq) 100 return 0; 101 qstate->minfo[id] = sq; 102 memset(sq, 0, sizeof(*sq)); 103 sq->started_no_cache_store = qstate->no_cache_store; 104 sq->started_no_cache_lookup = qstate->no_cache_lookup; 105 return 1; 106 } 107 108 /** Add ecs struct to edns list, after parsing it to wire format. */ 109 void 110 subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list, 111 struct module_qstate *qstate, struct regional *region) 112 { 113 size_t sn_octs, sn_octs_remainder; 114 sldns_buffer* buf = qstate->env->scratch_buffer; 115 116 if(ecs->subnet_validdata) { 117 log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 || 118 ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6); 119 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 || 120 ecs->subnet_source_mask <= INET_SIZE*8); 121 log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 || 122 ecs->subnet_source_mask <= INET6_SIZE*8); 123 124 sn_octs = ecs->subnet_source_mask / 8; 125 sn_octs_remainder = 126 (size_t)((ecs->subnet_source_mask % 8)>0?1:0); 127 128 log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE); 129 130 sldns_buffer_clear(buf); 131 sldns_buffer_write_u16(buf, ecs->subnet_addr_fam); 132 sldns_buffer_write_u8(buf, ecs->subnet_source_mask); 133 sldns_buffer_write_u8(buf, ecs->subnet_scope_mask); 134 sldns_buffer_write(buf, ecs->subnet_addr, sn_octs); 135 if(sn_octs_remainder) 136 sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] & 137 ~(0xFF >> (ecs->subnet_source_mask % 8))); 138 sldns_buffer_flip(buf); 139 140 edns_opt_list_append(list, 141 qstate->env->cfg->client_subnet_opcode, 142 sn_octs + sn_octs_remainder + 4, 143 sldns_buffer_begin(buf), region); 144 } 145 } 146 147 int ecs_whitelist_check(struct query_info* qinfo, 148 uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate, 149 struct sockaddr_storage* addr, socklen_t addrlen, 150 uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), 151 struct regional *region, int id, void* ATTR_UNUSED(cbargs)) 152 { 153 struct subnet_qstate *sq; 154 struct subnet_env *sn_env; 155 156 if(!(sq=(struct subnet_qstate*)qstate->minfo[id])) 157 return 1; 158 sn_env = (struct subnet_env*)qstate->env->modinfo[id]; 159 160 if(sq->is_subquery_nonsubnet) { 161 if(sq->is_subquery_scopezero) { 162 /* Check if the result can be stored in the global cache, 163 * this is okay if the address and name are not configured 164 * as subnet address and subnet zone. */ 165 if(!ecs_is_whitelisted(sn_env->whitelist, 166 addr, addrlen, qinfo->qname, qinfo->qname_len, 167 qinfo->qclass)) { 168 /* The stub or forward can have no_cache set.*/ 169 if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) { 170 verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache"); 171 } else { 172 verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s", 173 (sq->started_no_cache_store? 174 " But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":"")); 175 qstate->no_cache_store = sq->started_no_cache_store; 176 } 177 } 178 } 179 return 1; 180 } 181 182 /* Cache by default, might be disabled after parsing EDNS option 183 * received from nameserver. */ 184 if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0) 185 && sq->ecs_client_in.subnet_validdata) { 186 qstate->no_cache_store = 0; 187 } 188 189 sq->subnet_sent_no_subnet = 0; 190 if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream && 191 qstate->env->cfg->client_subnet_always_forward) || 192 ecs_is_whitelisted(sn_env->whitelist, 193 addr, addrlen, qinfo->qname, qinfo->qname_len, 194 qinfo->qclass))) { 195 /* Address on whitelist or client query contains ECS option, we 196 * want to sent out ECS. Only add option if it is not already 197 * set. */ 198 if(!edns_opt_list_find(qstate->edns_opts_back_out, 199 qstate->env->cfg->client_subnet_opcode)) { 200 /* if the client is not wanting an EDNS subnet option, 201 * omit it and store that we omitted it but actually 202 * are doing EDNS subnet to the server. */ 203 if(sq->ecs_server_out.subnet_source_mask == 0) { 204 sq->subnet_sent_no_subnet = 1; 205 sq->subnet_sent = 0; 206 /* The result should end up in subnet cache, 207 * not in global cache. */ 208 qstate->no_cache_store = 1; 209 return 1; 210 } 211 subnet_ecs_opt_list_append(&sq->ecs_server_out, 212 &qstate->edns_opts_back_out, qstate, region); 213 } 214 sq->subnet_sent = 1; 215 /* Do not store servfails in global cache, since the subnet 216 * option is sent out. */ 217 qstate->no_cache_store = 1; 218 } 219 else { 220 /* Outgoing ECS option is set, but we don't want to sent it to 221 * this address, remove option. */ 222 if(edns_opt_list_find(qstate->edns_opts_back_out, 223 qstate->env->cfg->client_subnet_opcode)) { 224 edns_opt_list_remove(&qstate->edns_opts_back_out, 225 qstate->env->cfg->client_subnet_opcode); 226 } 227 sq->subnet_sent = 0; 228 } 229 return 1; 230 } 231 232 233 void 234 subnet_markdel(void* key) 235 { 236 struct msgreply_entry *e = (struct msgreply_entry*)key; 237 e->key.qtype = 0; 238 e->key.qclass = 0; 239 } 240 241 int 242 subnetmod_init(struct module_env *env, int id) 243 { 244 struct subnet_env *sn_env = (struct subnet_env*)calloc(1, 245 sizeof(struct subnet_env)); 246 if(!sn_env) { 247 log_err("malloc failure"); 248 return 0; 249 } 250 alloc_init(&sn_env->alloc, NULL, 0); 251 env->modinfo[id] = (void*)sn_env; 252 253 /* Warn that serve-expired and prefetch do not work with the subnet 254 * module cache. */ 255 if(env->cfg->serve_expired) 256 log_warn( 257 "subnetcache: serve-expired is set but not working " 258 "for data originating from the subnet module cache."); 259 if(env->cfg->prefetch) 260 log_warn( 261 "subnetcache: prefetch is set but not working " 262 "for data originating from the subnet module cache."); 263 /* Copy msg_cache settings */ 264 sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs, 265 HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size, 266 msg_cache_sizefunc, query_info_compare, query_entry_delete, 267 subnet_data_delete, NULL); 268 if(!sn_env->subnet_msg_cache) { 269 log_err("subnetcache: could not create cache"); 270 free(sn_env); 271 env->modinfo[id] = NULL; 272 return 0; 273 } 274 slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel); 275 /* whitelist for edns subnet capable servers */ 276 sn_env->whitelist = ecs_whitelist_create(); 277 if(!sn_env->whitelist || 278 !ecs_whitelist_apply_cfg(sn_env->whitelist, env->cfg)) { 279 log_err("subnetcache: could not create ECS whitelist"); 280 slabhash_delete(sn_env->subnet_msg_cache); 281 free(sn_env); 282 env->modinfo[id] = NULL; 283 return 0; 284 } 285 286 verbose(VERB_QUERY, "subnetcache: option registered (%d)", 287 env->cfg->client_subnet_opcode); 288 /* Create new mesh state for all queries. */ 289 env->unique_mesh = 1; 290 if(!edns_register_option(env->cfg->client_subnet_opcode, 291 env->cfg->client_subnet_always_forward /* bypass cache */, 292 1 /* no aggregation */, env)) { 293 log_err("subnetcache: could not register opcode"); 294 ecs_whitelist_delete(sn_env->whitelist); 295 slabhash_delete(sn_env->subnet_msg_cache); 296 free(sn_env); 297 env->modinfo[id] = NULL; 298 return 0; 299 } 300 inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL, 301 env, id); 302 inplace_cb_register((void*)ecs_edns_back_parsed, 303 inplace_cb_edns_back_parsed, NULL, env, id); 304 inplace_cb_register((void*)ecs_query_response, 305 inplace_cb_query_response, NULL, env, id); 306 lock_rw_init(&sn_env->biglock); 307 return 1; 308 } 309 310 void 311 subnetmod_deinit(struct module_env *env, int id) 312 { 313 struct subnet_env *sn_env; 314 if(!env || !env->modinfo[id]) 315 return; 316 sn_env = (struct subnet_env*)env->modinfo[id]; 317 lock_rw_destroy(&sn_env->biglock); 318 inplace_cb_delete(env, inplace_cb_edns_back_parsed, id); 319 inplace_cb_delete(env, inplace_cb_query, id); 320 inplace_cb_delete(env, inplace_cb_query_response, id); 321 ecs_whitelist_delete(sn_env->whitelist); 322 slabhash_delete(sn_env->subnet_msg_cache); 323 alloc_clear(&sn_env->alloc); 324 free(sn_env); 325 env->modinfo[id] = NULL; 326 } 327 328 /** Tells client that upstream has no/improper support */ 329 static void 330 cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source) 331 { 332 target->subnet_scope_mask = 0; 333 target->subnet_source_mask = source->subnet_source_mask; 334 target->subnet_addr_fam = source->subnet_addr_fam; 335 memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE); 336 target->subnet_validdata = 1; 337 } 338 339 static void 340 delfunc(void *envptr, void *elemptr) { 341 struct reply_info *elem = (struct reply_info *)elemptr; 342 struct subnet_env *env = (struct subnet_env *)envptr; 343 reply_info_parsedelete(elem, &env->alloc); 344 } 345 346 static size_t 347 sizefunc(void *elemptr) { 348 struct reply_info *elem = (struct reply_info *)elemptr; 349 size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref) 350 + elem->rrset_count * sizeof (struct rrset_ref) 351 + elem->rrset_count * sizeof (struct ub_packed_rrset_key *); 352 size_t i; 353 for (i = 0; i < elem->rrset_count; i++) { 354 struct ub_packed_rrset_key *key = elem->rrsets[i]; 355 struct packed_rrset_data *data = key->entry.data; 356 s += ub_rrset_sizefunc(key, data); 357 } 358 if(elem->reason_bogus_str) 359 s += strlen(elem->reason_bogus_str)+1; 360 return s; 361 } 362 363 /** 364 * Select tree from cache entry based on edns data. 365 * If for address family not present it will create a new one. 366 * NULL on failure to create. */ 367 static struct addrtree* 368 get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns, 369 struct subnet_env *env, struct config_file* cfg) 370 { 371 struct addrtree *tree; 372 if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { 373 if (!data->tree4) 374 data->tree4 = addrtree_create( 375 cfg->max_client_subnet_ipv4, &delfunc, 376 &sizefunc, env, cfg->max_ecs_tree_size_ipv4); 377 tree = data->tree4; 378 } else { 379 if (!data->tree6) 380 data->tree6 = addrtree_create( 381 cfg->max_client_subnet_ipv6, &delfunc, 382 &sizefunc, env, cfg->max_ecs_tree_size_ipv6); 383 tree = data->tree6; 384 } 385 return tree; 386 } 387 388 static void 389 update_cache(struct module_qstate *qstate, int id) 390 { 391 struct msgreply_entry *mrep_entry; 392 struct addrtree *tree; 393 struct reply_info *rep; 394 struct query_info qinf; 395 struct subnet_env *sne = qstate->env->modinfo[id]; 396 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id]; 397 struct slabhash *subnet_msg_cache = sne->subnet_msg_cache; 398 struct ecs_data *edns = &sq->ecs_client_in; 399 size_t i; 400 int only_match_scope_zero, diff_size; 401 402 /* We already calculated hash upon lookup (lookup_and_reply) if we were 403 * allowed to look in the ECS cache */ 404 hashvalue_type h = qstate->minfo[id] && 405 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated? 406 ((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash : 407 query_info_hash(&qstate->qinfo, qstate->query_flags); 408 /* Step 1, general qinfo lookup */ 409 struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h, 410 &qstate->qinfo, 1); 411 int need_to_insert = (lru_entry == NULL); 412 if (!lru_entry) { 413 void* data = calloc(1, 414 sizeof(struct subnet_msg_cache_data)); 415 if(!data) { 416 log_err("malloc failed"); 417 return; 418 } 419 qinf = qstate->qinfo; 420 qinf.qname = memdup(qstate->qinfo.qname, 421 qstate->qinfo.qname_len); 422 if(!qinf.qname) { 423 free(data); 424 log_err("memdup failed"); 425 return; 426 } 427 mrep_entry = query_info_entrysetup(&qinf, data, h); 428 free(qinf.qname); /* if qname 'consumed', it is set to NULL */ 429 if (!mrep_entry) { 430 free(data); 431 log_err("query_info_entrysetup failed"); 432 return; 433 } 434 lru_entry = &mrep_entry->entry; 435 lock_rw_wrlock(&lru_entry->lock); 436 } 437 /* lru_entry->lock is locked regardless of how we got here, 438 * either from the slabhash_lookup, or above in the new allocated */ 439 if(!qstate->return_msg && qstate->error_response_cache) { 440 struct subnet_msg_cache_data *data = 441 (struct subnet_msg_cache_data*)lru_entry->data; 442 data->ttl_servfail = *qstate->env->now + NORR_TTL; 443 data->ede_fail = errinf_to_reason_bogus(qstate); 444 diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0); 445 if(qstate->errinf) { 446 char* str = errinf_to_str_misc(qstate); 447 free(data->reason_fail); 448 data->reason_fail = NULL; 449 if(str) 450 data->reason_fail = strdup(str); 451 } 452 diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0) 453 - diff_size; 454 lock_rw_unlock(&lru_entry->lock); 455 if (need_to_insert) { 456 slabhash_insert(subnet_msg_cache, h, lru_entry, 457 lru_entry->data, NULL); 458 } else { 459 slabhash_update_space_used(subnet_msg_cache, h, NULL, 460 diff_size); 461 } 462 return; 463 } 464 if(!qstate->return_msg) { 465 lock_rw_unlock(&lru_entry->lock); 466 return; 467 } 468 /* Step 2, find the correct tree */ 469 if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) { 470 lock_rw_unlock(&lru_entry->lock); 471 log_err("subnetcache: cache insertion failed"); 472 return; 473 } 474 lock_quick_lock(&sne->alloc.lock); 475 rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL); 476 lock_quick_unlock(&sne->alloc.lock); 477 if (!rep) { 478 lock_rw_unlock(&lru_entry->lock); 479 log_err("subnetcache: cache insertion failed"); 480 return; 481 } 482 483 /* store RRsets */ 484 for(i=0; i<rep->rrset_count; i++) { 485 rep->ref[i].key = rep->rrsets[i]; 486 rep->ref[i].id = rep->rrsets[i]->id; 487 } 488 reply_info_set_ttls(rep, *qstate->env->now); 489 reply_info_sortref(rep); 490 rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */ 491 rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */ 492 if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0) 493 only_match_scope_zero = 1; 494 else only_match_scope_zero = 0; 495 diff_size = (int)tree->size_bytes; 496 addrtree_insert(tree, (addrkey_t*)edns->subnet_addr, 497 edns->subnet_source_mask, sq->max_scope, rep, 498 rep->ttl, *qstate->env->now, only_match_scope_zero); 499 diff_size = (int)tree->size_bytes - diff_size; 500 501 lock_rw_unlock(&lru_entry->lock); 502 if (need_to_insert) { 503 slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data, 504 NULL); 505 } else { 506 slabhash_update_space_used(subnet_msg_cache, h, NULL, 507 diff_size); 508 } 509 } 510 511 /** See if there is a stored servfail, returns true if so, and sets reply. */ 512 static int 513 lookup_check_servfail(struct module_qstate *qstate, 514 struct subnet_msg_cache_data *data) 515 { 516 struct module_env *env = qstate->env; 517 if(!data) 518 return 0; 519 if(!data->ttl_servfail || TTL_IS_EXPIRED(data->ttl_servfail, *env->now)) 520 return 0; 521 qstate->return_rcode = LDNS_RCODE_SERVFAIL; 522 errinf_ede(qstate, data->reason_fail, data->ede_fail); 523 return 1; 524 } 525 526 /** Lookup in cache and reply true iff reply is sent. */ 527 static int 528 lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch) 529 { 530 struct lruhash_entry *e; 531 struct module_env *env = qstate->env; 532 struct subnet_env *sne = (struct subnet_env*)env->modinfo[id]; 533 hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags); 534 struct subnet_msg_cache_data *data; 535 struct ecs_data *ecs = &sq->ecs_client_in; 536 struct addrtree *tree; 537 struct addrnode *node; 538 uint8_t scope; 539 int must_validate = (!(qstate->query_flags&BIT_CD) 540 || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate; 541 542 memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out)); 543 544 if (sq) { 545 sq->qinfo_hash = h; /* Might be useful on cache miss */ 546 sq->qinfo_hash_calculated = 1; 547 } 548 e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1); 549 if (!e) return 0; /* qinfo not in cache */ 550 data = e->data; 551 tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)? 552 data->tree4 : data->tree6; 553 if (!tree) { /* qinfo in cache but not for this family */ 554 if(lookup_check_servfail(qstate, data)) { 555 lock_rw_unlock(&e->lock); 556 return 1; 557 } 558 lock_rw_unlock(&e->lock); 559 return 0; 560 } 561 node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr, 562 ecs->subnet_source_mask, *env->now); 563 if (!node) { /* plain old cache miss */ 564 if(lookup_check_servfail(qstate, data)) { 565 lock_rw_unlock(&e->lock); 566 return 1; 567 } 568 lock_rw_unlock(&e->lock); 569 return 0; 570 } 571 572 qstate->return_msg = tomsg(NULL, &qstate->qinfo, 573 (struct reply_info *)node->elem, qstate->region, *env->now, 0, 574 env->scratch); 575 scope = (uint8_t)node->scope; 576 577 if (!qstate->return_msg) { /* Failed allocation or expired TTL */ 578 if(lookup_check_servfail(qstate, data)) { 579 lock_rw_unlock(&e->lock); 580 return 1; 581 } 582 lock_rw_unlock(&e->lock); 583 return 0; 584 } 585 lock_rw_unlock(&e->lock); 586 if(qstate->return_msg->rep->security == sec_status_unchecked 587 && must_validate) { 588 /* The message has to be validated first. */ 589 verbose(VERB_ALGO, "subnet: unchecked cache entry needs " 590 "validation"); 591 return 0; 592 } 593 594 if (sq->subnet_downstream) { /* relay to interested client */ 595 sq->ecs_client_out.subnet_scope_mask = scope; 596 sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam; 597 sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask; 598 memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr, 599 INET6_SIZE); 600 sq->ecs_client_out.subnet_validdata = 1; 601 } 602 603 if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) { 604 qstate->need_refetch = 1; 605 } 606 return 1; 607 } 608 609 /** 610 * Test first bits of addresses for equality. Caller is responsible 611 * for making sure that both a and b are at least net/8 octets long. 612 * @param a: first address. 613 * @param a: seconds address. 614 * @param net: Number of bits to test. 615 * @return: 1 if equal, 0 otherwise. 616 */ 617 static int 618 common_prefix(uint8_t *a, uint8_t *b, uint8_t net) 619 { 620 size_t n = (size_t)net / 8; 621 return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]); 622 } 623 624 /** 625 * Create sub request that looks up the query. 626 * @param qstate: query state 627 * @param id: module id. 628 * @param sq: subnet qstate 629 * @return false on failure. 630 */ 631 static int 632 generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq) 633 { 634 struct module_qstate* subq = NULL; 635 uint16_t qflags = 0; /* OPCODE QUERY, no flags */ 636 int prime = 0; 637 int valrec = 0; 638 struct query_info qinf; 639 qinf.qname = qstate->qinfo.qname; 640 qinf.qname_len = qstate->qinfo.qname_len; 641 qinf.qtype = qstate->qinfo.qtype; 642 qinf.qclass = qstate->qinfo.qclass; 643 qinf.local_alias = NULL; 644 645 qflags |= BIT_RD; 646 if((qstate->query_flags & BIT_CD)!=0) { 647 qflags |= BIT_CD; 648 /* The valrec is left off. Leave out: valrec = 1; 649 * So that the cache is protected with DNSSEC validation. 650 * Just like the global cache. DNSSEC validation is performed 651 * regardless of the setting of the querier's CD flag. */ 652 } 653 654 fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); 655 if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info, 656 qflags, prime, valrec, &subq)) { 657 return 0; 658 } 659 if(subq) { 660 /* It is possible to access the subquery module state. */ 661 struct subnet_qstate* subsq; 662 if(!subnet_new_qstate(subq, id)) { 663 verbose(VERB_ALGO, "Could not allocate new subnet qstate"); 664 return 0; 665 } 666 subsq = (struct subnet_qstate*)subq->minfo[id]; 667 subsq->is_subquery_nonsubnet = 1; 668 subsq->started_no_cache_store = sq->started_no_cache_store; 669 670 /* When the client asks 0.0.0.0/0 and the name is not treated 671 * as subnet, it is to be stored in the global cache. 672 * Store that the client asked for that, if so. */ 673 if(sq->ecs_client_in.subnet_source_mask == 0 && 674 edns_opt_list_find(qstate->edns_opts_front_in, 675 qstate->env->cfg->client_subnet_opcode)) { 676 subq->no_cache_store = 1; 677 subsq->is_subquery_scopezero = 1; 678 } 679 } 680 return 1; 681 } 682 683 /** 684 * Perform the query without subnet 685 * @param qstate: query state 686 * @param id: module id. 687 * @param sq: subnet qstate 688 * @return module state 689 */ 690 static enum module_ext_state 691 generate_lookup_without_subnet(struct module_qstate *qstate, int id, 692 struct subnet_qstate* sq) 693 { 694 verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet"); 695 if(!generate_sub_request(qstate, id, sq)) { 696 verbose(VERB_ALGO, "Could not generate sub query"); 697 qstate->return_rcode = LDNS_RCODE_SERVFAIL; 698 qstate->return_msg = NULL; 699 return module_finished; 700 } 701 sq->wait_subquery = 1; 702 return module_wait_subquery; 703 } 704 705 static enum module_ext_state 706 eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) 707 { 708 struct subnet_env *sne = qstate->env->modinfo[id]; 709 710 struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */ 711 struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */ 712 struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */ 713 struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */ 714 715 memset(c_out, 0, sizeof(*c_out)); 716 717 if (!qstate->return_msg) { 718 /* already an answer and its not a message, but retain 719 * the actual rcode, instead of module_error, so send 720 * module_finished */ 721 if(qstate->error_response_cache) { 722 verbose(VERB_ALGO, "subnet: store error response"); 723 lock_rw_wrlock(&sne->biglock); 724 update_cache(qstate, id); 725 lock_rw_unlock(&sne->biglock); 726 } 727 return module_finished; 728 } 729 730 /* We have not asked for subnet data */ 731 if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) { 732 if (s_in->subnet_validdata) 733 verbose(VERB_QUERY, "subnetcache: received spurious data"); 734 if (sq->subnet_downstream) /* Copy back to client */ 735 cp_edns_bad_response(c_out, c_in); 736 return module_finished; 737 } 738 739 /* subnet sent but nothing came back */ 740 if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) { 741 /* The authority indicated no support for edns subnet. As a 742 * consequence the answer ended up in the regular cache. It 743 * is still useful to put it in the edns subnet cache for 744 * when a client explicitly asks for subnet specific answer. */ 745 verbose(VERB_QUERY, "subnetcache: Authority indicates no support"); 746 return generate_lookup_without_subnet(qstate, id, sq); 747 } 748 749 /* Purposefully there was no sent subnet, and there is consequently 750 * no subnet in the answer. If there was, use the subnet in the answer 751 * anyway. But if there is not, treat it as a prefix 0 answer. */ 752 if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) { 753 /* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */ 754 s_in->subnet_addr_fam = s_out->subnet_addr_fam; 755 s_in->subnet_source_mask = 0; 756 s_in->subnet_scope_mask = 0; 757 memset(s_in->subnet_addr, 0, INET6_SIZE); 758 s_in->subnet_validdata = 1; 759 } 760 761 /* Being here means we have asked for and got a subnet specific 762 * answer. Also, the answer from the authority is not yet cached 763 * anywhere. */ 764 765 /* can we accept response? */ 766 if(s_out->subnet_addr_fam != s_in->subnet_addr_fam || 767 s_out->subnet_source_mask != s_in->subnet_source_mask || 768 !common_prefix(s_out->subnet_addr, s_in->subnet_addr, 769 s_out->subnet_source_mask)) 770 { 771 /* we can not accept, perform query without option */ 772 verbose(VERB_QUERY, "subnetcache: forged data"); 773 s_out->subnet_validdata = 0; 774 (void)edns_opt_list_remove(&qstate->edns_opts_back_out, 775 qstate->env->cfg->client_subnet_opcode); 776 sq->subnet_sent = 0; 777 sq->subnet_sent_no_subnet = 0; 778 return generate_lookup_without_subnet(qstate, id, sq); 779 } 780 781 lock_rw_wrlock(&sne->biglock); 782 if(!sq->started_no_cache_store) { 783 update_cache(qstate, id); 784 } 785 sne->num_msg_nocache++; 786 lock_rw_unlock(&sne->biglock); 787 788 /* If there is an expired answer in the global cache, remove that, 789 * because expired answers would otherwise resurface once the ecs data 790 * expires, giving once in a while global data responses for ecs 791 * domains, with serve expired enabled. */ 792 if(qstate->env->cfg->serve_expired) { 793 msg_cache_remove(qstate->env, qstate->qinfo.qname, 794 qstate->qinfo.qname_len, qstate->qinfo.qtype, 795 qstate->qinfo.qclass, 0); 796 #ifdef USE_CACHEDB 797 if(qstate->env->cachedb_enabled) 798 cachedb_msg_remove(qstate); 799 #endif 800 } 801 802 if (sq->subnet_downstream) { 803 /* Client wants to see the answer, echo option back 804 * and adjust the scope. */ 805 c_out->subnet_addr_fam = c_in->subnet_addr_fam; 806 c_out->subnet_source_mask = c_in->subnet_source_mask; 807 memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE); 808 c_out->subnet_scope_mask = sq->max_scope; 809 /* Limit scope returned to client to scope used for caching. */ 810 if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { 811 if(c_out->subnet_scope_mask > 812 qstate->env->cfg->max_client_subnet_ipv4) { 813 c_out->subnet_scope_mask = 814 qstate->env->cfg->max_client_subnet_ipv4; 815 } 816 } 817 else if(c_out->subnet_scope_mask > 818 qstate->env->cfg->max_client_subnet_ipv6) { 819 c_out->subnet_scope_mask = 820 qstate->env->cfg->max_client_subnet_ipv6; 821 } 822 c_out->subnet_validdata = 1; 823 } 824 return module_finished; 825 } 826 827 /** Parse EDNS opt data containing ECS */ 828 static int 829 parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs) 830 { 831 memset(ecs, 0, sizeof(*ecs)); 832 if (ecs_option->opt_len < 4) 833 return 0; 834 835 ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data); 836 ecs->subnet_source_mask = ecs_option->opt_data[2]; 837 ecs->subnet_scope_mask = ecs_option->opt_data[3]; 838 /* remaining bytes indicate address */ 839 840 /* validate input*/ 841 /* option length matches calculated length? */ 842 if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4)) 843 return 0; 844 if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0) 845 return 0; 846 if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) { 847 if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32) 848 return 0; 849 } else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) { 850 if (ecs->subnet_source_mask > 128 || 851 ecs->subnet_scope_mask > 128) 852 return 0; 853 } else 854 return 0; 855 856 /* valid ECS data, write to ecs_data */ 857 if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4, 858 ecs_option->opt_len - 4, ecs->subnet_source_mask)) 859 return 0; 860 ecs->subnet_validdata = 1; 861 return 1; 862 } 863 864 void 865 subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs, 866 struct config_file* cfg) 867 { 868 void* sinaddr; 869 870 /* Construct subnet option from original query */ 871 if(((struct sockaddr_in*)ss)->sin_family == AF_INET) { 872 ecs->subnet_source_mask = cfg->max_client_subnet_ipv4; 873 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4; 874 sinaddr = &((struct sockaddr_in*)ss)->sin_addr; 875 if (!copy_clear( ecs->subnet_addr, INET6_SIZE, 876 (uint8_t *)sinaddr, INET_SIZE, 877 ecs->subnet_source_mask)) { 878 ecs->subnet_validdata = 1; 879 } 880 } 881 #ifdef INET6 882 else { 883 ecs->subnet_source_mask = cfg->max_client_subnet_ipv6; 884 ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6; 885 sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr; 886 if (!copy_clear( ecs->subnet_addr, INET6_SIZE, 887 (uint8_t *)sinaddr, INET6_SIZE, 888 ecs->subnet_source_mask)) { 889 ecs->subnet_validdata = 1; 890 } 891 } 892 #else 893 /* We don't know how to handle ip6, just pass */ 894 #endif /* INET6 */ 895 } 896 897 int 898 ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, 899 int id, void* ATTR_UNUSED(cbargs)) 900 { 901 struct subnet_qstate *sq; 902 903 if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id])) 904 return 1; 905 906 if(sq->subnet_sent && 907 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) { 908 /* REFUSED response to ECS query, remove ECS option. */ 909 edns_opt_list_remove(&qstate->edns_opts_back_out, 910 qstate->env->cfg->client_subnet_opcode); 911 sq->subnet_sent = 0; 912 sq->subnet_sent_no_subnet = 0; 913 memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out)); 914 } else if (!sq->track_max_scope && 915 FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR && 916 response->rep->an_numrrsets > 0 917 ) { 918 struct ub_packed_rrset_key* s = response->rep->rrsets[0]; 919 if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME && 920 query_dname_compare(qstate->qinfo.qname, 921 s->rk.dname) == 0) { 922 /* CNAME response for QNAME. From now on keep track of 923 * longest received ECS prefix for all queries on this 924 * qstate. */ 925 sq->track_max_scope = 1; 926 } 927 } 928 return 1; 929 } 930 931 /** verbose print edns subnet option in pretty print */ 932 static void 933 subnet_log_print(const char* s, struct edns_option* ecs_opt) 934 { 935 if(verbosity >= VERB_ALGO) { 936 char buf[256]; 937 char* str = buf; 938 size_t str_len = sizeof(buf); 939 if(!ecs_opt) { 940 verbose(VERB_ALGO, "%s (null)", s); 941 return; 942 } 943 (void)sldns_wire2str_edns_subnet_print(&str, &str_len, 944 ecs_opt->opt_data, ecs_opt->opt_len); 945 verbose(VERB_ALGO, "%s %s", s, buf); 946 } 947 } 948 949 int 950 ecs_edns_back_parsed(struct module_qstate* qstate, int id, 951 void* ATTR_UNUSED(cbargs)) 952 { 953 struct subnet_qstate *sq; 954 struct edns_option* ecs_opt; 955 956 if(!(sq=(struct subnet_qstate*)qstate->minfo[id])) 957 return 1; 958 if((ecs_opt = edns_opt_list_find( 959 qstate->edns_opts_back_in, 960 qstate->env->cfg->client_subnet_opcode)) && 961 parse_subnet_option(ecs_opt, &sq->ecs_server_in) && 962 sq->subnet_sent && sq->ecs_server_in.subnet_validdata) { 963 subnet_log_print("answer has edns subnet", ecs_opt); 964 /* Only skip global cache store if we sent an ECS option 965 * and received one back. Answers from non-whitelisted 966 * servers will end up in global cache. Answers for 967 * queries with 0 source will not (unless nameserver 968 * does not support ECS). */ 969 qstate->no_cache_store = 1; 970 if(!sq->track_max_scope || (sq->track_max_scope && 971 sq->ecs_server_in.subnet_scope_mask > 972 sq->max_scope)) 973 sq->max_scope = sq->ecs_server_in.subnet_scope_mask; 974 } else if(sq->subnet_sent_no_subnet) { 975 /* The answer can be stored as scope 0, not in global cache. */ 976 /* This was already set in ecs_whitelist_check */ 977 qstate->no_cache_store = 1; 978 } else if(sq->subnet_sent) { 979 /* Need another query to be able to store in global cache. */ 980 /* This was already set in ecs_whitelist_check */ 981 qstate->no_cache_store = 1; 982 } 983 984 return 1; 985 } 986 987 void 988 subnetmod_operate(struct module_qstate *qstate, enum module_ev event, 989 int id, struct outbound_entry* outbound) 990 { 991 struct subnet_env *sne = qstate->env->modinfo[id]; 992 struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id]; 993 994 verbose(VERB_QUERY, "subnetcache[module %d] operate: extstate:%s " 995 "event:%s", id, strextstate(qstate->ext_state[id]), 996 strmodulevent(event)); 997 log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo); 998 999 if(sq && sq->wait_subquery_done) { 1000 /* The subquery lookup returned. */ 1001 if(sq->ecs_client_in.subnet_source_mask == 0 && 1002 edns_opt_list_find(qstate->edns_opts_front_in, 1003 qstate->env->cfg->client_subnet_opcode)) { 1004 if(!sq->started_no_cache_store && 1005 qstate->return_msg) { 1006 lock_rw_wrlock(&sne->biglock); 1007 update_cache(qstate, id); 1008 lock_rw_unlock(&sne->biglock); 1009 } 1010 if (sq->subnet_downstream) 1011 cp_edns_bad_response(&sq->ecs_client_out, 1012 &sq->ecs_client_in); 1013 /* It is a scope zero lookup, append edns subnet 1014 * option to the querier. */ 1015 subnet_ecs_opt_list_append(&sq->ecs_client_out, 1016 &qstate->edns_opts_front_out, qstate, 1017 qstate->region); 1018 } 1019 sq->wait_subquery_done = 0; 1020 qstate->ext_state[id] = module_finished; 1021 qstate->no_cache_store = sq->started_no_cache_store; 1022 qstate->no_cache_lookup = sq->started_no_cache_lookup; 1023 return; 1024 } 1025 if((event == module_event_new || event == module_event_pass) && 1026 sq == NULL) { 1027 struct edns_option* ecs_opt; 1028 if(!subnet_new_qstate(qstate, id)) { 1029 qstate->return_msg = NULL; 1030 qstate->ext_state[id] = module_finished; 1031 return; 1032 } 1033 1034 sq = (struct subnet_qstate*)qstate->minfo[id]; 1035 if(sq->wait_subquery) 1036 return; /* Wait for that subquery to return */ 1037 1038 if((ecs_opt = edns_opt_list_find( 1039 qstate->edns_opts_front_in, 1040 qstate->env->cfg->client_subnet_opcode))) { 1041 if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) { 1042 /* Wrongly formatted ECS option. RFC mandates to 1043 * return FORMERROR. */ 1044 qstate->return_rcode = LDNS_RCODE_FORMERR; 1045 qstate->ext_state[id] = module_finished; 1046 return; 1047 } 1048 subnet_log_print("query has edns subnet", ecs_opt); 1049 sq->subnet_downstream = 1; 1050 } 1051 else if(qstate->mesh_info->reply_list) { 1052 subnet_option_from_ss( 1053 &qstate->mesh_info->reply_list->query_reply.client_addr, 1054 &sq->ecs_client_in, qstate->env->cfg); 1055 } 1056 else if(qstate->client_addr.ss_family != AF_UNSPEC) { 1057 subnet_option_from_ss( 1058 &qstate->client_addr, 1059 &sq->ecs_client_in, qstate->env->cfg); 1060 } 1061 1062 if(sq->ecs_client_in.subnet_validdata == 0) { 1063 /* No clients are interested in result or we could not 1064 * parse it, we don't do client subnet */ 1065 sq->ecs_server_out.subnet_validdata = 0; 1066 if(edns_opt_list_find(qstate->edns_opts_front_in, 1067 qstate->env->cfg->client_subnet_opcode)) { 1068 /* aggregated this deaggregated state */ 1069 qstate->ext_state[id] = 1070 generate_lookup_without_subnet( 1071 qstate, id, sq); 1072 return; 1073 } 1074 verbose(VERB_ALGO, "subnetcache: pass to next module"); 1075 qstate->ext_state[id] = module_wait_module; 1076 return; 1077 } 1078 1079 /* Limit to minimum allowed source mask */ 1080 if(sq->ecs_client_in.subnet_source_mask != 0 && ( 1081 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 && 1082 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv4) || 1083 (sq->ecs_client_in.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 && 1084 sq->ecs_client_in.subnet_source_mask < qstate->env->cfg->min_client_subnet_ipv6))) { 1085 qstate->return_rcode = LDNS_RCODE_REFUSED; 1086 qstate->ext_state[id] = module_finished; 1087 return; 1088 } 1089 1090 if(!sq->started_no_cache_lookup && !qstate->blacklist) { 1091 lock_rw_wrlock(&sne->biglock); 1092 if(qstate->mesh_info->reply_list && 1093 lookup_and_reply(qstate, id, sq, 1094 qstate->env->cfg->prefetch)) { 1095 sne->num_msg_cache++; 1096 lock_rw_unlock(&sne->biglock); 1097 verbose(VERB_QUERY, "subnetcache: answered from cache"); 1098 qstate->ext_state[id] = module_finished; 1099 1100 subnet_ecs_opt_list_append(&sq->ecs_client_out, 1101 &qstate->edns_opts_front_out, qstate, 1102 qstate->region); 1103 if(verbosity >= VERB_ALGO) { 1104 subnet_log_print("reply has edns subnet", 1105 edns_opt_list_find( 1106 qstate->edns_opts_front_out, 1107 qstate->env->cfg-> 1108 client_subnet_opcode)); 1109 } 1110 return; 1111 } 1112 lock_rw_unlock(&sne->biglock); 1113 } 1114 if(sq->ecs_client_in.subnet_source_mask == 0 && 1115 edns_opt_list_find(qstate->edns_opts_front_in, 1116 qstate->env->cfg->client_subnet_opcode)) { 1117 /* client asked for resolution without edns subnet */ 1118 qstate->ext_state[id] = generate_lookup_without_subnet( 1119 qstate, id, sq); 1120 return; 1121 } 1122 1123 sq->ecs_server_out.subnet_addr_fam = 1124 sq->ecs_client_in.subnet_addr_fam; 1125 sq->ecs_server_out.subnet_source_mask = 1126 sq->ecs_client_in.subnet_source_mask; 1127 /* Limit source prefix to configured maximum */ 1128 if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 1129 && sq->ecs_server_out.subnet_source_mask > 1130 qstate->env->cfg->max_client_subnet_ipv4) 1131 sq->ecs_server_out.subnet_source_mask = 1132 qstate->env->cfg->max_client_subnet_ipv4; 1133 else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6 1134 && sq->ecs_server_out.subnet_source_mask > 1135 qstate->env->cfg->max_client_subnet_ipv6) 1136 sq->ecs_server_out.subnet_source_mask = 1137 qstate->env->cfg->max_client_subnet_ipv6; 1138 /* Safe to copy completely, even if the source is limited by the 1139 * configuration. subnet_ecs_opt_list_append() will limit the address. 1140 * */ 1141 memcpy(&sq->ecs_server_out.subnet_addr, 1142 sq->ecs_client_in.subnet_addr, INET6_SIZE); 1143 sq->ecs_server_out.subnet_scope_mask = 0; 1144 sq->ecs_server_out.subnet_validdata = 1; 1145 if(sq->ecs_server_out.subnet_source_mask != 0 && 1146 qstate->env->cfg->client_subnet_always_forward && 1147 sq->subnet_downstream) 1148 /* ECS specific data required, do not look at the global 1149 * cache in other modules. */ 1150 qstate->no_cache_lookup = 1; 1151 1152 /* pass request to next module */ 1153 verbose(VERB_ALGO, 1154 "subnetcache: not found in cache. pass to next module"); 1155 qstate->ext_state[id] = module_wait_module; 1156 return; 1157 } 1158 if(sq && sq->wait_subquery) 1159 return; /* Wait for that subquery to return */ 1160 /* Query handed back by next module, we have a 'final' answer */ 1161 if(sq && event == module_event_moddone) { 1162 qstate->ext_state[id] = eval_response(qstate, id, sq); 1163 if(qstate->ext_state[id] == module_finished && 1164 qstate->return_msg) { 1165 subnet_ecs_opt_list_append(&sq->ecs_client_out, 1166 &qstate->edns_opts_front_out, qstate, 1167 qstate->region); 1168 if(verbosity >= VERB_ALGO) { 1169 subnet_log_print("reply has edns subnet", 1170 edns_opt_list_find( 1171 qstate->edns_opts_front_out, 1172 qstate->env->cfg-> 1173 client_subnet_opcode)); 1174 } 1175 } 1176 qstate->no_cache_store = sq->started_no_cache_store; 1177 qstate->no_cache_lookup = sq->started_no_cache_lookup; 1178 return; 1179 } 1180 if(sq && outbound) { 1181 return; 1182 } 1183 /* We are being revisited */ 1184 if(event == module_event_pass || event == module_event_new) { 1185 /* Just pass it on, we already did the work */ 1186 verbose(VERB_ALGO, "subnetcache: pass to next module"); 1187 qstate->ext_state[id] = module_wait_module; 1188 return; 1189 } 1190 if(!sq && (event == module_event_moddone)) { 1191 /* during priming, module done but we never started */ 1192 qstate->ext_state[id] = module_finished; 1193 return; 1194 } 1195 log_err("subnetcache: bad event %s", strmodulevent(event)); 1196 qstate->ext_state[id] = module_error; 1197 return; 1198 } 1199 1200 void 1201 subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate), 1202 int ATTR_UNUSED(id)) 1203 { 1204 /* qstate has no data outside region */ 1205 } 1206 1207 void 1208 subnetmod_inform_super(struct module_qstate *qstate, int id, 1209 struct module_qstate *super) 1210 { 1211 struct subnet_qstate* super_sq = 1212 (struct subnet_qstate*)super->minfo[id]; 1213 log_query_info(VERB_ALGO, "subnetcache inform_super: query", 1214 &super->qinfo); 1215 super_sq->wait_subquery = 0; 1216 super_sq->wait_subquery_done = 1; 1217 if(qstate->return_rcode != LDNS_RCODE_NOERROR || 1218 !qstate->return_msg) { 1219 super->return_msg = NULL; 1220 super->return_rcode = LDNS_RCODE_SERVFAIL; 1221 return; 1222 } 1223 super->return_rcode = LDNS_RCODE_NOERROR; 1224 super->return_msg = dns_copy_msg(qstate->return_msg, super->region); 1225 if(!super->return_msg) { 1226 log_err("subnetcache: copy response, out of memory"); 1227 super->return_rcode = LDNS_RCODE_SERVFAIL; 1228 } 1229 } 1230 1231 size_t 1232 subnetmod_get_mem(struct module_env *env, int id) 1233 { 1234 struct subnet_env *sn_env = env->modinfo[id]; 1235 if (!sn_env) return 0; 1236 return sizeof(*sn_env) + 1237 slabhash_get_mem(sn_env->subnet_msg_cache) + 1238 ecs_whitelist_get_mem(sn_env->whitelist); 1239 } 1240 1241 /** 1242 * The module function block 1243 */ 1244 static struct module_func_block subnetmod_block = { 1245 "subnetcache", 1246 NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate, 1247 &subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem 1248 }; 1249 1250 struct module_func_block* 1251 subnetmod_get_funcblock(void) 1252 { 1253 return &subnetmod_block; 1254 } 1255 1256 /** Wrappers for static functions to unit test */ 1257 size_t 1258 unittest_wrapper_subnetmod_sizefunc(void *elemptr) 1259 { 1260 return sizefunc(elemptr); 1261 } 1262 1263 #endif /* CLIENT_SUBNET */ 1264