]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/iterator/iter_delegpt.c
2 * iterator/iter_delegpt.c - delegation point with NS and address information.
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 implements the Delegation Point. It contains a list of name servers
40 * and their addresses if known.
43 #include "iterator/iter_delegpt.h"
44 #include "services/cache/dns.h"
45 #include "util/regional.h"
46 #include "util/data/dname.h"
47 #include "util/data/packed_rrset.h"
48 #include "util/data/msgreply.h"
49 #include "util/net_help.h"
50 #include "ldns/rrdef.h"
51 #include "ldns/sbuffer.h"
54 delegpt_create(struct regional
* region
)
56 struct delegpt
* dp
=(struct delegpt
*)regional_alloc(
60 memset(dp
, 0, sizeof(*dp
));
64 struct delegpt
* delegpt_copy(struct delegpt
* dp
, struct regional
* region
)
66 struct delegpt
* copy
= delegpt_create(region
);
67 struct delegpt_ns
* ns
;
68 struct delegpt_addr
* a
;
71 if(!delegpt_set_name(copy
, region
, dp
->name
))
73 copy
->bogus
= dp
->bogus
;
74 copy
->has_parent_side_NS
= dp
->has_parent_side_NS
;
75 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
76 if(!delegpt_add_ns(copy
, region
, ns
->name
, ns
->lame
))
78 copy
->nslist
->resolved
= ns
->resolved
;
79 copy
->nslist
->got4
= ns
->got4
;
80 copy
->nslist
->got6
= ns
->got6
;
81 copy
->nslist
->done_pside4
= ns
->done_pside4
;
82 copy
->nslist
->done_pside6
= ns
->done_pside6
;
84 for(a
= dp
->target_list
; a
; a
= a
->next_target
) {
85 if(!delegpt_add_addr(copy
, region
, &a
->addr
, a
->addrlen
,
93 delegpt_set_name(struct delegpt
* dp
, struct regional
* region
, uint8_t* name
)
95 log_assert(!dp
->dp_type_mlc
);
96 dp
->namelabs
= dname_count_size_labels(name
, &dp
->namelen
);
97 dp
->name
= regional_alloc_init(region
, name
, dp
->namelen
);
102 delegpt_add_ns(struct delegpt
* dp
, struct regional
* region
, uint8_t* name
,
105 struct delegpt_ns
* ns
;
107 (void)dname_count_size_labels(name
, &len
);
108 log_assert(!dp
->dp_type_mlc
);
109 /* slow check for duplicates to avoid counting failures when
110 * adding the same server as a dependency twice */
111 if(delegpt_find_ns(dp
, name
, len
))
113 ns
= (struct delegpt_ns
*)regional_alloc(region
,
114 sizeof(struct delegpt_ns
));
117 ns
->next
= dp
->nslist
;
120 ns
->name
= regional_alloc_init(region
, name
, ns
->namelen
);
127 return ns
->name
!= 0;
131 delegpt_find_ns(struct delegpt
* dp
, uint8_t* name
, size_t namelen
)
133 struct delegpt_ns
* p
= dp
->nslist
;
135 if(namelen
== p
->namelen
&&
136 query_dname_compare(name
, p
->name
) == 0) {
145 delegpt_find_addr(struct delegpt
* dp
, struct sockaddr_storage
* addr
,
148 struct delegpt_addr
* p
= dp
->target_list
;
150 if(sockaddr_cmp_addr(addr
, addrlen
, &p
->addr
, p
->addrlen
)==0
151 && ((struct sockaddr_in
*)addr
)->sin_port
==
152 ((struct sockaddr_in
*)&p
->addr
)->sin_port
) {
161 delegpt_add_target(struct delegpt
* dp
, struct regional
* region
,
162 uint8_t* name
, size_t namelen
, struct sockaddr_storage
* addr
,
163 socklen_t addrlen
, uint8_t bogus
, uint8_t lame
)
165 struct delegpt_ns
* ns
= delegpt_find_ns(dp
, name
, namelen
);
166 log_assert(!dp
->dp_type_mlc
);
172 if(addr_is_ip6(addr
, addrlen
))
175 if(ns
->got4
&& ns
->got6
)
178 return delegpt_add_addr(dp
, region
, addr
, addrlen
, bogus
, lame
);
182 delegpt_add_addr(struct delegpt
* dp
, struct regional
* region
,
183 struct sockaddr_storage
* addr
, socklen_t addrlen
, uint8_t bogus
,
186 struct delegpt_addr
* a
;
187 log_assert(!dp
->dp_type_mlc
);
188 /* check for duplicates */
189 if((a
= delegpt_find_addr(dp
, addr
, addrlen
))) {
197 a
= (struct delegpt_addr
*)regional_alloc(region
,
198 sizeof(struct delegpt_addr
));
201 a
->next_target
= dp
->target_list
;
204 a
->next_usable
= dp
->usable_list
;
206 memcpy(&a
->addr
, addr
, addrlen
);
207 a
->addrlen
= addrlen
;
216 delegpt_count_ns(struct delegpt
* dp
, size_t* numns
, size_t* missing
)
218 struct delegpt_ns
* ns
;
221 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
229 delegpt_count_addr(struct delegpt
* dp
, size_t* numaddr
, size_t* numres
,
232 struct delegpt_addr
* a
;
236 for(a
= dp
->target_list
; a
; a
= a
->next_target
) {
239 for(a
= dp
->result_list
; a
; a
= a
->next_result
) {
242 for(a
= dp
->usable_list
; a
; a
= a
->next_usable
) {
247 void delegpt_log(enum verbosity_value v
, struct delegpt
* dp
)
249 char buf
[LDNS_MAX_DOMAINLEN
+1];
250 struct delegpt_ns
* ns
;
251 struct delegpt_addr
* a
;
252 size_t missing
=0, numns
=0, numaddr
=0, numres
=0, numavail
=0;
255 dname_str(dp
->name
, buf
);
256 if(dp
->nslist
== NULL
&& dp
->target_list
== NULL
) {
257 log_info("DelegationPoint<%s>: empty", buf
);
260 delegpt_count_ns(dp
, &numns
, &missing
);
261 delegpt_count_addr(dp
, &numaddr
, &numres
, &numavail
);
262 log_info("DelegationPoint<%s>: %u names (%u missing), "
263 "%u addrs (%u result, %u avail)%s",
264 buf
, (unsigned)numns
, (unsigned)missing
,
265 (unsigned)numaddr
, (unsigned)numres
, (unsigned)numavail
,
266 (dp
->has_parent_side_NS
?" parentNS":" cacheNS"));
267 if(verbosity
>= VERB_ALGO
) {
268 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
269 dname_str(ns
->name
, buf
);
270 log_info(" %s %s%s%s%s%s%s%s", buf
,
271 (ns
->resolved
?"*":""),
272 (ns
->got4
?" A":""), (ns
->got6
?" AAAA":""),
273 (dp
->bogus
?" BOGUS":""), (ns
->lame
?" PARENTSIDE":""),
274 (ns
->done_pside4
?" PSIDE_A":""),
275 (ns
->done_pside6
?" PSIDE_AAAA":""));
277 for(a
= dp
->target_list
; a
; a
= a
->next_target
) {
278 const char* str
= " ";
279 if(a
->bogus
&& a
->lame
) str
= " BOGUS ADDR_LAME ";
280 else if(a
->bogus
) str
= " BOGUS ";
281 else if(a
->lame
) str
= " ADDR_LAME ";
282 log_addr(VERB_ALGO
, str
, &a
->addr
, a
->addrlen
);
288 delegpt_add_unused_targets(struct delegpt
* dp
)
290 struct delegpt_addr
* usa
= dp
->usable_list
;
291 dp
->usable_list
= NULL
;
293 usa
->next_result
= dp
->result_list
;
294 dp
->result_list
= usa
;
295 usa
= usa
->next_usable
;
300 delegpt_count_targets(struct delegpt
* dp
)
302 struct delegpt_addr
* a
;
304 for(a
= dp
->target_list
; a
; a
= a
->next_target
)
310 delegpt_count_missing_targets(struct delegpt
* dp
)
312 struct delegpt_ns
* ns
;
314 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
)
320 /** find NS rrset in given list */
321 static struct ub_packed_rrset_key
*
322 find_NS(struct reply_info
* rep
, size_t from
, size_t to
)
325 for(i
=from
; i
<to
; i
++) {
326 if(ntohs(rep
->rrsets
[i
]->rk
.type
) == LDNS_RR_TYPE_NS
)
327 return rep
->rrsets
[i
];
333 delegpt_from_message(struct dns_msg
* msg
, struct regional
* region
)
335 struct ub_packed_rrset_key
* ns_rrset
= NULL
;
338 /* look for NS records in the authority section... */
339 ns_rrset
= find_NS(msg
->rep
, msg
->rep
->an_numrrsets
,
340 msg
->rep
->an_numrrsets
+msg
->rep
->ns_numrrsets
);
342 /* In some cases (even legitimate, perfectly legal cases), the
343 * NS set for the "referral" might be in the answer section. */
345 ns_rrset
= find_NS(msg
->rep
, 0, msg
->rep
->an_numrrsets
);
347 /* If there was no NS rrset in the authority section, then this
348 * wasn't a referral message. (It might not actually be a
349 * referral message anyway) */
353 /* If we found any, then Yay! we have a delegation point. */
354 dp
= delegpt_create(region
);
357 dp
->has_parent_side_NS
= 1; /* created from message */
358 if(!delegpt_set_name(dp
, region
, ns_rrset
->rk
.dname
))
360 if(!delegpt_rrset_add_ns(dp
, region
, ns_rrset
, 0))
363 /* add glue, A and AAAA in answer and additional section */
364 for(i
=0; i
<msg
->rep
->rrset_count
; i
++) {
365 struct ub_packed_rrset_key
* s
= msg
->rep
->rrsets
[i
];
366 /* skip auth section. FIXME really needed?*/
367 if(msg
->rep
->an_numrrsets
<= i
&&
368 i
< (msg
->rep
->an_numrrsets
+msg
->rep
->ns_numrrsets
))
371 if(ntohs(s
->rk
.type
) == LDNS_RR_TYPE_A
) {
372 if(!delegpt_add_rrset_A(dp
, region
, s
, 0))
374 } else if(ntohs(s
->rk
.type
) == LDNS_RR_TYPE_AAAA
) {
375 if(!delegpt_add_rrset_AAAA(dp
, region
, s
, 0))
383 delegpt_rrset_add_ns(struct delegpt
* dp
, struct regional
* region
,
384 struct ub_packed_rrset_key
* ns_rrset
, uint8_t lame
)
386 struct packed_rrset_data
* nsdata
= (struct packed_rrset_data
*)
387 ns_rrset
->entry
.data
;
389 log_assert(!dp
->dp_type_mlc
);
390 if(nsdata
->security
== sec_status_bogus
)
392 for(i
=0; i
<nsdata
->count
; i
++) {
393 if(nsdata
->rr_len
[i
] < 2+1) continue; /* len + root label */
394 if(dname_valid(nsdata
->rr_data
[i
]+2, nsdata
->rr_len
[i
]-2) !=
395 (size_t)sldns_read_uint16(nsdata
->rr_data
[i
]))
396 continue; /* bad format */
397 /* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
398 if(!delegpt_add_ns(dp
, region
, nsdata
->rr_data
[i
]+2, lame
))
405 delegpt_add_rrset_A(struct delegpt
* dp
, struct regional
* region
,
406 struct ub_packed_rrset_key
* ak
, uint8_t lame
)
408 struct packed_rrset_data
* d
=(struct packed_rrset_data
*)ak
->entry
.data
;
410 struct sockaddr_in sa
;
411 socklen_t len
= (socklen_t
)sizeof(sa
);
412 log_assert(!dp
->dp_type_mlc
);
414 sa
.sin_family
= AF_INET
;
415 sa
.sin_port
= (in_port_t
)htons(UNBOUND_DNS_PORT
);
416 for(i
=0; i
<d
->count
; i
++) {
417 if(d
->rr_len
[i
] != 2 + INET_SIZE
)
419 memmove(&sa
.sin_addr
, d
->rr_data
[i
]+2, INET_SIZE
);
420 if(!delegpt_add_target(dp
, region
, ak
->rk
.dname
,
421 ak
->rk
.dname_len
, (struct sockaddr_storage
*)&sa
,
422 len
, (d
->security
==sec_status_bogus
), lame
))
429 delegpt_add_rrset_AAAA(struct delegpt
* dp
, struct regional
* region
,
430 struct ub_packed_rrset_key
* ak
, uint8_t lame
)
432 struct packed_rrset_data
* d
=(struct packed_rrset_data
*)ak
->entry
.data
;
434 struct sockaddr_in6 sa
;
435 socklen_t len
= (socklen_t
)sizeof(sa
);
436 log_assert(!dp
->dp_type_mlc
);
438 sa
.sin6_family
= AF_INET6
;
439 sa
.sin6_port
= (in_port_t
)htons(UNBOUND_DNS_PORT
);
440 for(i
=0; i
<d
->count
; i
++) {
441 if(d
->rr_len
[i
] != 2 + INET6_SIZE
) /* rdatalen + len of IP6 */
443 memmove(&sa
.sin6_addr
, d
->rr_data
[i
]+2, INET6_SIZE
);
444 if(!delegpt_add_target(dp
, region
, ak
->rk
.dname
,
445 ak
->rk
.dname_len
, (struct sockaddr_storage
*)&sa
,
446 len
, (d
->security
==sec_status_bogus
), lame
))
453 delegpt_add_rrset(struct delegpt
* dp
, struct regional
* region
,
454 struct ub_packed_rrset_key
* rrset
, uint8_t lame
)
458 if(ntohs(rrset
->rk
.type
) == LDNS_RR_TYPE_NS
)
459 return delegpt_rrset_add_ns(dp
, region
, rrset
, lame
);
460 else if(ntohs(rrset
->rk
.type
) == LDNS_RR_TYPE_A
)
461 return delegpt_add_rrset_A(dp
, region
, rrset
, lame
);
462 else if(ntohs(rrset
->rk
.type
) == LDNS_RR_TYPE_AAAA
)
463 return delegpt_add_rrset_AAAA(dp
, region
, rrset
, lame
);
464 log_warn("Unknown rrset type added to delegpt");
468 void delegpt_add_neg_msg(struct delegpt
* dp
, struct msgreply_entry
* msg
)
470 struct reply_info
* rep
= (struct reply_info
*)msg
->entry
.data
;
473 /* if error or no answers */
474 if(FLAGS_GET_RCODE(rep
->flags
) != 0 || rep
->an_numrrsets
== 0) {
475 struct delegpt_ns
* ns
= delegpt_find_ns(dp
, msg
->key
.qname
,
478 if(msg
->key
.qtype
== LDNS_RR_TYPE_A
)
480 else if(msg
->key
.qtype
== LDNS_RR_TYPE_AAAA
)
482 if(ns
->got4
&& ns
->got6
)
488 void delegpt_no_ipv6(struct delegpt
* dp
)
490 struct delegpt_ns
* ns
;
491 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
492 /* no ipv6, so only ipv4 is enough to resolve a nameserver */
498 void delegpt_no_ipv4(struct delegpt
* dp
)
500 struct delegpt_ns
* ns
;
501 for(ns
= dp
->nslist
; ns
; ns
= ns
->next
) {
502 /* no ipv4, so only ipv6 is enough to resolve a nameserver */
508 struct delegpt
* delegpt_create_mlc(uint8_t* name
)
510 struct delegpt
* dp
=(struct delegpt
*)calloc(1, sizeof(*dp
));
515 dp
->namelabs
= dname_count_size_labels(name
, &dp
->namelen
);
516 dp
->name
= memdup(name
, dp
->namelen
);
525 void delegpt_free_mlc(struct delegpt
* dp
)
527 struct delegpt_ns
* n
, *nn
;
528 struct delegpt_addr
* a
, *na
;
530 log_assert(dp
->dp_type_mlc
);
548 int delegpt_set_name_mlc(struct delegpt
* dp
, uint8_t* name
)
550 log_assert(dp
->dp_type_mlc
);
551 dp
->namelabs
= dname_count_size_labels(name
, &dp
->namelen
);
552 dp
->name
= memdup(name
, dp
->namelen
);
553 return (dp
->name
!= NULL
);
556 int delegpt_add_ns_mlc(struct delegpt
* dp
, uint8_t* name
, uint8_t lame
)
558 struct delegpt_ns
* ns
;
560 (void)dname_count_size_labels(name
, &len
);
561 log_assert(dp
->dp_type_mlc
);
562 /* slow check for duplicates to avoid counting failures when
563 * adding the same server as a dependency twice */
564 if(delegpt_find_ns(dp
, name
, len
))
566 ns
= (struct delegpt_ns
*)malloc(sizeof(struct delegpt_ns
));
570 ns
->name
= memdup(name
, ns
->namelen
);
575 ns
->next
= dp
->nslist
;
580 ns
->lame
= (uint8_t)lame
;
586 int delegpt_add_addr_mlc(struct delegpt
* dp
, struct sockaddr_storage
* addr
,
587 socklen_t addrlen
, uint8_t bogus
, uint8_t lame
)
589 struct delegpt_addr
* a
;
590 log_assert(dp
->dp_type_mlc
);
591 /* check for duplicates */
592 if((a
= delegpt_find_addr(dp
, addr
, addrlen
))) {
600 a
= (struct delegpt_addr
*)malloc(sizeof(struct delegpt_addr
));
603 a
->next_target
= dp
->target_list
;
606 a
->next_usable
= dp
->usable_list
;
608 memcpy(&a
->addr
, addr
, addrlen
);
609 a
->addrlen
= addrlen
;
617 int delegpt_add_target_mlc(struct delegpt
* dp
, uint8_t* name
, size_t namelen
,
618 struct sockaddr_storage
* addr
, socklen_t addrlen
, uint8_t bogus
,
621 struct delegpt_ns
* ns
= delegpt_find_ns(dp
, name
, namelen
);
622 log_assert(dp
->dp_type_mlc
);
628 if(addr_is_ip6(addr
, addrlen
))
631 if(ns
->got4
&& ns
->got6
)
634 return delegpt_add_addr_mlc(dp
, addr
, addrlen
, bogus
, lame
);
637 size_t delegpt_get_mem(struct delegpt
* dp
)
639 struct delegpt_ns
* ns
;
642 s
= sizeof(*dp
) + dp
->namelen
+
643 delegpt_count_targets(dp
)*sizeof(struct delegpt_addr
);
644 for(ns
=dp
->nslist
; ns
; ns
=ns
->next
)
645 s
+= sizeof(*ns
)+ns
->namelen
;