]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/services/cache/dns.c
4692744a15ddf5fd13fd1967b96942e4b843d732
2 * services/cache/dns.c - Cache services for DNS using msg and rrset caches.
4 * Copyright (c) 2007, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
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.
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.
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.
39 * This file contains the DNS cache.
42 #include "iterator/iter_delegpt.h"
43 #include "validator/val_nsec.h"
44 #include "services/cache/dns.h"
45 #include "services/cache/rrset.h"
46 #include "util/data/msgreply.h"
47 #include "util/data/packed_rrset.h"
48 #include "util/data/dname.h"
49 #include "util/module.h"
50 #include "util/net_help.h"
51 #include "util/regional.h"
52 #include "util/config_file.h"
53 #include "ldns/sbuffer.h"
55 /** store rrsets in the rrset cache.
56 * @param env: module environment with caches.
57 * @param rep: contains list of rrsets to store.
58 * @param now: current time.
59 * @param leeway: during prefetch how much leeway to update TTLs.
60 * This makes rrsets (other than type NS) timeout sooner so they get
61 * updated with a new full TTL.
62 * Type NS does not get this, because it must not be refreshed from the
63 * child domain, but keep counting down properly.
64 * @param pside: if from parentside discovered NS, so that its NS is okay
65 * in a prefetch situation to be updated (without becoming sticky).
66 * @param qrep: update rrsets here if cache is better
67 * @param region: for qrep allocs.
70 store_rrsets(struct module_env
* env
, struct reply_info
* rep
, time_t now
,
71 time_t leeway
, int pside
, struct reply_info
* qrep
,
72 struct regional
* region
)
75 /* see if rrset already exists in cache, if not insert it. */
76 for(i
=0; i
<rep
->rrset_count
; i
++) {
77 rep
->ref
[i
].key
= rep
->rrsets
[i
];
78 rep
->ref
[i
].id
= rep
->rrsets
[i
]->id
;
79 /* update ref if it was in the cache */
80 switch(rrset_cache_update(env
->rrset_cache
, &rep
->ref
[i
],
81 env
->alloc
, now
+ ((ntohs(rep
->ref
[i
].key
->rk
.type
)==
82 LDNS_RR_TYPE_NS
&& !pside
)?0:leeway
))) {
83 case 0: /* ref unchanged, item inserted */
85 case 2: /* ref updated, cache is superior */
87 struct ub_packed_rrset_key
* ck
;
88 lock_rw_rdlock(&rep
->ref
[i
].key
->entry
.lock
);
89 /* if deleted rrset, do not copy it */
90 if(rep
->ref
[i
].key
->id
== 0)
92 else ck
= packed_rrset_copy_region(
93 rep
->ref
[i
].key
, region
, now
);
94 lock_rw_unlock(&rep
->ref
[i
].key
->entry
.lock
);
96 /* use cached copy if memory allows */
100 /* no break: also copy key item */
101 case 1: /* ref updated, item inserted */
102 rep
->rrsets
[i
] = rep
->ref
[i
].key
;
108 dns_cache_store_msg(struct module_env
* env
, struct query_info
* qinfo
,
109 hashvalue_t hash
, struct reply_info
* rep
, time_t leeway
, int pside
,
110 struct reply_info
* qrep
, struct regional
* region
)
112 struct msgreply_entry
* e
;
113 time_t ttl
= rep
->ttl
;
117 for(i
=0; i
<rep
->rrset_count
; i
++) {
118 rep
->ref
[i
].key
= rep
->rrsets
[i
];
119 rep
->ref
[i
].id
= rep
->rrsets
[i
]->id
;
122 /* there was a reply_info_sortref(rep) here but it seems to be
123 * unnecessary, because the cache gets locked per rrset. */
124 reply_info_set_ttls(rep
, *env
->now
);
125 store_rrsets(env
, rep
, *env
->now
, leeway
, pside
, qrep
, region
);
127 /* we do not store the message, but we did store the RRs,
128 * which could be useful for delegation information */
129 verbose(VERB_ALGO
, "TTL 0: dropped msg from cache");
134 /* store msg in the cache */
135 reply_info_sortref(rep
);
136 if(!(e
= query_info_entrysetup(qinfo
, rep
, hash
))) {
137 log_err("store_msg: malloc failed");
140 slabhash_insert(env
->msg_cache
, hash
, &e
->entry
, rep
, env
->alloc
);
143 /** find closest NS or DNAME and returns the rrset (locked) */
144 static struct ub_packed_rrset_key
*
145 find_closest_of_type(struct module_env
* env
, uint8_t* qname
, size_t qnamelen
,
146 uint16_t qclass
, time_t now
, uint16_t searchtype
, int stripfront
)
148 struct ub_packed_rrset_key
*rrset
;
152 /* strip off so that DNAMEs have strict subdomain match */
155 qnamelen
-= lablen
+ 1;
158 /* snip off front part of qname until the type is found */
159 while(qnamelen
> 0) {
160 if((rrset
= rrset_cache_lookup(env
->rrset_cache
, qname
,
161 qnamelen
, searchtype
, qclass
, 0, now
, 0)))
164 /* snip off front label */
167 qnamelen
-= lablen
+ 1;
172 /** add addr to additional section */
174 addr_to_additional(struct ub_packed_rrset_key
* rrset
, struct regional
* region
,
175 struct dns_msg
* msg
, time_t now
)
177 if((msg
->rep
->rrsets
[msg
->rep
->rrset_count
] =
178 packed_rrset_copy_region(rrset
, region
, now
))) {
179 msg
->rep
->ar_numrrsets
++;
180 msg
->rep
->rrset_count
++;
184 /** lookup message in message cache */
185 static struct msgreply_entry
*
186 msg_cache_lookup(struct module_env
* env
, uint8_t* qname
, size_t qnamelen
,
187 uint16_t qtype
, uint16_t qclass
, uint16_t flags
, time_t now
, int wr
)
189 struct lruhash_entry
* e
;
194 k
.qname_len
= qnamelen
;
197 h
= query_info_hash(&k
, flags
);
198 e
= slabhash_lookup(env
->msg_cache
, h
, &k
, wr
);
201 if( now
> ((struct reply_info
*)e
->data
)->ttl
) {
202 lock_rw_unlock(&e
->lock
);
205 return (struct msgreply_entry
*)e
->key
;
208 /** find and add A and AAAA records for nameservers in delegpt */
210 find_add_addrs(struct module_env
* env
, uint16_t qclass
,
211 struct regional
* region
, struct delegpt
* dp
, time_t now
,
212 struct dns_msg
** msg
)
214 struct delegpt_ns
* ns
;
215 struct msgreply_entry
* neg
;
216 struct ub_packed_rrset_key
* akey
;
217 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
218 akey
= rrset_cache_lookup(env
->rrset_cache
, ns
->name
,
219 ns
->namelen
, LDNS_RR_TYPE_A
, qclass
, 0, now
, 0);
221 if(!delegpt_add_rrset_A(dp
, region
, akey
, 0)) {
222 lock_rw_unlock(&akey
->entry
.lock
);
226 addr_to_additional(akey
, region
, *msg
, now
);
227 lock_rw_unlock(&akey
->entry
.lock
);
229 /* BIT_CD on false because delegpt lookup does
230 * not use dns64 translation */
231 neg
= msg_cache_lookup(env
, ns
->name
, ns
->namelen
,
232 LDNS_RR_TYPE_A
, qclass
, 0, now
, 0);
234 delegpt_add_neg_msg(dp
, neg
);
235 lock_rw_unlock(&neg
->entry
.lock
);
238 akey
= rrset_cache_lookup(env
->rrset_cache
, ns
->name
,
239 ns
->namelen
, LDNS_RR_TYPE_AAAA
, qclass
, 0, now
, 0);
241 if(!delegpt_add_rrset_AAAA(dp
, region
, akey
, 0)) {
242 lock_rw_unlock(&akey
->entry
.lock
);
246 addr_to_additional(akey
, region
, *msg
, now
);
247 lock_rw_unlock(&akey
->entry
.lock
);
249 /* BIT_CD on false because delegpt lookup does
250 * not use dns64 translation */
251 neg
= msg_cache_lookup(env
, ns
->name
, ns
->namelen
,
252 LDNS_RR_TYPE_AAAA
, qclass
, 0, now
, 0);
254 delegpt_add_neg_msg(dp
, neg
);
255 lock_rw_unlock(&neg
->entry
.lock
);
262 /** find and add A and AAAA records for missing nameservers in delegpt */
264 cache_fill_missing(struct module_env
* env
, uint16_t qclass
,
265 struct regional
* region
, struct delegpt
* dp
)
267 struct delegpt_ns
* ns
;
268 struct msgreply_entry
* neg
;
269 struct ub_packed_rrset_key
* akey
;
270 time_t now
= *env
->now
;
271 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
272 akey
= rrset_cache_lookup(env
->rrset_cache
, ns
->name
,
273 ns
->namelen
, LDNS_RR_TYPE_A
, qclass
, 0, now
, 0);
275 if(!delegpt_add_rrset_A(dp
, region
, akey
, ns
->lame
)) {
276 lock_rw_unlock(&akey
->entry
.lock
);
279 log_nametypeclass(VERB_ALGO
, "found in cache",
280 ns
->name
, LDNS_RR_TYPE_A
, qclass
);
281 lock_rw_unlock(&akey
->entry
.lock
);
283 /* BIT_CD on false because delegpt lookup does
284 * not use dns64 translation */
285 neg
= msg_cache_lookup(env
, ns
->name
, ns
->namelen
,
286 LDNS_RR_TYPE_A
, qclass
, 0, now
, 0);
288 delegpt_add_neg_msg(dp
, neg
);
289 lock_rw_unlock(&neg
->entry
.lock
);
292 akey
= rrset_cache_lookup(env
->rrset_cache
, ns
->name
,
293 ns
->namelen
, LDNS_RR_TYPE_AAAA
, qclass
, 0, now
, 0);
295 if(!delegpt_add_rrset_AAAA(dp
, region
, akey
, ns
->lame
)) {
296 lock_rw_unlock(&akey
->entry
.lock
);
299 log_nametypeclass(VERB_ALGO
, "found in cache",
300 ns
->name
, LDNS_RR_TYPE_AAAA
, qclass
);
301 lock_rw_unlock(&akey
->entry
.lock
);
303 /* BIT_CD on false because delegpt lookup does
304 * not use dns64 translation */
305 neg
= msg_cache_lookup(env
, ns
->name
, ns
->namelen
,
306 LDNS_RR_TYPE_AAAA
, qclass
, 0, now
, 0);
308 delegpt_add_neg_msg(dp
, neg
);
309 lock_rw_unlock(&neg
->entry
.lock
);
316 /** find and add DS or NSEC to delegation msg */
318 find_add_ds(struct module_env
* env
, struct regional
* region
,
319 struct dns_msg
* msg
, struct delegpt
* dp
, time_t now
)
321 /* Lookup the DS or NSEC at the delegation point. */
322 struct ub_packed_rrset_key
* rrset
= rrset_cache_lookup(
323 env
->rrset_cache
, dp
->name
, dp
->namelen
, LDNS_RR_TYPE_DS
,
324 msg
->qinfo
.qclass
, 0, now
, 0);
326 /* NOTE: this won't work for alternate NSEC schemes
328 rrset
= rrset_cache_lookup(env
->rrset_cache
, dp
->name
,
329 dp
->namelen
, LDNS_RR_TYPE_NSEC
, msg
->qinfo
.qclass
,
331 /* Note: the PACKED_RRSET_NSEC_AT_APEX flag is not used.
332 * since this is a referral, we need the NSEC at the parent
333 * side of the zone cut, not the NSEC at apex side. */
334 if(rrset
&& nsec_has_type(rrset
, LDNS_RR_TYPE_DS
)) {
335 lock_rw_unlock(&rrset
->entry
.lock
);
336 rrset
= NULL
; /* discard wrong NSEC */
340 /* add it to auth section. This is the second rrset. */
341 if((msg
->rep
->rrsets
[msg
->rep
->rrset_count
] =
342 packed_rrset_copy_region(rrset
, region
, now
))) {
343 msg
->rep
->ns_numrrsets
++;
344 msg
->rep
->rrset_count
++;
346 lock_rw_unlock(&rrset
->entry
.lock
);
351 dns_msg_create(uint8_t* qname
, size_t qnamelen
, uint16_t qtype
,
352 uint16_t qclass
, struct regional
* region
, size_t capacity
)
354 struct dns_msg
* msg
= (struct dns_msg
*)regional_alloc(region
,
355 sizeof(struct dns_msg
));
358 msg
->qinfo
.qname
= regional_alloc_init(region
, qname
, qnamelen
);
359 if(!msg
->qinfo
.qname
)
361 msg
->qinfo
.qname_len
= qnamelen
;
362 msg
->qinfo
.qtype
= qtype
;
363 msg
->qinfo
.qclass
= qclass
;
364 /* non-packed reply_info, because it needs to grow the array */
365 msg
->rep
= (struct reply_info
*)regional_alloc_zero(region
,
366 sizeof(struct reply_info
)-sizeof(struct rrset_ref
));
369 msg
->rep
->flags
= BIT_QR
; /* with QR, no AA */
370 msg
->rep
->qdcount
= 1;
371 msg
->rep
->rrsets
= (struct ub_packed_rrset_key
**)
372 regional_alloc(region
,
373 capacity
*sizeof(struct ub_packed_rrset_key
*));
374 if(!msg
->rep
->rrsets
)
380 dns_msg_authadd(struct dns_msg
* msg
, struct regional
* region
,
381 struct ub_packed_rrset_key
* rrset
, time_t now
)
383 if(!(msg
->rep
->rrsets
[msg
->rep
->rrset_count
++] =
384 packed_rrset_copy_region(rrset
, region
, now
)))
386 msg
->rep
->ns_numrrsets
++;
391 dns_cache_find_delegation(struct module_env
* env
, uint8_t* qname
,
392 size_t qnamelen
, uint16_t qtype
, uint16_t qclass
,
393 struct regional
* region
, struct dns_msg
** msg
, time_t now
)
395 /* try to find closest NS rrset */
396 struct ub_packed_rrset_key
* nskey
;
397 struct packed_rrset_data
* nsdata
;
400 nskey
= find_closest_of_type(env
, qname
, qnamelen
, qclass
, now
,
402 if(!nskey
) /* hope the caller has hints to prime or something */
404 nsdata
= (struct packed_rrset_data
*)nskey
->entry
.data
;
405 /* got the NS key, create delegation point */
406 dp
= delegpt_create(region
);
407 if(!dp
|| !delegpt_set_name(dp
, region
, nskey
->rk
.dname
)) {
408 lock_rw_unlock(&nskey
->entry
.lock
);
409 log_err("find_delegation: out of memory");
412 /* create referral message */
414 /* allocate the array to as much as we could need:
415 * NS rrset + DS/NSEC rrset +
416 * A rrset for every NS RR
417 * AAAA rrset for every NS RR
419 *msg
= dns_msg_create(qname
, qnamelen
, qtype
, qclass
, region
,
420 2 + nsdata
->count
*2);
421 if(!*msg
|| !dns_msg_authadd(*msg
, region
, nskey
, now
)) {
422 lock_rw_unlock(&nskey
->entry
.lock
);
423 log_err("find_delegation: out of memory");
427 if(!delegpt_rrset_add_ns(dp
, region
, nskey
, 0))
428 log_err("find_delegation: addns out of memory");
429 lock_rw_unlock(&nskey
->entry
.lock
); /* first unlock before next lookup*/
430 /* find and add DS/NSEC (if any) */
432 find_add_ds(env
, region
, *msg
, dp
, now
);
433 /* find and add A entries */
434 if(!find_add_addrs(env
, qclass
, region
, dp
, now
, msg
))
435 log_err("find_delegation: addrs out of memory");
439 /** allocate dns_msg from query_info and reply_info */
440 static struct dns_msg
*
441 gen_dns_msg(struct regional
* region
, struct query_info
* q
, size_t num
)
443 struct dns_msg
* msg
= (struct dns_msg
*)regional_alloc(region
,
444 sizeof(struct dns_msg
));
447 memcpy(&msg
->qinfo
, q
, sizeof(struct query_info
));
448 msg
->qinfo
.qname
= regional_alloc_init(region
, q
->qname
, q
->qname_len
);
449 if(!msg
->qinfo
.qname
)
451 /* allocate replyinfo struct and rrset key array separately */
452 msg
->rep
= (struct reply_info
*)regional_alloc(region
,
453 sizeof(struct reply_info
) - sizeof(struct rrset_ref
));
456 msg
->rep
->rrsets
= (struct ub_packed_rrset_key
**)
457 regional_alloc(region
,
458 num
* sizeof(struct ub_packed_rrset_key
*));
459 if(!msg
->rep
->rrsets
)
464 /** generate dns_msg from cached message */
465 static struct dns_msg
*
466 tomsg(struct module_env
* env
, struct query_info
* q
, struct reply_info
* r
,
467 struct regional
* region
, time_t now
, struct regional
* scratch
)
473 msg
= gen_dns_msg(region
, q
, r
->rrset_count
);
476 msg
->rep
->flags
= r
->flags
;
477 msg
->rep
->qdcount
= r
->qdcount
;
478 msg
->rep
->ttl
= r
->ttl
- now
;
479 if(r
->prefetch_ttl
> now
)
480 msg
->rep
->prefetch_ttl
= r
->prefetch_ttl
- now
;
481 else msg
->rep
->prefetch_ttl
= PREFETCH_TTL_CALC(msg
->rep
->ttl
);
482 msg
->rep
->security
= r
->security
;
483 msg
->rep
->an_numrrsets
= r
->an_numrrsets
;
484 msg
->rep
->ns_numrrsets
= r
->ns_numrrsets
;
485 msg
->rep
->ar_numrrsets
= r
->ar_numrrsets
;
486 msg
->rep
->rrset_count
= r
->rrset_count
;
487 msg
->rep
->authoritative
= r
->authoritative
;
488 if(!rrset_array_lock(r
->ref
, r
->rrset_count
, now
))
490 if(r
->an_numrrsets
> 0 && (r
->rrsets
[0]->rk
.type
== htons(
491 LDNS_RR_TYPE_CNAME
) || r
->rrsets
[0]->rk
.type
== htons(
492 LDNS_RR_TYPE_DNAME
)) && !reply_check_cname_chain(r
)) {
493 /* cname chain is now invalid, reconstruct msg */
494 rrset_array_unlock(r
->ref
, r
->rrset_count
);
497 if(r
->security
== sec_status_secure
&& !reply_all_rrsets_secure(r
)) {
498 /* message rrsets have changed status, revalidate */
499 rrset_array_unlock(r
->ref
, r
->rrset_count
);
502 for(i
=0; i
<msg
->rep
->rrset_count
; i
++) {
503 msg
->rep
->rrsets
[i
] = packed_rrset_copy_region(r
->rrsets
[i
],
505 if(!msg
->rep
->rrsets
[i
]) {
506 rrset_array_unlock(r
->ref
, r
->rrset_count
);
510 rrset_array_unlock_touch(env
->rrset_cache
, scratch
, r
->ref
,
515 /** synthesize RRset-only response from cached RRset item */
516 static struct dns_msg
*
517 rrset_msg(struct ub_packed_rrset_key
* rrset
, struct regional
* region
,
518 time_t now
, struct query_info
* q
)
521 struct packed_rrset_data
* d
= (struct packed_rrset_data
*)
525 msg
= gen_dns_msg(region
, q
, 1); /* only the CNAME (or other) RRset */
528 msg
->rep
->flags
= BIT_QR
; /* reply, no AA, no error */
529 msg
->rep
->authoritative
= 0; /* reply stored in cache can't be authoritative */
530 msg
->rep
->qdcount
= 1;
531 msg
->rep
->ttl
= d
->ttl
- now
;
532 msg
->rep
->prefetch_ttl
= PREFETCH_TTL_CALC(msg
->rep
->ttl
);
533 msg
->rep
->security
= sec_status_unchecked
;
534 msg
->rep
->an_numrrsets
= 1;
535 msg
->rep
->ns_numrrsets
= 0;
536 msg
->rep
->ar_numrrsets
= 0;
537 msg
->rep
->rrset_count
= 1;
538 msg
->rep
->rrsets
[0] = packed_rrset_copy_region(rrset
, region
, now
);
539 if(!msg
->rep
->rrsets
[0]) /* copy CNAME */
544 /** synthesize DNAME+CNAME response from cached DNAME item */
545 static struct dns_msg
*
546 synth_dname_msg(struct ub_packed_rrset_key
* rrset
, struct regional
* region
,
547 time_t now
, struct query_info
* q
)
550 struct ub_packed_rrset_key
* ck
;
551 struct packed_rrset_data
* newd
, *d
= (struct packed_rrset_data
*)
553 uint8_t* newname
, *dtarg
= NULL
;
554 size_t newlen
, dtarglen
;
557 /* only allow validated (with DNSSEC) DNAMEs used from cache
558 * for insecure DNAMEs, query again. */
559 if(d
->security
!= sec_status_secure
)
561 msg
= gen_dns_msg(region
, q
, 2); /* DNAME + CNAME RRset */
564 msg
->rep
->flags
= BIT_QR
; /* reply, no AA, no error */
565 msg
->rep
->authoritative
= 0; /* reply stored in cache can't be authoritative */
566 msg
->rep
->qdcount
= 1;
567 msg
->rep
->ttl
= d
->ttl
- now
;
568 msg
->rep
->prefetch_ttl
= PREFETCH_TTL_CALC(msg
->rep
->ttl
);
569 msg
->rep
->security
= sec_status_unchecked
;
570 msg
->rep
->an_numrrsets
= 1;
571 msg
->rep
->ns_numrrsets
= 0;
572 msg
->rep
->ar_numrrsets
= 0;
573 msg
->rep
->rrset_count
= 1;
574 msg
->rep
->rrsets
[0] = packed_rrset_copy_region(rrset
, region
, now
);
575 if(!msg
->rep
->rrsets
[0]) /* copy DNAME */
577 /* synth CNAME rrset */
578 get_cname_target(rrset
, &dtarg
, &dtarglen
);
581 newlen
= q
->qname_len
+ dtarglen
- rrset
->rk
.dname_len
;
582 if(newlen
> LDNS_MAX_DOMAINLEN
) {
583 msg
->rep
->flags
|= LDNS_RCODE_YXDOMAIN
;
586 newname
= (uint8_t*)regional_alloc(region
, newlen
);
589 /* new name is concatenation of qname front (without DNAME owner)
590 * and DNAME target name */
591 memcpy(newname
, q
->qname
, q
->qname_len
-rrset
->rk
.dname_len
);
592 memmove(newname
+(q
->qname_len
-rrset
->rk
.dname_len
), dtarg
, dtarglen
);
593 /* create rest of CNAME rrset */
594 ck
= (struct ub_packed_rrset_key
*)regional_alloc(region
,
595 sizeof(struct ub_packed_rrset_key
));
598 memset(&ck
->entry
, 0, sizeof(ck
->entry
));
599 msg
->rep
->rrsets
[1] = ck
;
601 ck
->rk
.type
= htons(LDNS_RR_TYPE_CNAME
);
602 ck
->rk
.rrset_class
= rrset
->rk
.rrset_class
;
604 ck
->rk
.dname
= regional_alloc_init(region
, q
->qname
, q
->qname_len
);
607 ck
->rk
.dname_len
= q
->qname_len
;
608 ck
->entry
.hash
= rrset_key_hash(&ck
->rk
);
609 newd
= (struct packed_rrset_data
*)regional_alloc_zero(region
,
610 sizeof(struct packed_rrset_data
) + sizeof(size_t) +
611 sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)
615 ck
->entry
.data
= newd
;
616 newd
->ttl
= 0; /* 0 for synthesized CNAME TTL */
618 newd
->rrsig_count
= 0;
619 newd
->trust
= rrset_trust_ans_noAA
;
620 newd
->rr_len
= (size_t*)((uint8_t*)newd
+
621 sizeof(struct packed_rrset_data
));
622 newd
->rr_len
[0] = newlen
+ sizeof(uint16_t);
623 packed_rrset_ptr_fixup(newd
);
624 newd
->rr_ttl
[0] = newd
->ttl
;
625 msg
->rep
->ttl
= newd
->ttl
;
626 msg
->rep
->prefetch_ttl
= PREFETCH_TTL_CALC(newd
->ttl
);
627 sldns_write_uint16(newd
->rr_data
[0], newlen
);
628 memmove(newd
->rr_data
[0] + sizeof(uint16_t), newname
, newlen
);
629 msg
->rep
->an_numrrsets
++;
630 msg
->rep
->rrset_count
++;
635 dns_cache_lookup(struct module_env
* env
,
636 uint8_t* qname
, size_t qnamelen
, uint16_t qtype
, uint16_t qclass
,
637 uint16_t flags
, struct regional
* region
, struct regional
* scratch
)
639 struct lruhash_entry
* e
;
642 time_t now
= *env
->now
;
643 struct ub_packed_rrset_key
* rrset
;
645 /* lookup first, this has both NXdomains and ANSWER responses */
647 k
.qname_len
= qnamelen
;
650 h
= query_info_hash(&k
, flags
);
651 e
= slabhash_lookup(env
->msg_cache
, h
, &k
, 0);
653 struct msgreply_entry
* key
= (struct msgreply_entry
*)e
->key
;
654 struct reply_info
* data
= (struct reply_info
*)e
->data
;
655 struct dns_msg
* msg
= tomsg(env
, &key
->key
, data
, region
, now
,
658 lock_rw_unlock(&e
->lock
);
661 /* could be msg==NULL; due to TTL or not all rrsets available */
662 lock_rw_unlock(&e
->lock
);
665 /* see if a DNAME exists. Checked for first, to enforce that DNAMEs
666 * are more important, the CNAME is resynthesized and thus
667 * consistent with the DNAME */
668 if( (rrset
=find_closest_of_type(env
, qname
, qnamelen
, qclass
, now
,
669 LDNS_RR_TYPE_DNAME
, 1))) {
670 /* synthesize a DNAME+CNAME message based on this */
671 struct dns_msg
* msg
= synth_dname_msg(rrset
, region
, now
, &k
);
673 lock_rw_unlock(&rrset
->entry
.lock
);
676 lock_rw_unlock(&rrset
->entry
.lock
);
679 /* see if we have CNAME for this domain,
680 * but not for DS records (which are part of the parent) */
681 if( qtype
!= LDNS_RR_TYPE_DS
&&
682 (rrset
=rrset_cache_lookup(env
->rrset_cache
, qname
, qnamelen
,
683 LDNS_RR_TYPE_CNAME
, qclass
, 0, now
, 0))) {
684 struct dns_msg
* msg
= rrset_msg(rrset
, region
, now
, &k
);
686 lock_rw_unlock(&rrset
->entry
.lock
);
689 lock_rw_unlock(&rrset
->entry
.lock
);
692 /* construct DS, DNSKEY, DLV messages from rrset cache. */
693 if((qtype
== LDNS_RR_TYPE_DS
|| qtype
== LDNS_RR_TYPE_DNSKEY
||
694 qtype
== LDNS_RR_TYPE_DLV
) &&
695 (rrset
=rrset_cache_lookup(env
->rrset_cache
, qname
, qnamelen
,
696 qtype
, qclass
, 0, now
, 0))) {
697 /* if the rrset is from the additional section, and the
698 * signatures have fallen off, then do not synthesize a msg
699 * instead, allow a full query for signed results to happen.
700 * Forego all rrset data from additional section, because
701 * some signatures may not be present and cause validation
704 struct packed_rrset_data
*d
= (struct packed_rrset_data
*)
706 if(d
->trust
!= rrset_trust_add_noAA
&&
707 d
->trust
!= rrset_trust_add_AA
&&
708 (qtype
== LDNS_RR_TYPE_DS
||
709 (d
->trust
!= rrset_trust_auth_noAA
710 && d
->trust
!= rrset_trust_auth_AA
) )) {
711 struct dns_msg
* msg
= rrset_msg(rrset
, region
, now
, &k
);
713 lock_rw_unlock(&rrset
->entry
.lock
);
717 lock_rw_unlock(&rrset
->entry
.lock
);
720 /* stop downwards cache search on NXDOMAIN.
721 * Empty nonterminals are NOERROR, so an NXDOMAIN for foo
722 * means bla.foo also does not exist. The DNSSEC proofs are
723 * the same. We search upwards for NXDOMAINs. */
724 if(env
->cfg
->harden_below_nxdomain
)
725 while(!dname_is_root(k
.qname
)) {
726 dname_remove_label(&k
.qname
, &k
.qname_len
);
727 h
= query_info_hash(&k
, flags
);
728 e
= slabhash_lookup(env
->msg_cache
, h
, &k
, 0);
730 struct reply_info
* data
= (struct reply_info
*)e
->data
;
732 if(FLAGS_GET_RCODE(data
->flags
) == LDNS_RCODE_NXDOMAIN
733 && data
->security
== sec_status_secure
734 && (msg
=tomsg(env
, &k
, data
, region
, now
, scratch
))){
735 lock_rw_unlock(&e
->lock
);
736 msg
->qinfo
.qname
=qname
;
737 msg
->qinfo
.qname_len
=qnamelen
;
738 /* check that DNSSEC really works out */
739 msg
->rep
->security
= sec_status_unchecked
;
742 lock_rw_unlock(&e
->lock
);
750 dns_cache_store(struct module_env
* env
, struct query_info
* msgqinf
,
751 struct reply_info
* msgrep
, int is_referral
, time_t leeway
, int pside
,
752 struct regional
* region
, uint16_t flags
)
754 struct reply_info
* rep
= NULL
;
755 /* alloc, malloc properly (not in region, like msg is) */
756 rep
= reply_info_copy(msgrep
, env
->alloc
, NULL
);
759 /* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
760 * the env->now is added to message and RRsets in this routine. */
761 /* the leeway is used to invalidate other rrsets earlier */
765 struct rrset_ref ref
;
767 for(i
=0; i
<rep
->rrset_count
; i
++) {
768 packed_rrset_ttl_add((struct packed_rrset_data
*)
769 rep
->rrsets
[i
]->entry
.data
, *env
->now
);
770 ref
.key
= rep
->rrsets
[i
];
771 ref
.id
= rep
->rrsets
[i
]->id
;
772 /*ignore ret: it was in the cache, ref updated */
773 /* no leeway for typeNS */
774 (void)rrset_cache_update(env
->rrset_cache
, &ref
,
775 env
->alloc
, *env
->now
+
776 ((ntohs(ref
.key
->rk
.type
)==LDNS_RR_TYPE_NS
777 && !pside
) ? 0:leeway
));
782 /* store msg, and rrsets */
783 struct query_info qinf
;
787 qinf
.qname
= memdup(msgqinf
->qname
, msgqinf
->qname_len
);
789 reply_info_parsedelete(rep
, env
->alloc
);
792 /* fixup flags to be sensible for a reply based on the cache */
793 /* this module means that RA is available. It is an answer QR.
794 * Not AA from cache. Not CD in cache (depends on client bit). */
795 rep
->flags
|= (BIT_RA
| BIT_QR
);
796 rep
->flags
&= ~(BIT_AA
| BIT_CD
);
797 h
= query_info_hash(&qinf
, flags
);
798 dns_cache_store_msg(env
, &qinf
, h
, rep
, leeway
, pside
, msgrep
,
800 /* qname is used inside query_info_entrysetup, and set to
801 * NULL. If it has not been used, free it. free(0) is safe. */
808 dns_cache_prefetch_adjust(struct module_env
* env
, struct query_info
* qinfo
,
809 time_t adjust
, uint16_t flags
)
811 struct msgreply_entry
* msg
;
812 msg
= msg_cache_lookup(env
, qinfo
->qname
, qinfo
->qname_len
,
813 qinfo
->qtype
, qinfo
->qclass
, flags
, *env
->now
, 1);
815 struct reply_info
* rep
= (struct reply_info
*)msg
->entry
.data
;
817 rep
->prefetch_ttl
+= adjust
;
818 lock_rw_unlock(&msg
->entry
.lock
);
821 lock_rw_unlock(&msg
->entry
.lock
);