]>
git.saurik.com Git - apple/network_cmds.git/blob - unbound/iterator/iter_priv.c
9e09a84bd01e69c32aed4def49ba149c46eb0560
2 * iterator/iter_priv.c - iterative resolver private address and domain store
4 * Copyright (c) 2008, 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 functions to assist the iterator module.
40 * Keep track of the private addresses and lookup fast.
44 #include "iterator/iter_priv.h"
45 #include "util/regional.h"
47 #include "util/config_file.h"
48 #include "util/data/dname.h"
49 #include "util/data/msgparse.h"
50 #include "util/net_help.h"
51 #include "util/storage/dnstree.h"
52 #include "ldns/str2wire.h"
53 #include "ldns/sbuffer.h"
55 struct iter_priv
* priv_create(void)
57 struct iter_priv
* priv
= (struct iter_priv
*)calloc(1, sizeof(*priv
));
60 priv
->region
= regional_create();
65 addr_tree_init(&priv
->a
);
66 name_tree_init(&priv
->n
);
70 void priv_delete(struct iter_priv
* priv
)
73 regional_destroy(priv
->region
);
77 /** Read private-addr declarations from config */
78 static int read_addrs(struct iter_priv
* priv
, struct config_file
* cfg
)
80 /* parse addresses, report errors, insert into tree */
81 struct config_strlist
* p
;
82 struct addr_tree_node
* n
;
83 struct sockaddr_storage addr
;
87 for(p
= cfg
->private_address
; p
; p
= p
->next
) {
89 if(!netblockstrtoaddr(p
->str
, UNBOUND_DNS_PORT
, &addr
,
91 log_err("cannot parse private-address: %s", p
->str
);
94 n
= (struct addr_tree_node
*)regional_alloc(priv
->region
,
97 log_err("out of memory");
100 if(!addr_tree_insert(&priv
->a
, n
, &addr
, addrlen
, net
)) {
101 verbose(VERB_QUERY
, "ignoring duplicate "
102 "private-address: %s", p
->str
);
108 /** Read private-domain declarations from config */
109 static int read_names(struct iter_priv
* priv
, struct config_file
* cfg
)
111 /* parse names, report errors, insert into tree */
112 struct config_strlist
* p
;
113 struct name_tree_node
* n
;
118 for(p
= cfg
->private_domain
; p
; p
= p
->next
) {
120 nm
= sldns_str2wire_dname(p
->str
, &nm_len
);
122 log_err("cannot parse private-domain: %s", p
->str
);
125 nm_labs
= dname_count_size_labels(nm
, &nm_len
);
126 nmr
= (uint8_t*)regional_alloc_init(priv
->region
, nm
, nm_len
);
129 log_err("out of memory");
132 n
= (struct name_tree_node
*)regional_alloc(priv
->region
,
135 log_err("out of memory");
138 if(!name_tree_insert(&priv
->n
, n
, nmr
, nm_len
, nm_labs
,
140 verbose(VERB_QUERY
, "ignoring duplicate "
141 "private-domain: %s", p
->str
);
147 int priv_apply_cfg(struct iter_priv
* priv
, struct config_file
* cfg
)
149 /* empty the current contents */
150 regional_free_all(priv
->region
);
151 addr_tree_init(&priv
->a
);
152 name_tree_init(&priv
->n
);
154 /* read new contents */
155 if(!read_addrs(priv
, cfg
))
157 if(!read_names(priv
, cfg
))
160 /* prepare for lookups */
161 addr_tree_init_parents(&priv
->a
);
162 name_tree_init_parents(&priv
->n
);
167 * See if an address is blocked.
168 * @param priv: structure for address storage.
169 * @param addr: address to check
170 * @param addrlen: length of addr.
171 * @return: true if the address must not be queried. false if unlisted.
174 priv_lookup_addr(struct iter_priv
* priv
, struct sockaddr_storage
* addr
,
177 return addr_tree_lookup(&priv
->a
, addr
, addrlen
) != NULL
;
181 * See if a name is whitelisted.
182 * @param priv: structure for address storage.
183 * @param pkt: the packet (for compression ptrs).
184 * @param name: name to check.
185 * @param name_len: uncompressed length of the name to check.
186 * @param dclass: class to check.
187 * @return: true if the name is OK. false if unlisted.
190 priv_lookup_name(struct iter_priv
* priv
, sldns_buffer
* pkt
,
191 uint8_t* name
, size_t name_len
, uint16_t dclass
)
196 if(name_len
>= sizeof(decomp
))
198 dname_pkt_copy(pkt
, decomp
, name
);
199 labs
= dname_count_size_labels(decomp
, &len
);
200 log_assert(name_len
== len
);
201 return name_tree_lookup(&priv
->n
, decomp
, len
, labs
, dclass
) != NULL
;
204 size_t priv_get_mem(struct iter_priv
* priv
)
207 return sizeof(*priv
) + regional_get_mem(priv
->region
);
210 /** remove RR from msgparse RRset, return true if rrset is entirely bad */
212 remove_rr(const char* str
, sldns_buffer
* pkt
, struct rrset_parse
* rrset
,
213 struct rr_parse
* prev
, struct rr_parse
** rr
, struct sockaddr_storage
* addr
, socklen_t addrlen
)
215 if(verbosity
>= VERB_QUERY
&& rrset
->dname_len
<= LDNS_MAX_DOMAINLEN
&& str
) {
216 uint8_t buf
[LDNS_MAX_DOMAINLEN
+1];
217 dname_pkt_copy(pkt
, buf
, rrset
->dname
);
218 log_name_addr(VERB_QUERY
, str
, buf
, addr
, addrlen
);
221 prev
->next
= (*rr
)->next
;
222 else rrset
->rr_first
= (*rr
)->next
;
223 if(rrset
->rr_last
== *rr
)
224 rrset
->rr_last
= prev
;
226 rrset
->size
-= (*rr
)->size
;
227 /* rr struct still exists, but is unlinked, so that in the for loop
228 * the rr->next works fine to continue. */
229 return rrset
->rr_count
== 0;
232 int priv_rrset_bad(struct iter_priv
* priv
, sldns_buffer
* pkt
,
233 struct rrset_parse
* rrset
)
235 if(priv
->a
.count
== 0)
236 return 0; /* there are no blocked addresses */
238 /* see if it is a private name, that is allowed to have any */
239 if(priv_lookup_name(priv
, pkt
, rrset
->dname
, rrset
->dname_len
,
240 ntohs(rrset
->rrset_class
))) {
243 /* so its a public name, check the address */
245 struct rr_parse
* rr
, *prev
= NULL
;
246 if(rrset
->type
== LDNS_RR_TYPE_A
) {
247 struct sockaddr_storage addr
;
248 struct sockaddr_in sa
;
250 len
= (socklen_t
)sizeof(sa
);
252 sa
.sin_family
= AF_INET
;
253 sa
.sin_port
= (in_port_t
)htons(UNBOUND_DNS_PORT
);
254 for(rr
= rrset
->rr_first
; rr
; rr
= rr
->next
) {
255 if(sldns_read_uint16(rr
->ttl_data
+4)
260 memmove(&sa
.sin_addr
, rr
->ttl_data
+4+2,
262 memmove(&addr
, &sa
, len
);
263 if(priv_lookup_addr(priv
, &addr
, len
)) {
264 if(remove_rr("sanitize: removing public name with private address", pkt
, rrset
, prev
, &rr
, &addr
, len
))
270 } else if(rrset
->type
== LDNS_RR_TYPE_AAAA
) {
271 struct sockaddr_storage addr
;
272 struct sockaddr_in6 sa
;
273 len
= (socklen_t
)sizeof(sa
);
275 sa
.sin6_family
= AF_INET6
;
276 sa
.sin6_port
= (in_port_t
)htons(UNBOUND_DNS_PORT
);
277 for(rr
= rrset
->rr_first
; rr
; rr
= rr
->next
) {
278 if(sldns_read_uint16(rr
->ttl_data
+4)
283 memmove(&sa
.sin6_addr
, rr
->ttl_data
+4+2,
285 memmove(&addr
, &sa
, len
);
286 if(priv_lookup_addr(priv
, &addr
, len
)) {
287 if(remove_rr("sanitize: removing public name with private address", pkt
, rrset
, prev
, &rr
, &addr
, len
))