]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/util/data/msgreply.c
2 * util/data/msgreply.c - store message and reply data.
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 a data structure to store a message and its reply.
43 #include "util/data/msgreply.h"
44 #include "util/storage/lookup3.h"
46 #include "util/alloc.h"
47 #include "util/netevent.h"
48 #include "util/net_help.h"
49 #include "util/data/dname.h"
50 #include "util/regional.h"
51 #include "util/data/msgparse.h"
52 #include "util/data/msgencode.h"
53 #include "ldns/sbuffer.h"
54 #include "ldns/wire2str.h"
56 /** MAX TTL default for messages and rrsets */
57 time_t MAX_TTL
= 3600 * 24 * 10; /* ten days */
58 /** MIN TTL default for messages and rrsets */
61 /** allocate qinfo, return 0 on error */
63 parse_create_qinfo(sldns_buffer
* pkt
, struct msg_parse
* msg
,
64 struct query_info
* qinf
, struct regional
* region
)
68 qinf
->qname
= (uint8_t*)regional_alloc(region
,
70 else qinf
->qname
= (uint8_t*)malloc(msg
->qname_len
);
71 if(!qinf
->qname
) return 0;
72 dname_pkt_copy(pkt
, qinf
->qname
, msg
->qname
);
73 } else qinf
->qname
= 0;
74 qinf
->qname_len
= msg
->qname_len
;
75 qinf
->qtype
= msg
->qtype
;
76 qinf
->qclass
= msg
->qclass
;
80 /** constructor for replyinfo */
82 construct_reply_info_base(struct regional
* region
, uint16_t flags
, size_t qd
,
83 time_t ttl
, time_t prettl
, size_t an
, size_t ns
, size_t ar
,
84 size_t total
, enum sec_status sec
)
86 struct reply_info
* rep
;
87 /* rrset_count-1 because the first ref is part of the struct. */
88 size_t s
= sizeof(struct reply_info
) - sizeof(struct rrset_ref
) +
89 sizeof(struct ub_packed_rrset_key
*) * total
;
91 rep
= (struct reply_info
*)regional_alloc(region
, s
);
92 else rep
= (struct reply_info
*)malloc(s
+
93 sizeof(struct rrset_ref
) * (total
));
99 rep
->prefetch_ttl
= prettl
;
100 rep
->an_numrrsets
= an
;
101 rep
->ns_numrrsets
= ns
;
102 rep
->ar_numrrsets
= ar
;
103 rep
->rrset_count
= total
;
105 rep
->authoritative
= 0;
106 /* array starts after the refs */
108 rep
->rrsets
= (struct ub_packed_rrset_key
**)&(rep
->ref
[0]);
109 else rep
->rrsets
= (struct ub_packed_rrset_key
**)&(rep
->ref
[total
]);
110 /* zero the arrays to assist cleanup in case of malloc failure */
111 memset( rep
->rrsets
, 0, sizeof(struct ub_packed_rrset_key
*) * total
);
113 memset( &rep
->ref
[0], 0, sizeof(struct rrset_ref
) * total
);
117 /** allocate replyinfo, return 0 on error */
119 parse_create_repinfo(struct msg_parse
* msg
, struct reply_info
** rep
,
120 struct regional
* region
)
122 *rep
= construct_reply_info_base(region
, msg
->flags
, msg
->qdcount
, 0,
123 0, msg
->an_rrsets
, msg
->ns_rrsets
, msg
->ar_rrsets
,
124 msg
->rrset_count
, sec_status_unchecked
);
130 /** allocate (special) rrset keys, return 0 on error */
132 repinfo_alloc_rrset_keys(struct reply_info
* rep
, struct alloc_cache
* alloc
,
133 struct regional
* region
)
136 for(i
=0; i
<rep
->rrset_count
; i
++) {
138 rep
->rrsets
[i
] = (struct ub_packed_rrset_key
*)
139 regional_alloc(region
,
140 sizeof(struct ub_packed_rrset_key
));
142 memset(rep
->rrsets
[i
], 0,
143 sizeof(struct ub_packed_rrset_key
));
144 rep
->rrsets
[i
]->entry
.key
= rep
->rrsets
[i
];
147 else rep
->rrsets
[i
] = alloc_special_obtain(alloc
);
150 rep
->rrsets
[i
]->entry
.data
= NULL
;
155 /** do the rdata copy */
157 rdata_copy(sldns_buffer
* pkt
, struct packed_rrset_data
* data
, uint8_t* to
,
158 struct rr_parse
* rr
, time_t* rr_ttl
, uint16_t type
)
161 const sldns_rr_descriptor
* desc
;
163 *rr_ttl
= sldns_read_uint32(rr
->ttl_data
);
164 /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */
165 if(*rr_ttl
& 0x80000000U
)
167 if(*rr_ttl
< MIN_TTL
)
169 if(*rr_ttl
< data
->ttl
)
172 if(rr
->outside_packet
) {
173 /* uncompressed already, only needs copy */
174 memmove(to
, rr
->ttl_data
+sizeof(uint32_t), rr
->size
);
178 sldns_buffer_set_position(pkt
, (size_t)
179 (rr
->ttl_data
- sldns_buffer_begin(pkt
) + sizeof(uint32_t)));
180 /* insert decompressed size into rdata len stored in memory */
181 /* -2 because rdatalen bytes are not included. */
182 pkt_len
= htons(rr
->size
- 2);
183 memmove(to
, &pkt_len
, sizeof(uint16_t));
185 /* read packet rdata len */
186 pkt_len
= sldns_buffer_read_u16(pkt
);
187 if(sldns_buffer_remaining(pkt
) < pkt_len
)
189 desc
= sldns_rr_descript(type
);
190 if(pkt_len
> 0 && desc
&& desc
->_dname_count
> 0) {
191 int count
= (int)desc
->_dname_count
;
195 /* decompress dnames. */
196 while(pkt_len
> 0 && count
) {
197 switch(desc
->_wireformat
[rdf
]) {
198 case LDNS_RDF_TYPE_DNAME
:
199 oldpos
= sldns_buffer_position(pkt
);
200 dname_pkt_copy(pkt
, to
,
201 sldns_buffer_current(pkt
));
202 to
+= pkt_dname_len(pkt
);
203 pkt_len
-= sldns_buffer_position(pkt
)-oldpos
;
207 case LDNS_RDF_TYPE_STR
:
208 len
= sldns_buffer_current(pkt
)[0] + 1;
211 len
= get_rdf_size(desc
->_wireformat
[rdf
]);
215 memmove(to
, sldns_buffer_current(pkt
), len
);
217 sldns_buffer_skip(pkt
, (ssize_t
)len
);
218 log_assert(len
<= pkt_len
);
224 /* copy remaining rdata */
226 memmove(to
, sldns_buffer_current(pkt
), pkt_len
);
231 /** copy over the data into packed rrset */
233 parse_rr_copy(sldns_buffer
* pkt
, struct rrset_parse
* pset
,
234 struct packed_rrset_data
* data
)
237 struct rr_parse
* rr
= pset
->rr_first
;
239 size_t total
= pset
->rr_count
+ pset
->rrsig_count
;
241 data
->count
= pset
->rr_count
;
242 data
->rrsig_count
= pset
->rrsig_count
;
243 data
->trust
= rrset_trust_none
;
244 data
->security
= sec_status_unchecked
;
245 /* layout: struct - rr_len - rr_data - rr_ttl - rdata - rrsig */
246 data
->rr_len
= (size_t*)((uint8_t*)data
+
247 sizeof(struct packed_rrset_data
));
248 data
->rr_data
= (uint8_t**)&(data
->rr_len
[total
]);
249 data
->rr_ttl
= (time_t*)&(data
->rr_data
[total
]);
250 nextrdata
= (uint8_t*)&(data
->rr_ttl
[total
]);
251 for(i
=0; i
<data
->count
; i
++) {
252 data
->rr_len
[i
] = rr
->size
;
253 data
->rr_data
[i
] = nextrdata
;
254 nextrdata
+= rr
->size
;
255 if(!rdata_copy(pkt
, data
, data
->rr_data
[i
], rr
,
256 &data
->rr_ttl
[i
], pset
->type
))
260 /* if rrsig, its rdata is at nextrdata */
261 rr
= pset
->rrsig_first
;
262 for(i
=data
->count
; i
<total
; i
++) {
263 data
->rr_len
[i
] = rr
->size
;
264 data
->rr_data
[i
] = nextrdata
;
265 nextrdata
+= rr
->size
;
266 if(!rdata_copy(pkt
, data
, data
->rr_data
[i
], rr
,
267 &data
->rr_ttl
[i
], LDNS_RR_TYPE_RRSIG
))
274 /** create rrset return 0 on failure */
276 parse_create_rrset(sldns_buffer
* pkt
, struct rrset_parse
* pset
,
277 struct packed_rrset_data
** data
, struct regional
* region
)
280 size_t s
= sizeof(struct packed_rrset_data
) +
281 (pset
->rr_count
+ pset
->rrsig_count
) *
282 (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) +
285 *data
= regional_alloc(region
, s
);
286 else *data
= malloc(s
);
289 /* copy & decompress */
290 if(!parse_rr_copy(pkt
, pset
, *data
)) {
291 if(!region
) free(*data
);
297 /** get trust value for rrset */
298 static enum rrset_trust
299 get_rrset_trust(struct msg_parse
* msg
, struct rrset_parse
* rrset
)
301 uint16_t AA
= msg
->flags
& BIT_AA
;
302 if(rrset
->section
== LDNS_SECTION_ANSWER
) {
304 /* RFC2181 says remainder of CNAME chain is nonauth*/
305 if(msg
->rrset_first
&&
306 msg
->rrset_first
->section
==LDNS_SECTION_ANSWER
307 && msg
->rrset_first
->type
==LDNS_RR_TYPE_CNAME
){
308 if(rrset
== msg
->rrset_first
)
309 return rrset_trust_ans_AA
;
310 else return rrset_trust_ans_noAA
;
312 if(msg
->rrset_first
&&
313 msg
->rrset_first
->section
==LDNS_SECTION_ANSWER
314 && msg
->rrset_first
->type
==LDNS_RR_TYPE_DNAME
){
315 if(rrset
== msg
->rrset_first
||
316 rrset
== msg
->rrset_first
->rrset_all_next
)
317 return rrset_trust_ans_AA
;
318 else return rrset_trust_ans_noAA
;
320 return rrset_trust_ans_AA
;
322 else return rrset_trust_ans_noAA
;
323 } else if(rrset
->section
== LDNS_SECTION_AUTHORITY
) {
324 if(AA
) return rrset_trust_auth_AA
;
325 else return rrset_trust_auth_noAA
;
328 if(AA
) return rrset_trust_add_AA
;
329 else return rrset_trust_add_noAA
;
332 return rrset_trust_none
;
336 parse_copy_decompress_rrset(sldns_buffer
* pkt
, struct msg_parse
* msg
,
337 struct rrset_parse
*pset
, struct regional
* region
,
338 struct ub_packed_rrset_key
* pk
)
340 struct packed_rrset_data
* data
;
341 pk
->rk
.flags
= pset
->flags
;
342 pk
->rk
.dname_len
= pset
->dname_len
;
344 pk
->rk
.dname
= (uint8_t*)regional_alloc(
345 region
, pset
->dname_len
);
347 (uint8_t*)malloc(pset
->dname_len
);
350 /** copy & decompress dname */
351 dname_pkt_copy(pkt
, pk
->rk
.dname
, pset
->dname
);
352 /** copy over type and class */
353 pk
->rk
.type
= htons(pset
->type
);
354 pk
->rk
.rrset_class
= pset
->rrset_class
;
355 /** read data part. */
356 if(!parse_create_rrset(pkt
, pset
, &data
, region
))
358 pk
->entry
.data
= (void*)data
;
359 pk
->entry
.key
= (void*)pk
;
360 pk
->entry
.hash
= pset
->hash
;
361 data
->trust
= get_rrset_trust(msg
, pset
);
366 * Copy and decompress rrs
367 * @param pkt: the packet for compression pointer resolution.
368 * @param msg: the parsed message
369 * @param rep: reply info to put rrs into.
370 * @param region: if not NULL, used for allocation.
371 * @return 0 on failure.
374 parse_copy_decompress(sldns_buffer
* pkt
, struct msg_parse
* msg
,
375 struct reply_info
* rep
, struct regional
* region
)
378 struct rrset_parse
*pset
= msg
->rrset_first
;
379 struct packed_rrset_data
* data
;
382 rep
->security
= sec_status_unchecked
;
383 if(rep
->rrset_count
== 0)
386 for(i
=0; i
<rep
->rrset_count
; i
++) {
387 if(!parse_copy_decompress_rrset(pkt
, msg
, pset
, region
,
390 data
= (struct packed_rrset_data
*)rep
->rrsets
[i
]->entry
.data
;
391 if(data
->ttl
< rep
->ttl
)
392 rep
->ttl
= data
->ttl
;
394 pset
= pset
->rrset_all_next
;
396 rep
->prefetch_ttl
= PREFETCH_TTL_CALC(rep
->ttl
);
401 parse_create_msg(sldns_buffer
* pkt
, struct msg_parse
* msg
,
402 struct alloc_cache
* alloc
, struct query_info
* qinf
,
403 struct reply_info
** rep
, struct regional
* region
)
405 log_assert(pkt
&& msg
);
406 if(!parse_create_qinfo(pkt
, msg
, qinf
, region
))
408 if(!parse_create_repinfo(msg
, rep
, region
))
410 if(!repinfo_alloc_rrset_keys(*rep
, alloc
, region
))
412 if(!parse_copy_decompress(pkt
, msg
, *rep
, region
))
417 int reply_info_parse(sldns_buffer
* pkt
, struct alloc_cache
* alloc
,
418 struct query_info
* qinf
, struct reply_info
** rep
,
419 struct regional
* region
, struct edns_data
* edns
)
421 /* use scratch pad region-allocator during parsing. */
422 struct msg_parse
* msg
;
427 if(!(msg
= regional_alloc(region
, sizeof(*msg
)))) {
428 return LDNS_RCODE_SERVFAIL
;
430 memset(msg
, 0, sizeof(*msg
));
432 sldns_buffer_set_position(pkt
, 0);
433 if((ret
= parse_packet(pkt
, msg
, region
)) != 0) {
436 if((ret
= parse_extract_edns(msg
, edns
)) != 0)
439 /* parse OK, allocate return structures */
440 /* this also performs dname decompression */
441 if(!parse_create_msg(pkt
, msg
, alloc
, qinf
, rep
, NULL
)) {
442 query_info_clear(qinf
);
443 reply_info_parsedelete(*rep
, alloc
);
445 return LDNS_RCODE_SERVFAIL
;
450 /** helper compare function to sort in lock order */
452 reply_info_sortref_cmp(const void* a
, const void* b
)
454 struct rrset_ref
* x
= (struct rrset_ref
*)a
;
455 struct rrset_ref
* y
= (struct rrset_ref
*)b
;
456 if(x
->key
< y
->key
) return -1;
457 if(x
->key
> y
->key
) return 1;
462 reply_info_sortref(struct reply_info
* rep
)
464 qsort(&rep
->ref
[0], rep
->rrset_count
, sizeof(struct rrset_ref
),
465 reply_info_sortref_cmp
);
469 reply_info_set_ttls(struct reply_info
* rep
, time_t timenow
)
473 rep
->prefetch_ttl
+= timenow
;
474 for(i
=0; i
<rep
->rrset_count
; i
++) {
475 struct packed_rrset_data
* data
= (struct packed_rrset_data
*)
476 rep
->ref
[i
].key
->entry
.data
;
477 if(i
>0 && rep
->ref
[i
].key
== rep
->ref
[i
-1].key
)
479 data
->ttl
+= timenow
;
480 for(j
=0; j
<data
->count
+ data
->rrsig_count
; j
++) {
481 data
->rr_ttl
[j
] += timenow
;
487 reply_info_parsedelete(struct reply_info
* rep
, struct alloc_cache
* alloc
)
492 /* no need to lock, since not shared in hashtables. */
493 for(i
=0; i
<rep
->rrset_count
; i
++) {
494 ub_packed_rrset_parsedelete(rep
->rrsets
[i
], alloc
);
500 query_info_parse(struct query_info
* m
, sldns_buffer
* query
)
502 uint8_t* q
= sldns_buffer_begin(query
);
503 /* minimum size: header + \0 + qtype + qclass */
504 if(sldns_buffer_limit(query
) < LDNS_HEADER_SIZE
+ 5)
506 if(LDNS_OPCODE_WIRE(q
) != LDNS_PACKET_QUERY
||
507 LDNS_QDCOUNT(q
) != 1 || sldns_buffer_position(query
) != 0)
509 sldns_buffer_skip(query
, LDNS_HEADER_SIZE
);
510 m
->qname
= sldns_buffer_current(query
);
511 if((m
->qname_len
= query_dname_len(query
)) == 0)
512 return 0; /* parse error */
513 if(sldns_buffer_remaining(query
) < 4)
514 return 0; /* need qtype, qclass */
515 m
->qtype
= sldns_buffer_read_u16(query
);
516 m
->qclass
= sldns_buffer_read_u16(query
);
520 /** tiny subroutine for msgreply_compare */
521 #define COMPARE_IT(x, y) \
522 if( (x) < (y) ) return -1; \
523 else if( (x) > (y) ) return +1; \
524 log_assert( (x) == (y) );
527 query_info_compare(void* m1
, void* m2
)
529 struct query_info
* msg1
= (struct query_info
*)m1
;
530 struct query_info
* msg2
= (struct query_info
*)m2
;
532 /* from most different to least different for speed */
533 COMPARE_IT(msg1
->qtype
, msg2
->qtype
);
534 if((mc
= query_dname_compare(msg1
->qname
, msg2
->qname
)) != 0)
536 log_assert(msg1
->qname_len
== msg2
->qname_len
);
537 COMPARE_IT(msg1
->qclass
, msg2
->qclass
);
543 query_info_clear(struct query_info
* m
)
550 msgreply_sizefunc(void* k
, void* d
)
552 struct msgreply_entry
* q
= (struct msgreply_entry
*)k
;
553 struct reply_info
* r
= (struct reply_info
*)d
;
554 size_t s
= sizeof(struct msgreply_entry
) + sizeof(struct reply_info
)
555 + q
->key
.qname_len
+ lock_get_mem(&q
->entry
.lock
)
556 - sizeof(struct rrset_ref
);
557 s
+= r
->rrset_count
* sizeof(struct rrset_ref
);
558 s
+= r
->rrset_count
* sizeof(struct ub_packed_rrset_key
*);
563 query_entry_delete(void *k
, void* ATTR_UNUSED(arg
))
565 struct msgreply_entry
* q
= (struct msgreply_entry
*)k
;
566 lock_rw_destroy(&q
->entry
.lock
);
567 query_info_clear(&q
->key
);
572 reply_info_delete(void* d
, void* ATTR_UNUSED(arg
))
574 struct reply_info
* r
= (struct reply_info
*)d
;
579 query_info_hash(struct query_info
*q
, uint16_t flags
)
581 hashvalue_t h
= 0xab;
582 h
= hashlittle(&q
->qtype
, sizeof(q
->qtype
), h
);
583 if(q
->qtype
== LDNS_RR_TYPE_AAAA
&& (flags
&BIT_CD
))
585 h
= hashlittle(&q
->qclass
, sizeof(q
->qclass
), h
);
586 h
= dname_query_hash(q
->qname
, h
);
590 struct msgreply_entry
*
591 query_info_entrysetup(struct query_info
* q
, struct reply_info
* r
,
594 struct msgreply_entry
* e
= (struct msgreply_entry
*)malloc(
595 sizeof(struct msgreply_entry
));
597 memcpy(&e
->key
, q
, sizeof(*q
));
601 lock_rw_init(&e
->entry
.lock
);
602 lock_protect(&e
->entry
.lock
, &e
->key
, sizeof(e
->key
));
603 lock_protect(&e
->entry
.lock
, &e
->entry
.hash
, sizeof(e
->entry
.hash
) +
604 sizeof(e
->entry
.key
) + sizeof(e
->entry
.data
));
605 lock_protect(&e
->entry
.lock
, e
->key
.qname
, e
->key
.qname_len
);
610 /** copy rrsets from replyinfo to dest replyinfo */
612 repinfo_copy_rrsets(struct reply_info
* dest
, struct reply_info
* from
,
613 struct regional
* region
)
616 struct packed_rrset_data
* fd
, *dd
;
617 struct ub_packed_rrset_key
* fk
, *dk
;
618 for(i
=0; i
<dest
->rrset_count
; i
++) {
619 fk
= from
->rrsets
[i
];
620 dk
= dest
->rrsets
[i
];
621 fd
= (struct packed_rrset_data
*)fk
->entry
.data
;
622 dk
->entry
.hash
= fk
->entry
.hash
;
626 dk
->rk
.dname
= (uint8_t*)regional_alloc_init(region
,
627 fk
->rk
.dname
, fk
->rk
.dname_len
);
629 dk
->rk
.dname
= (uint8_t*)memdup(fk
->rk
.dname
,
633 s
= packed_rrset_sizeof(fd
);
635 dd
= (struct packed_rrset_data
*)regional_alloc_init(
637 else dd
= (struct packed_rrset_data
*)memdup(fd
, s
);
640 packed_rrset_ptr_fixup(dd
);
641 dk
->entry
.data
= (void*)dd
;
647 reply_info_copy(struct reply_info
* rep
, struct alloc_cache
* alloc
,
648 struct regional
* region
)
650 struct reply_info
* cp
;
651 cp
= construct_reply_info_base(region
, rep
->flags
, rep
->qdcount
,
652 rep
->ttl
, rep
->prefetch_ttl
, rep
->an_numrrsets
,
653 rep
->ns_numrrsets
, rep
->ar_numrrsets
, rep
->rrset_count
,
657 /* allocate ub_key structures special or not */
658 if(!repinfo_alloc_rrset_keys(cp
, alloc
, region
)) {
660 reply_info_parsedelete(cp
, alloc
);
663 if(!repinfo_copy_rrsets(cp
, rep
, region
)) {
665 reply_info_parsedelete(cp
, alloc
);
672 reply_find_final_cname_target(struct query_info
* qinfo
, struct reply_info
* rep
)
674 uint8_t* sname
= qinfo
->qname
;
675 size_t snamelen
= qinfo
->qname_len
;
677 for(i
=0; i
<rep
->an_numrrsets
; i
++) {
678 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
679 /* follow CNAME chain (if any) */
680 if(ntohs(s
->rk
.type
) == LDNS_RR_TYPE_CNAME
&&
681 ntohs(s
->rk
.rrset_class
) == qinfo
->qclass
&&
682 snamelen
== s
->rk
.dname_len
&&
683 query_dname_compare(sname
, s
->rk
.dname
) == 0) {
684 get_cname_target(s
, &sname
, &snamelen
);
687 if(sname
!= qinfo
->qname
)
692 struct ub_packed_rrset_key
*
693 reply_find_answer_rrset(struct query_info
* qinfo
, struct reply_info
* rep
)
695 uint8_t* sname
= qinfo
->qname
;
696 size_t snamelen
= qinfo
->qname_len
;
698 for(i
=0; i
<rep
->an_numrrsets
; i
++) {
699 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
700 /* first match type, for query of qtype cname */
701 if(ntohs(s
->rk
.type
) == qinfo
->qtype
&&
702 ntohs(s
->rk
.rrset_class
) == qinfo
->qclass
&&
703 snamelen
== s
->rk
.dname_len
&&
704 query_dname_compare(sname
, s
->rk
.dname
) == 0) {
707 /* follow CNAME chain (if any) */
708 if(ntohs(s
->rk
.type
) == LDNS_RR_TYPE_CNAME
&&
709 ntohs(s
->rk
.rrset_class
) == qinfo
->qclass
&&
710 snamelen
== s
->rk
.dname_len
&&
711 query_dname_compare(sname
, s
->rk
.dname
) == 0) {
712 get_cname_target(s
, &sname
, &snamelen
);
718 struct ub_packed_rrset_key
* reply_find_rrset_section_an(struct reply_info
* rep
,
719 uint8_t* name
, size_t namelen
, uint16_t type
, uint16_t dclass
)
722 for(i
=0; i
<rep
->an_numrrsets
; i
++) {
723 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
724 if(ntohs(s
->rk
.type
) == type
&&
725 ntohs(s
->rk
.rrset_class
) == dclass
&&
726 namelen
== s
->rk
.dname_len
&&
727 query_dname_compare(name
, s
->rk
.dname
) == 0) {
734 struct ub_packed_rrset_key
* reply_find_rrset_section_ns(struct reply_info
* rep
,
735 uint8_t* name
, size_t namelen
, uint16_t type
, uint16_t dclass
)
738 for(i
=rep
->an_numrrsets
; i
<rep
->an_numrrsets
+rep
->ns_numrrsets
; i
++) {
739 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
740 if(ntohs(s
->rk
.type
) == type
&&
741 ntohs(s
->rk
.rrset_class
) == dclass
&&
742 namelen
== s
->rk
.dname_len
&&
743 query_dname_compare(name
, s
->rk
.dname
) == 0) {
750 struct ub_packed_rrset_key
* reply_find_rrset(struct reply_info
* rep
,
751 uint8_t* name
, size_t namelen
, uint16_t type
, uint16_t dclass
)
754 for(i
=0; i
<rep
->rrset_count
; i
++) {
755 struct ub_packed_rrset_key
* s
= rep
->rrsets
[i
];
756 if(ntohs(s
->rk
.type
) == type
&&
757 ntohs(s
->rk
.rrset_class
) == dclass
&&
758 namelen
== s
->rk
.dname_len
&&
759 query_dname_compare(name
, s
->rk
.dname
) == 0) {
767 log_dns_msg(const char* str
, struct query_info
* qinfo
, struct reply_info
* rep
)
769 /* not particularly fast but flexible, make wireformat and print */
770 sldns_buffer
* buf
= sldns_buffer_new(65535);
771 struct regional
* region
= regional_create();
772 if(!reply_info_encode(qinfo
, rep
, 0, rep
->flags
, buf
, 0,
774 log_info("%s: log_dns_msg: out of memory", str
);
776 char* s
= sldns_wire2str_pkt(sldns_buffer_begin(buf
),
777 sldns_buffer_limit(buf
));
779 log_info("%s: log_dns_msg: ldns tostr failed", str
);
781 log_info("%s %s", str
, s
);
785 sldns_buffer_free(buf
);
786 regional_destroy(region
);
790 log_query_info(enum verbosity_value v
, const char* str
,
791 struct query_info
* qinf
)
793 log_nametypeclass(v
, str
, qinf
->qname
, qinf
->qtype
, qinf
->qclass
);
797 reply_check_cname_chain(struct reply_info
* rep
)
799 /* check only answer section rrs for matching cname chain.
800 * the cache may return changed rdata, but owner names are untouched.*/
802 uint8_t* sname
= rep
->rrsets
[0]->rk
.dname
;
803 size_t snamelen
= rep
->rrsets
[0]->rk
.dname_len
;
804 for(i
=0; i
<rep
->an_numrrsets
; i
++) {
805 uint16_t t
= ntohs(rep
->rrsets
[i
]->rk
.type
);
806 if(t
== LDNS_RR_TYPE_DNAME
)
807 continue; /* skip dnames; note TTL 0 not cached */
808 /* verify that owner matches current sname */
809 if(query_dname_compare(sname
, rep
->rrsets
[i
]->rk
.dname
) != 0){
810 /* cname chain broken */
813 /* if this is a cname; move on */
814 if(t
== LDNS_RR_TYPE_CNAME
) {
815 get_cname_target(rep
->rrsets
[i
], &sname
, &snamelen
);
822 reply_all_rrsets_secure(struct reply_info
* rep
)
825 for(i
=0; i
<rep
->rrset_count
; i
++) {
826 if( ((struct packed_rrset_data
*)rep
->rrsets
[i
]->entry
.data
)
827 ->security
!= sec_status_secure
)