1 /* 2 * services/cache/dns.c - Cache services for DNS using msg and rrset caches. 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 the DNS cache. 40 */ 41 #include "config.h" 42 #include "iterator/iter_delegpt.h" 43 #include "iterator/iter_utils.h" 44 #include "validator/val_nsec.h" 45 #include "validator/val_utils.h" 46 #include "services/cache/dns.h" 47 #include "services/cache/rrset.h" 48 #include "util/data/msgparse.h" 49 #include "util/data/msgreply.h" 50 #include "util/data/packed_rrset.h" 51 #include "util/data/dname.h" 52 #include "util/module.h" 53 #include "util/net_help.h" 54 #include "util/regional.h" 55 #include "util/config_file.h" 56 #include "sldns/sbuffer.h" 57 58 /** store rrsets in the rrset cache. 59 * @param env: module environment with caches. 60 * @param rep: contains list of rrsets to store. 61 * @param now: current time. 62 * @param leeway: during prefetch how much leeway to update TTLs. 63 * This makes rrsets (other than type NS) timeout sooner so they get 64 * updated with a new full TTL. 65 * Type NS does not get this, because it must not be refreshed from the 66 * child domain, but keep counting down properly. 67 * @param pside: if from parentside discovered NS, so that its NS is okay 68 * in a prefetch situation to be updated (without becoming sticky). 69 * @param qrep: update rrsets here if cache is better 70 * @param region: for qrep allocs. 71 * @param qstarttime: time when delegations were looked up, this is perhaps 72 * earlier than the time in now. The time is used to determine if RRsets 73 * of type NS have expired, so that they can only be updated using 74 * lookups of delegation points that did not use them, since they had 75 * expired then. 76 */ 77 static void 78 store_rrsets(struct module_env* env, struct reply_info* rep, time_t now, 79 time_t leeway, int pside, struct reply_info* qrep, 80 struct regional* region, time_t qstarttime) 81 { 82 size_t i; 83 time_t ttl, min_ttl = rep->ttl; 84 /* see if rrset already exists in cache, if not insert it. */ 85 for(i=0; i<rep->rrset_count; i++) { 86 rep->ref[i].key = rep->rrsets[i]; 87 rep->ref[i].id = rep->rrsets[i]->id; 88 /* update ref if it was in the cache */ 89 switch(rrset_cache_update(env->rrset_cache, &rep->ref[i], 90 env->alloc, ((ntohs(rep->ref[i].key->rk.type)== 91 LDNS_RR_TYPE_NS && !pside)?qstarttime:now + leeway))) { 92 case 0: /* ref unchanged, item inserted */ 93 break; 94 case 2: /* ref updated, cache is superior */ 95 if(region) { 96 struct ub_packed_rrset_key* ck; 97 lock_rw_rdlock(&rep->ref[i].key->entry.lock); 98 /* if deleted rrset, do not copy it */ 99 if(rep->ref[i].key->id == 0) 100 ck = NULL; 101 else ck = packed_rrset_copy_region( 102 rep->ref[i].key, region, now); 103 lock_rw_unlock(&rep->ref[i].key->entry.lock); 104 if(ck) { 105 /* use cached copy if memory allows */ 106 qrep->rrsets[i] = ck; 107 } 108 } 109 /* no break: also copy key item */ 110 /* the line below is matched by gcc regex and silences 111 * the fallthrough warning */ 112 /* fallthrough */ 113 case 1: /* ref updated, item inserted */ 114 rep->rrsets[i] = rep->ref[i].key; 115 } 116 /* if ref was updated make sure the message ttl is updated to 117 * the minimum of the current rrsets. */ 118 ttl = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)->ttl; 119 if(ttl < min_ttl) min_ttl = ttl; 120 } 121 if(min_ttl < rep->ttl) { 122 rep->ttl = min_ttl; 123 rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl); 124 rep->serve_expired_ttl = rep->ttl + SERVE_EXPIRED_TTL; 125 } 126 } 127 128 /** delete message from message cache */ 129 void 130 msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen, 131 uint16_t qtype, uint16_t qclass, uint16_t flags) 132 { 133 struct query_info k; 134 hashvalue_type h; 135 136 k.qname = qname; 137 k.qname_len = qnamelen; 138 k.qtype = qtype; 139 k.qclass = qclass; 140 k.local_alias = NULL; 141 h = query_info_hash(&k, flags); 142 slabhash_remove(env->msg_cache, h, &k); 143 } 144 145 void 146 dns_cache_store_msg(struct module_env* env, struct query_info* qinfo, 147 hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside, 148 struct reply_info* qrep, uint32_t flags, struct regional* region, 149 time_t qstarttime) 150 { 151 struct msgreply_entry* e; 152 time_t ttl = rep->ttl; 153 size_t i; 154 155 /* store RRsets */ 156 for(i=0; i<rep->rrset_count; i++) { 157 rep->ref[i].key = rep->rrsets[i]; 158 rep->ref[i].id = rep->rrsets[i]->id; 159 } 160 161 /* there was a reply_info_sortref(rep) here but it seems to be 162 * unnecessary, because the cache gets locked per rrset. */ 163 reply_info_set_ttls(rep, *env->now); 164 store_rrsets(env, rep, *env->now, leeway, pside, qrep, region, 165 qstarttime); 166 if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) { 167 /* we do not store the message, but we did store the RRs, 168 * which could be useful for delegation information */ 169 verbose(VERB_ALGO, "TTL 0: dropped msg from cache"); 170 reply_info_delete(rep, NULL); 171 /* if the message is in the cache, remove that msg, 172 * so that the TTL 0 response can be returned for future 173 * responses (i.e. don't get answered from 174 * cache, but instead go to recursion to get this TTL0 175 * response). 176 * Possible messages that could be in the cache: 177 * - SERVFAIL 178 * - NXDOMAIN 179 * - NODATA 180 * - an older record that is expired 181 * - an older record that did not yet expire */ 182 msg_cache_remove(env, qinfo->qname, qinfo->qname_len, 183 qinfo->qtype, qinfo->qclass, flags); 184 return; 185 } 186 187 /* store msg in the cache */ 188 reply_info_sortref(rep); 189 if(!(e = query_info_entrysetup(qinfo, rep, hash))) { 190 log_err("store_msg: malloc failed"); 191 return; 192 } 193 slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc); 194 } 195 196 /** see if an rrset is expired above the qname, return upper qname. */ 197 static int 198 rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen, 199 uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop, 200 size_t expiretoplen) 201 { 202 struct ub_packed_rrset_key *rrset; 203 uint8_t lablen; 204 205 while(*qnamelen > 0) { 206 /* look one label higher */ 207 lablen = **qname; 208 *qname += lablen + 1; 209 *qnamelen -= lablen + 1; 210 if(*qnamelen <= 0) 211 break; 212 213 /* looks up with a time of 0, to see expired entries */ 214 if((rrset = rrset_cache_lookup(env->rrset_cache, *qname, 215 *qnamelen, searchtype, qclass, 0, 0, 0))) { 216 struct packed_rrset_data* data = 217 (struct packed_rrset_data*)rrset->entry.data; 218 if(now > data->ttl) { 219 /* it is expired, this is not wanted */ 220 lock_rw_unlock(&rrset->entry.lock); 221 log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass); 222 return 1; 223 } 224 /* it is not expired, continue looking */ 225 lock_rw_unlock(&rrset->entry.lock); 226 } 227 228 /* do not look above the expiretop. */ 229 if(expiretop && *qnamelen == expiretoplen && 230 query_dname_compare(*qname, expiretop)==0) 231 break; 232 } 233 return 0; 234 } 235 236 /** find closest NS or DNAME and returns the rrset (locked) */ 237 static struct ub_packed_rrset_key* 238 find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen, 239 uint16_t qclass, time_t now, uint16_t searchtype, int stripfront, 240 int noexpiredabove, uint8_t* expiretop, size_t expiretoplen) 241 { 242 struct ub_packed_rrset_key *rrset; 243 uint8_t lablen; 244 245 if(stripfront) { 246 /* strip off so that DNAMEs have strict subdomain match */ 247 lablen = *qname; 248 qname += lablen + 1; 249 qnamelen -= lablen + 1; 250 } 251 252 /* snip off front part of qname until the type is found */ 253 while(qnamelen > 0) { 254 if((rrset = rrset_cache_lookup(env->rrset_cache, qname, 255 qnamelen, searchtype, qclass, 0, now, 0))) { 256 uint8_t* origqname = qname; 257 size_t origqnamelen = qnamelen; 258 if(!noexpiredabove) 259 return rrset; 260 /* if expiretop set, do not look above it, but 261 * qname is equal, so the just found result is also 262 * the nonexpired above part. */ 263 if(expiretop && qnamelen == expiretoplen && 264 query_dname_compare(qname, expiretop)==0) 265 return rrset; 266 /* check for expiry, but we have to let go of the rrset 267 * for the lock ordering */ 268 lock_rw_unlock(&rrset->entry.lock); 269 /* the expired_above function always takes off one 270 * label (if qnamelen>0) and returns the final qname 271 * where it searched, so we can continue from there 272 * turning the O N*N search into O N. */ 273 if(!rrset_expired_above(env, &qname, &qnamelen, 274 searchtype, qclass, now, expiretop, 275 expiretoplen)) { 276 /* we want to return rrset, but it may be 277 * gone from cache, if so, just loop like 278 * it was not in the cache in the first place. 279 */ 280 if((rrset = rrset_cache_lookup(env-> 281 rrset_cache, origqname, origqnamelen, 282 searchtype, qclass, 0, now, 0))) { 283 return rrset; 284 } 285 } 286 log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass); 287 continue; 288 } 289 290 /* snip off front label */ 291 lablen = *qname; 292 qname += lablen + 1; 293 qnamelen -= lablen + 1; 294 } 295 return NULL; 296 } 297 298 /** add addr to additional section */ 299 static void 300 addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region, 301 struct dns_msg* msg, time_t now) 302 { 303 if((msg->rep->rrsets[msg->rep->rrset_count] = 304 packed_rrset_copy_region(rrset, region, now))) { 305 msg->rep->ar_numrrsets++; 306 msg->rep->rrset_count++; 307 } 308 } 309 310 /** lookup message in message cache */ 311 struct msgreply_entry* 312 msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen, 313 uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr) 314 { 315 struct lruhash_entry* e; 316 struct query_info k; 317 hashvalue_type h; 318 319 k.qname = qname; 320 k.qname_len = qnamelen; 321 k.qtype = qtype; 322 k.qclass = qclass; 323 k.local_alias = NULL; 324 h = query_info_hash(&k, flags); 325 e = slabhash_lookup(env->msg_cache, h, &k, wr); 326 327 if(!e) return NULL; 328 if( now > ((struct reply_info*)e->data)->ttl ) { 329 lock_rw_unlock(&e->lock); 330 return NULL; 331 } 332 return (struct msgreply_entry*)e->key; 333 } 334 335 /** find and add A and AAAA records for nameservers in delegpt */ 336 static int 337 find_add_addrs(struct module_env* env, uint16_t qclass, 338 struct regional* region, struct delegpt* dp, time_t now, 339 struct dns_msg** msg) 340 { 341 struct delegpt_ns* ns; 342 struct msgreply_entry* neg; 343 struct ub_packed_rrset_key* akey; 344 for(ns = dp->nslist; ns; ns = ns->next) { 345 akey = rrset_cache_lookup(env->rrset_cache, ns->name, 346 ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); 347 if(akey) { 348 if(!delegpt_add_rrset_A(dp, region, akey, 0, NULL)) { 349 lock_rw_unlock(&akey->entry.lock); 350 return 0; 351 } 352 if(msg) 353 addr_to_additional(akey, region, *msg, now); 354 lock_rw_unlock(&akey->entry.lock); 355 } else { 356 /* BIT_CD on false because delegpt lookup does 357 * not use dns64 translation */ 358 neg = msg_cache_lookup(env, ns->name, ns->namelen, 359 LDNS_RR_TYPE_A, qclass, 0, now, 0); 360 if(neg) { 361 delegpt_add_neg_msg(dp, neg); 362 lock_rw_unlock(&neg->entry.lock); 363 } 364 } 365 akey = rrset_cache_lookup(env->rrset_cache, ns->name, 366 ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); 367 if(akey) { 368 if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, NULL)) { 369 lock_rw_unlock(&akey->entry.lock); 370 return 0; 371 } 372 if(msg) 373 addr_to_additional(akey, region, *msg, now); 374 lock_rw_unlock(&akey->entry.lock); 375 } else { 376 /* BIT_CD on false because delegpt lookup does 377 * not use dns64 translation */ 378 neg = msg_cache_lookup(env, ns->name, ns->namelen, 379 LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); 380 if(neg) { 381 delegpt_add_neg_msg(dp, neg); 382 lock_rw_unlock(&neg->entry.lock); 383 } 384 } 385 } 386 return 1; 387 } 388 389 /** find and add A and AAAA records for missing nameservers in delegpt */ 390 int 391 cache_fill_missing(struct module_env* env, uint16_t qclass, 392 struct regional* region, struct delegpt* dp) 393 { 394 struct delegpt_ns* ns; 395 struct msgreply_entry* neg; 396 struct ub_packed_rrset_key* akey; 397 time_t now = *env->now; 398 for(ns = dp->nslist; ns; ns = ns->next) { 399 if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX) 400 continue; 401 ns->cache_lookup_count++; 402 akey = rrset_cache_lookup(env->rrset_cache, ns->name, 403 ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0); 404 if(akey) { 405 if(!delegpt_add_rrset_A(dp, region, akey, ns->lame, 406 NULL)) { 407 lock_rw_unlock(&akey->entry.lock); 408 return 0; 409 } 410 log_nametypeclass(VERB_ALGO, "found in cache", 411 ns->name, LDNS_RR_TYPE_A, qclass); 412 lock_rw_unlock(&akey->entry.lock); 413 } else { 414 /* BIT_CD on false because delegpt lookup does 415 * not use dns64 translation */ 416 neg = msg_cache_lookup(env, ns->name, ns->namelen, 417 LDNS_RR_TYPE_A, qclass, 0, now, 0); 418 if(neg) { 419 delegpt_add_neg_msg(dp, neg); 420 lock_rw_unlock(&neg->entry.lock); 421 } 422 } 423 akey = rrset_cache_lookup(env->rrset_cache, ns->name, 424 ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); 425 if(akey) { 426 if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame, 427 NULL)) { 428 lock_rw_unlock(&akey->entry.lock); 429 return 0; 430 } 431 log_nametypeclass(VERB_ALGO, "found in cache", 432 ns->name, LDNS_RR_TYPE_AAAA, qclass); 433 lock_rw_unlock(&akey->entry.lock); 434 } else { 435 /* BIT_CD on false because delegpt lookup does 436 * not use dns64 translation */ 437 neg = msg_cache_lookup(env, ns->name, ns->namelen, 438 LDNS_RR_TYPE_AAAA, qclass, 0, now, 0); 439 if(neg) { 440 delegpt_add_neg_msg(dp, neg); 441 lock_rw_unlock(&neg->entry.lock); 442 } 443 } 444 } 445 return 1; 446 } 447 448 /** find and add DS or NSEC to delegation msg */ 449 static void 450 find_add_ds(struct module_env* env, struct regional* region, 451 struct dns_msg* msg, struct delegpt* dp, time_t now) 452 { 453 /* Lookup the DS or NSEC at the delegation point. */ 454 struct ub_packed_rrset_key* rrset = rrset_cache_lookup( 455 env->rrset_cache, dp->name, dp->namelen, LDNS_RR_TYPE_DS, 456 msg->qinfo.qclass, 0, now, 0); 457 if(!rrset) { 458 /* NOTE: this won't work for alternate NSEC schemes 459 * (opt-in, NSEC3) */ 460 rrset = rrset_cache_lookup(env->rrset_cache, dp->name, 461 dp->namelen, LDNS_RR_TYPE_NSEC, msg->qinfo.qclass, 462 0, now, 0); 463 /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used. 464 * since this is a referral, we need the NSEC at the parent 465 * side of the zone cut, not the NSEC at apex side. */ 466 if(rrset && nsec_has_type(rrset, LDNS_RR_TYPE_DS)) { 467 lock_rw_unlock(&rrset->entry.lock); 468 rrset = NULL; /* discard wrong NSEC */ 469 } 470 } 471 if(rrset) { 472 /* add it to auth section. This is the second rrset. */ 473 if((msg->rep->rrsets[msg->rep->rrset_count] = 474 packed_rrset_copy_region(rrset, region, now))) { 475 msg->rep->ns_numrrsets++; 476 msg->rep->rrset_count++; 477 } 478 lock_rw_unlock(&rrset->entry.lock); 479 } 480 } 481 482 struct dns_msg* 483 dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, 484 uint16_t qclass, struct regional* region, size_t capacity) 485 { 486 struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, 487 sizeof(struct dns_msg)); 488 if(!msg) 489 return NULL; 490 msg->qinfo.qname = regional_alloc_init(region, qname, qnamelen); 491 if(!msg->qinfo.qname) 492 return NULL; 493 msg->qinfo.qname_len = qnamelen; 494 msg->qinfo.qtype = qtype; 495 msg->qinfo.qclass = qclass; 496 msg->qinfo.local_alias = NULL; 497 /* non-packed reply_info, because it needs to grow the array */ 498 msg->rep = (struct reply_info*)regional_alloc_zero(region, 499 sizeof(struct reply_info)-sizeof(struct rrset_ref)); 500 if(!msg->rep) 501 return NULL; 502 if(capacity > RR_COUNT_MAX) 503 return NULL; /* integer overflow protection */ 504 msg->rep->flags = BIT_QR; /* with QR, no AA */ 505 msg->rep->qdcount = 1; 506 msg->rep->reason_bogus = LDNS_EDE_NONE; 507 msg->rep->rrsets = (struct ub_packed_rrset_key**) 508 regional_alloc(region, 509 capacity*sizeof(struct ub_packed_rrset_key*)); 510 if(!msg->rep->rrsets) 511 return NULL; 512 return msg; 513 } 514 515 int 516 dns_msg_authadd(struct dns_msg* msg, struct regional* region, 517 struct ub_packed_rrset_key* rrset, time_t now) 518 { 519 if(!(msg->rep->rrsets[msg->rep->rrset_count++] = 520 packed_rrset_copy_region(rrset, region, now))) 521 return 0; 522 msg->rep->ns_numrrsets++; 523 return 1; 524 } 525 526 int 527 dns_msg_ansadd(struct dns_msg* msg, struct regional* region, 528 struct ub_packed_rrset_key* rrset, time_t now) 529 { 530 if(!(msg->rep->rrsets[msg->rep->rrset_count++] = 531 packed_rrset_copy_region(rrset, region, now))) 532 return 0; 533 msg->rep->an_numrrsets++; 534 return 1; 535 } 536 537 struct delegpt* 538 dns_cache_find_delegation(struct module_env* env, uint8_t* qname, 539 size_t qnamelen, uint16_t qtype, uint16_t qclass, 540 struct regional* region, struct dns_msg** msg, time_t now, 541 int noexpiredabove, uint8_t* expiretop, size_t expiretoplen) 542 { 543 /* try to find closest NS rrset */ 544 struct ub_packed_rrset_key* nskey; 545 struct packed_rrset_data* nsdata; 546 struct delegpt* dp; 547 548 nskey = find_closest_of_type(env, qname, qnamelen, qclass, now, 549 LDNS_RR_TYPE_NS, 0, noexpiredabove, expiretop, expiretoplen); 550 if(!nskey) /* hope the caller has hints to prime or something */ 551 return NULL; 552 nsdata = (struct packed_rrset_data*)nskey->entry.data; 553 /* got the NS key, create delegation point */ 554 dp = delegpt_create(region); 555 if(!dp || !delegpt_set_name(dp, region, nskey->rk.dname)) { 556 lock_rw_unlock(&nskey->entry.lock); 557 log_err("find_delegation: out of memory"); 558 return NULL; 559 } 560 /* create referral message */ 561 if(msg) { 562 /* allocate the array to as much as we could need: 563 * NS rrset + DS/NSEC rrset + 564 * A rrset for every NS RR 565 * AAAA rrset for every NS RR 566 */ 567 *msg = dns_msg_create(qname, qnamelen, qtype, qclass, region, 568 2 + nsdata->count*2); 569 if(!*msg || !dns_msg_authadd(*msg, region, nskey, now)) { 570 lock_rw_unlock(&nskey->entry.lock); 571 log_err("find_delegation: out of memory"); 572 return NULL; 573 } 574 } 575 if(!delegpt_rrset_add_ns(dp, region, nskey, 0)) 576 log_err("find_delegation: addns out of memory"); 577 lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/ 578 /* find and add DS/NSEC (if any) */ 579 if(msg) 580 find_add_ds(env, region, *msg, dp, now); 581 /* find and add A entries */ 582 if(!find_add_addrs(env, qclass, region, dp, now, msg)) 583 log_err("find_delegation: addrs out of memory"); 584 return dp; 585 } 586 587 /** allocate dns_msg from query_info and reply_info */ 588 static struct dns_msg* 589 gen_dns_msg(struct regional* region, struct query_info* q, size_t num) 590 { 591 struct dns_msg* msg = (struct dns_msg*)regional_alloc(region, 592 sizeof(struct dns_msg)); 593 if(!msg) 594 return NULL; 595 memcpy(&msg->qinfo, q, sizeof(struct query_info)); 596 msg->qinfo.qname = regional_alloc_init(region, q->qname, q->qname_len); 597 if(!msg->qinfo.qname) 598 return NULL; 599 /* allocate replyinfo struct and rrset key array separately */ 600 msg->rep = (struct reply_info*)regional_alloc(region, 601 sizeof(struct reply_info) - sizeof(struct rrset_ref)); 602 if(!msg->rep) 603 return NULL; 604 msg->rep->reason_bogus = LDNS_EDE_NONE; 605 msg->rep->reason_bogus_str = NULL; 606 if(num > RR_COUNT_MAX) 607 return NULL; /* integer overflow protection */ 608 msg->rep->rrsets = (struct ub_packed_rrset_key**) 609 regional_alloc(region, 610 num * sizeof(struct ub_packed_rrset_key*)); 611 if(!msg->rep->rrsets) 612 return NULL; 613 return msg; 614 } 615 616 struct dns_msg* 617 tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, 618 struct regional* region, time_t now, int allow_expired, 619 struct regional* scratch) 620 { 621 struct dns_msg* msg; 622 size_t i; 623 int is_expired = 0; 624 time_t now_control = now; 625 if(now > r->ttl) { 626 /* Check if we are allowed to serve expired */ 627 if(allow_expired) { 628 if(env->cfg->serve_expired_ttl && 629 r->serve_expired_ttl < now) { 630 return NULL; 631 } 632 /* Ignore expired failure answers */ 633 if(FLAGS_GET_RCODE(r->flags) != 634 LDNS_RCODE_NOERROR && 635 FLAGS_GET_RCODE(r->flags) != 636 LDNS_RCODE_NXDOMAIN && 637 FLAGS_GET_RCODE(r->flags) != 638 LDNS_RCODE_YXDOMAIN) 639 return 0; 640 } else { 641 return NULL; 642 } 643 /* Change the current time so we can pass the below TTL checks when 644 * serving expired data. */ 645 now_control = r->ttl - env->cfg->serve_expired_reply_ttl; 646 is_expired = 1; 647 } 648 649 msg = gen_dns_msg(region, q, r->rrset_count); 650 if(!msg) return NULL; 651 msg->rep->flags = r->flags; 652 msg->rep->qdcount = r->qdcount; 653 msg->rep->ttl = is_expired 654 ?SERVE_EXPIRED_REPLY_TTL 655 :r->ttl - now; 656 if(r->prefetch_ttl > now) 657 msg->rep->prefetch_ttl = r->prefetch_ttl - now; 658 else 659 msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); 660 msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; 661 msg->rep->security = r->security; 662 msg->rep->an_numrrsets = r->an_numrrsets; 663 msg->rep->ns_numrrsets = r->ns_numrrsets; 664 msg->rep->ar_numrrsets = r->ar_numrrsets; 665 msg->rep->rrset_count = r->rrset_count; 666 msg->rep->authoritative = r->authoritative; 667 msg->rep->reason_bogus = r->reason_bogus; 668 if(r->reason_bogus_str) { 669 msg->rep->reason_bogus_str = regional_strdup(region, r->reason_bogus_str); 670 } 671 672 if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) { 673 return NULL; 674 } 675 if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons( 676 LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons( 677 LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) { 678 /* cname chain is now invalid, reconstruct msg */ 679 rrset_array_unlock(r->ref, r->rrset_count); 680 return NULL; 681 } 682 if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) { 683 /* message rrsets have changed status, revalidate */ 684 rrset_array_unlock(r->ref, r->rrset_count); 685 return NULL; 686 } 687 for(i=0; i<msg->rep->rrset_count; i++) { 688 msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], 689 region, now); 690 if(!msg->rep->rrsets[i]) { 691 rrset_array_unlock(r->ref, r->rrset_count); 692 return NULL; 693 } 694 } 695 if(env) 696 rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref, 697 r->rrset_count); 698 else 699 rrset_array_unlock(r->ref, r->rrset_count); 700 return msg; 701 } 702 703 struct dns_msg* 704 dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region) 705 { 706 size_t i; 707 struct dns_msg* res = NULL; 708 res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count); 709 if(!res) return NULL; 710 *res->rep = *origin->rep; 711 if(origin->rep->reason_bogus_str) { 712 res->rep->reason_bogus_str = regional_strdup(region, 713 origin->rep->reason_bogus_str); 714 } 715 for(i=0; i<res->rep->rrset_count; i++) { 716 res->rep->rrsets[i] = packed_rrset_copy_region( 717 origin->rep->rrsets[i], region, 0); 718 if(!res->rep->rrsets[i]) { 719 return NULL; 720 } 721 } 722 return res; 723 } 724 725 /** synthesize RRset-only response from cached RRset item */ 726 static struct dns_msg* 727 rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region, 728 time_t now, struct query_info* q) 729 { 730 struct dns_msg* msg; 731 struct packed_rrset_data* d = (struct packed_rrset_data*) 732 rrset->entry.data; 733 if(now > d->ttl) 734 return NULL; 735 msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */ 736 if(!msg) 737 return NULL; 738 msg->rep->flags = BIT_QR; /* reply, no AA, no error */ 739 msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ 740 msg->rep->qdcount = 1; 741 msg->rep->ttl = d->ttl - now; 742 msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); 743 msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; 744 msg->rep->security = sec_status_unchecked; 745 msg->rep->an_numrrsets = 1; 746 msg->rep->ns_numrrsets = 0; 747 msg->rep->ar_numrrsets = 0; 748 msg->rep->rrset_count = 1; 749 msg->rep->reason_bogus = LDNS_EDE_NONE; 750 msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); 751 if(!msg->rep->rrsets[0]) /* copy CNAME */ 752 return NULL; 753 return msg; 754 } 755 756 /** synthesize DNAME+CNAME response from cached DNAME item */ 757 static struct dns_msg* 758 synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, 759 time_t now, struct query_info* q, enum sec_status* sec_status) 760 { 761 struct dns_msg* msg; 762 struct ub_packed_rrset_key* ck; 763 struct packed_rrset_data* newd, *d = (struct packed_rrset_data*) 764 rrset->entry.data; 765 uint8_t* newname, *dtarg = NULL; 766 size_t newlen, dtarglen; 767 if(now > d->ttl) 768 return NULL; 769 /* only allow validated (with DNSSEC) DNAMEs used from cache 770 * for insecure DNAMEs, query again. */ 771 *sec_status = d->security; 772 /* return sec status, so the status of the CNAME can be checked 773 * by the calling routine. */ 774 msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */ 775 if(!msg) 776 return NULL; 777 msg->rep->flags = BIT_QR; /* reply, no AA, no error */ 778 msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */ 779 msg->rep->qdcount = 1; 780 msg->rep->ttl = d->ttl - now; 781 msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); 782 msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; 783 msg->rep->security = sec_status_unchecked; 784 msg->rep->an_numrrsets = 1; 785 msg->rep->ns_numrrsets = 0; 786 msg->rep->ar_numrrsets = 0; 787 msg->rep->rrset_count = 1; 788 msg->rep->reason_bogus = LDNS_EDE_NONE; 789 msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now); 790 if(!msg->rep->rrsets[0]) /* copy DNAME */ 791 return NULL; 792 /* synth CNAME rrset */ 793 get_cname_target(rrset, &dtarg, &dtarglen); 794 if(!dtarg) 795 return NULL; 796 newlen = q->qname_len + dtarglen - rrset->rk.dname_len; 797 if(newlen > LDNS_MAX_DOMAINLEN) { 798 msg->rep->flags |= LDNS_RCODE_YXDOMAIN; 799 return msg; 800 } 801 newname = (uint8_t*)regional_alloc(region, newlen); 802 if(!newname) 803 return NULL; 804 /* new name is concatenation of qname front (without DNAME owner) 805 * and DNAME target name */ 806 memcpy(newname, q->qname, q->qname_len-rrset->rk.dname_len); 807 memmove(newname+(q->qname_len-rrset->rk.dname_len), dtarg, dtarglen); 808 /* create rest of CNAME rrset */ 809 ck = (struct ub_packed_rrset_key*)regional_alloc(region, 810 sizeof(struct ub_packed_rrset_key)); 811 if(!ck) 812 return NULL; 813 memset(&ck->entry, 0, sizeof(ck->entry)); 814 msg->rep->rrsets[1] = ck; 815 ck->entry.key = ck; 816 ck->rk.type = htons(LDNS_RR_TYPE_CNAME); 817 ck->rk.rrset_class = rrset->rk.rrset_class; 818 ck->rk.flags = 0; 819 ck->rk.dname = regional_alloc_init(region, q->qname, q->qname_len); 820 if(!ck->rk.dname) 821 return NULL; 822 ck->rk.dname_len = q->qname_len; 823 ck->entry.hash = rrset_key_hash(&ck->rk); 824 newd = (struct packed_rrset_data*)regional_alloc_zero(region, 825 sizeof(struct packed_rrset_data) + sizeof(size_t) + 826 sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t) 827 + newlen); 828 if(!newd) 829 return NULL; 830 ck->entry.data = newd; 831 newd->ttl = d->ttl - now; /* RFC6672: synth CNAME TTL == DNAME TTL */ 832 newd->count = 1; 833 newd->rrsig_count = 0; 834 newd->trust = rrset_trust_ans_noAA; 835 newd->rr_len = (size_t*)((uint8_t*)newd + 836 sizeof(struct packed_rrset_data)); 837 newd->rr_len[0] = newlen + sizeof(uint16_t); 838 packed_rrset_ptr_fixup(newd); 839 newd->rr_ttl[0] = newd->ttl; 840 msg->rep->ttl = newd->ttl; 841 msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(newd->ttl); 842 msg->rep->serve_expired_ttl = newd->ttl + SERVE_EXPIRED_TTL; 843 sldns_write_uint16(newd->rr_data[0], newlen); 844 memmove(newd->rr_data[0] + sizeof(uint16_t), newname, newlen); 845 msg->rep->an_numrrsets ++; 846 msg->rep->rrset_count ++; 847 return msg; 848 } 849 850 /** Fill TYPE_ANY response with some data from cache */ 851 static struct dns_msg* 852 fill_any(struct module_env* env, 853 uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, 854 struct regional* region) 855 { 856 time_t now = *env->now; 857 struct dns_msg* msg = NULL; 858 uint16_t lookup[] = {LDNS_RR_TYPE_A, LDNS_RR_TYPE_AAAA, 859 LDNS_RR_TYPE_MX, LDNS_RR_TYPE_SOA, LDNS_RR_TYPE_NS, 860 LDNS_RR_TYPE_DNAME, 0}; 861 int i, num=6; /* number of RR types to look up */ 862 log_assert(lookup[num] == 0); 863 864 if(env->cfg->deny_any) { 865 /* return empty message */ 866 msg = dns_msg_create(qname, qnamelen, qtype, qclass, 867 region, 0); 868 if(!msg) { 869 return NULL; 870 } 871 /* set NOTIMPL for RFC 8482 */ 872 msg->rep->flags |= LDNS_RCODE_NOTIMPL; 873 msg->rep->security = sec_status_indeterminate; 874 return msg; 875 } 876 877 for(i=0; i<num; i++) { 878 /* look up this RR for inclusion in type ANY response */ 879 struct ub_packed_rrset_key* rrset = rrset_cache_lookup( 880 env->rrset_cache, qname, qnamelen, lookup[i], 881 qclass, 0, now, 0); 882 struct packed_rrset_data *d; 883 if(!rrset) 884 continue; 885 886 /* only if rrset from answer section */ 887 d = (struct packed_rrset_data*)rrset->entry.data; 888 if(d->trust == rrset_trust_add_noAA || 889 d->trust == rrset_trust_auth_noAA || 890 d->trust == rrset_trust_add_AA || 891 d->trust == rrset_trust_auth_AA) { 892 lock_rw_unlock(&rrset->entry.lock); 893 continue; 894 } 895 896 /* create msg if none */ 897 if(!msg) { 898 msg = dns_msg_create(qname, qnamelen, qtype, qclass, 899 region, (size_t)(num-i)); 900 if(!msg) { 901 lock_rw_unlock(&rrset->entry.lock); 902 return NULL; 903 } 904 } 905 906 /* add RRset to response */ 907 if(!dns_msg_ansadd(msg, region, rrset, now)) { 908 lock_rw_unlock(&rrset->entry.lock); 909 return NULL; 910 } 911 lock_rw_unlock(&rrset->entry.lock); 912 } 913 return msg; 914 } 915 916 struct dns_msg* 917 dns_cache_lookup(struct module_env* env, 918 uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, 919 uint16_t flags, struct regional* region, struct regional* scratch, 920 int no_partial, uint8_t* dpname, size_t dpnamelen) 921 { 922 struct lruhash_entry* e; 923 struct query_info k; 924 hashvalue_type h; 925 time_t now = *env->now; 926 struct ub_packed_rrset_key* rrset; 927 928 /* lookup first, this has both NXdomains and ANSWER responses */ 929 k.qname = qname; 930 k.qname_len = qnamelen; 931 k.qtype = qtype; 932 k.qclass = qclass; 933 k.local_alias = NULL; 934 h = query_info_hash(&k, flags); 935 e = slabhash_lookup(env->msg_cache, h, &k, 0); 936 if(e) { 937 struct msgreply_entry* key = (struct msgreply_entry*)e->key; 938 struct reply_info* data = (struct reply_info*)e->data; 939 struct dns_msg* msg = tomsg(env, &key->key, data, region, now, 0, 940 scratch); 941 if(msg) { 942 lock_rw_unlock(&e->lock); 943 return msg; 944 } 945 /* could be msg==NULL; due to TTL or not all rrsets available */ 946 lock_rw_unlock(&e->lock); 947 } 948 949 /* see if a DNAME exists. Checked for first, to enforce that DNAMEs 950 * are more important, the CNAME is resynthesized and thus 951 * consistent with the DNAME */ 952 if(!no_partial && 953 (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now, 954 LDNS_RR_TYPE_DNAME, 1, 0, NULL, 0))) { 955 /* synthesize a DNAME+CNAME message based on this */ 956 enum sec_status sec_status = sec_status_unchecked; 957 struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k, 958 &sec_status); 959 if(msg) { 960 struct ub_packed_rrset_key* cname_rrset; 961 lock_rw_unlock(&rrset->entry.lock); 962 /* now, after unlocking the DNAME rrset lock, 963 * check the sec_status, and see if we need to look 964 * up the CNAME record associated before it can 965 * be used */ 966 /* normally, only secure DNAMEs allowed from cache*/ 967 if(sec_status == sec_status_secure) 968 return msg; 969 /* but if we have a CNAME cached with this name, then we 970 * have previously already allowed this name to pass. 971 * the next cache lookup is going to fetch that CNAME itself, 972 * but it is better to have the (unsigned)DNAME + CNAME in 973 * that case */ 974 cname_rrset = rrset_cache_lookup( 975 env->rrset_cache, qname, qnamelen, 976 LDNS_RR_TYPE_CNAME, qclass, 0, now, 0); 977 if(cname_rrset) { 978 /* CNAME already synthesized by 979 * synth_dname_msg routine, so we can 980 * straight up return the msg */ 981 lock_rw_unlock(&cname_rrset->entry.lock); 982 return msg; 983 } 984 } else { 985 lock_rw_unlock(&rrset->entry.lock); 986 } 987 } 988 989 /* see if we have CNAME for this domain, 990 * but not for DS records (which are part of the parent) */ 991 if(!no_partial && qtype != LDNS_RR_TYPE_DS && 992 (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, 993 LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) { 994 uint8_t* wc = NULL; 995 size_t wl; 996 /* if the rrset is not a wildcard expansion, with wcname */ 997 /* because, if we return that CNAME rrset on its own, it is 998 * missing the NSEC or NSEC3 proof */ 999 if(!(val_rrset_wildcard(rrset, &wc, &wl) && wc != NULL)) { 1000 struct dns_msg* msg = rrset_msg(rrset, region, now, &k); 1001 if(msg) { 1002 lock_rw_unlock(&rrset->entry.lock); 1003 return msg; 1004 } 1005 } 1006 lock_rw_unlock(&rrset->entry.lock); 1007 } 1008 1009 /* construct DS, DNSKEY messages from rrset cache. */ 1010 if((qtype == LDNS_RR_TYPE_DS || qtype == LDNS_RR_TYPE_DNSKEY) && 1011 (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, 1012 qtype, qclass, 0, now, 0))) { 1013 /* if the rrset is from the additional section, and the 1014 * signatures have fallen off, then do not synthesize a msg 1015 * instead, allow a full query for signed results to happen. 1016 * Forego all rrset data from additional section, because 1017 * some signatures may not be present and cause validation 1018 * failure. 1019 */ 1020 struct packed_rrset_data *d = (struct packed_rrset_data*) 1021 rrset->entry.data; 1022 if(d->trust != rrset_trust_add_noAA && 1023 d->trust != rrset_trust_add_AA && 1024 (qtype == LDNS_RR_TYPE_DS || 1025 (d->trust != rrset_trust_auth_noAA 1026 && d->trust != rrset_trust_auth_AA) )) { 1027 struct dns_msg* msg = rrset_msg(rrset, region, now, &k); 1028 if(msg) { 1029 lock_rw_unlock(&rrset->entry.lock); 1030 return msg; 1031 } 1032 } 1033 lock_rw_unlock(&rrset->entry.lock); 1034 } 1035 1036 /* stop downwards cache search on NXDOMAIN. 1037 * Empty nonterminals are NOERROR, so an NXDOMAIN for foo 1038 * means bla.foo also does not exist. The DNSSEC proofs are 1039 * the same. We search upwards for NXDOMAINs. */ 1040 if(env->cfg->harden_below_nxdomain) { 1041 while(!dname_is_root(k.qname)) { 1042 if(dpname && dpnamelen 1043 && !dname_subdomain_c(k.qname, dpname)) 1044 break; /* no synth nxdomain above the stub */ 1045 dname_remove_label(&k.qname, &k.qname_len); 1046 h = query_info_hash(&k, flags); 1047 e = slabhash_lookup(env->msg_cache, h, &k, 0); 1048 if(!e && k.qtype != LDNS_RR_TYPE_A && 1049 env->cfg->qname_minimisation) { 1050 k.qtype = LDNS_RR_TYPE_A; 1051 h = query_info_hash(&k, flags); 1052 e = slabhash_lookup(env->msg_cache, h, &k, 0); 1053 } 1054 if(e) { 1055 struct reply_info* data = (struct reply_info*)e->data; 1056 struct dns_msg* msg; 1057 if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN 1058 && data->security == sec_status_secure 1059 && (data->an_numrrsets == 0 || 1060 ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME) 1061 && (msg=tomsg(env, &k, data, region, now, 0, scratch))) { 1062 lock_rw_unlock(&e->lock); 1063 msg->qinfo.qname=qname; 1064 msg->qinfo.qname_len=qnamelen; 1065 /* check that DNSSEC really works out */ 1066 msg->rep->security = sec_status_unchecked; 1067 iter_scrub_nxdomain(msg); 1068 return msg; 1069 } 1070 lock_rw_unlock(&e->lock); 1071 } 1072 k.qtype = qtype; 1073 } 1074 } 1075 1076 /* fill common RR types for ANY response to avoid requery */ 1077 if(qtype == LDNS_RR_TYPE_ANY) { 1078 return fill_any(env, qname, qnamelen, qtype, qclass, region); 1079 } 1080 1081 return NULL; 1082 } 1083 1084 int 1085 dns_cache_store(struct module_env* env, struct query_info* msgqinf, 1086 struct reply_info* msgrep, int is_referral, time_t leeway, int pside, 1087 struct regional* region, uint32_t flags, time_t qstarttime) 1088 { 1089 struct reply_info* rep = NULL; 1090 /* alloc, malloc properly (not in region, like msg is) */ 1091 rep = reply_info_copy(msgrep, env->alloc, NULL); 1092 if(!rep) 1093 return 0; 1094 /* ttl must be relative ;i.e. 0..86400 not time(0)+86400. 1095 * the env->now is added to message and RRsets in this routine. */ 1096 /* the leeway is used to invalidate other rrsets earlier */ 1097 if(is_referral) { 1098 /* store rrsets */ 1099 struct rrset_ref ref; 1100 size_t i; 1101 for(i=0; i<rep->rrset_count; i++) { 1102 packed_rrset_ttl_add((struct packed_rrset_data*) 1103 rep->rrsets[i]->entry.data, *env->now); 1104 ref.key = rep->rrsets[i]; 1105 ref.id = rep->rrsets[i]->id; 1106 /*ignore ret: it was in the cache, ref updated */ 1107 /* no leeway for typeNS */ 1108 (void)rrset_cache_update(env->rrset_cache, &ref, 1109 env->alloc, 1110 ((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS 1111 && !pside) ? qstarttime:*env->now + leeway)); 1112 } 1113 reply_info_delete(rep, NULL); 1114 return 1; 1115 } else { 1116 /* store msg, and rrsets */ 1117 struct query_info qinf; 1118 hashvalue_type h; 1119 1120 qinf = *msgqinf; 1121 qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len); 1122 if(!qinf.qname) { 1123 reply_info_parsedelete(rep, env->alloc); 1124 return 0; 1125 } 1126 /* fixup flags to be sensible for a reply based on the cache */ 1127 /* this module means that RA is available. It is an answer QR. 1128 * Not AA from cache. Not CD in cache (depends on client bit). */ 1129 rep->flags |= (BIT_RA | BIT_QR); 1130 rep->flags &= ~(BIT_AA | BIT_CD); 1131 h = query_info_hash(&qinf, (uint16_t)flags); 1132 dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep, 1133 flags, region, qstarttime); 1134 /* qname is used inside query_info_entrysetup, and set to 1135 * NULL. If it has not been used, free it. free(0) is safe. */ 1136 free(qinf.qname); 1137 } 1138 return 1; 1139 } 1140 1141 int 1142 dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo, 1143 time_t adjust, uint16_t flags) 1144 { 1145 struct msgreply_entry* msg; 1146 msg = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len, 1147 qinfo->qtype, qinfo->qclass, flags, *env->now, 1); 1148 if(msg) { 1149 struct reply_info* rep = (struct reply_info*)msg->entry.data; 1150 if(rep) { 1151 rep->prefetch_ttl += adjust; 1152 lock_rw_unlock(&msg->entry.lock); 1153 return 1; 1154 } 1155 lock_rw_unlock(&msg->entry.lock); 1156 } 1157 return 0; 1158 } 1159