iter_priv.c revision 1.1.1.2.4.1 1 1.1 christos /*
2 1.1 christos * iterator/iter_priv.c - iterative resolver private address and domain store
3 1.1 christos *
4 1.1 christos * Copyright (c) 2008, NLnet Labs. All rights reserved.
5 1.1 christos *
6 1.1 christos * This software is open source.
7 1.1 christos *
8 1.1 christos * Redistribution and use in source and binary forms, with or without
9 1.1 christos * modification, are permitted provided that the following conditions
10 1.1 christos * are met:
11 1.1 christos *
12 1.1 christos * Redistributions of source code must retain the above copyright notice,
13 1.1 christos * this list of conditions and the following disclaimer.
14 1.1 christos *
15 1.1 christos * Redistributions in binary form must reproduce the above copyright notice,
16 1.1 christos * this list of conditions and the following disclaimer in the documentation
17 1.1 christos * and/or other materials provided with the distribution.
18 1.1 christos *
19 1.1 christos * Neither the name of the NLNET LABS nor the names of its contributors may
20 1.1 christos * be used to endorse or promote products derived from this software without
21 1.1 christos * specific prior written permission.
22 1.1 christos *
23 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 1.1 christos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 1.1 christos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 1.1 christos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 1.1 christos * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 1.1 christos * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 1.1 christos * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 1.1 christos * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 1.1 christos * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 1.1 christos * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 1.1 christos * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 1.1 christos */
35 1.1 christos
36 1.1 christos /**
37 1.1 christos * \file
38 1.1 christos *
39 1.1 christos * This file contains functions to assist the iterator module.
40 1.1 christos * Keep track of the private addresses and lookup fast.
41 1.1 christos */
42 1.1 christos
43 1.1 christos #include "config.h"
44 1.1 christos #include "iterator/iter_priv.h"
45 1.1 christos #include "util/regional.h"
46 1.1 christos #include "util/log.h"
47 1.1 christos #include "util/config_file.h"
48 1.1 christos #include "util/data/dname.h"
49 1.1 christos #include "util/data/msgparse.h"
50 1.1 christos #include "util/net_help.h"
51 1.1 christos #include "util/storage/dnstree.h"
52 1.1 christos #include "sldns/str2wire.h"
53 1.1 christos #include "sldns/sbuffer.h"
54 1.1 christos
55 1.1 christos struct iter_priv* priv_create(void)
56 1.1 christos {
57 1.1 christos struct iter_priv* priv = (struct iter_priv*)calloc(1, sizeof(*priv));
58 1.1 christos if(!priv)
59 1.1 christos return NULL;
60 1.1 christos priv->region = regional_create();
61 1.1 christos if(!priv->region) {
62 1.1 christos priv_delete(priv);
63 1.1 christos return NULL;
64 1.1 christos }
65 1.1 christos addr_tree_init(&priv->a);
66 1.1 christos name_tree_init(&priv->n);
67 1.1 christos return priv;
68 1.1 christos }
69 1.1 christos
70 1.1 christos void priv_delete(struct iter_priv* priv)
71 1.1 christos {
72 1.1 christos if(!priv) return;
73 1.1 christos regional_destroy(priv->region);
74 1.1 christos free(priv);
75 1.1 christos }
76 1.1 christos
77 1.1 christos /** Read private-addr declarations from config */
78 1.1 christos static int read_addrs(struct iter_priv* priv, struct config_file* cfg)
79 1.1 christos {
80 1.1 christos /* parse addresses, report errors, insert into tree */
81 1.1 christos struct config_strlist* p;
82 1.1 christos struct addr_tree_node* n;
83 1.1 christos struct sockaddr_storage addr;
84 1.1 christos int net;
85 1.1 christos socklen_t addrlen;
86 1.1 christos
87 1.1 christos for(p = cfg->private_address; p; p = p->next) {
88 1.1 christos log_assert(p->str);
89 1.1 christos if(!netblockstrtoaddr(p->str, UNBOUND_DNS_PORT, &addr,
90 1.1 christos &addrlen, &net)) {
91 1.1 christos log_err("cannot parse private-address: %s", p->str);
92 1.1 christos return 0;
93 1.1 christos }
94 1.1 christos n = (struct addr_tree_node*)regional_alloc(priv->region,
95 1.1 christos sizeof(*n));
96 1.1 christos if(!n) {
97 1.1 christos log_err("out of memory");
98 1.1 christos return 0;
99 1.1 christos }
100 1.1 christos if(!addr_tree_insert(&priv->a, n, &addr, addrlen, net)) {
101 1.1 christos verbose(VERB_QUERY, "ignoring duplicate "
102 1.1 christos "private-address: %s", p->str);
103 1.1 christos }
104 1.1 christos }
105 1.1 christos return 1;
106 1.1 christos }
107 1.1 christos
108 1.1 christos /** Read private-domain declarations from config */
109 1.1 christos static int read_names(struct iter_priv* priv, struct config_file* cfg)
110 1.1 christos {
111 1.1 christos /* parse names, report errors, insert into tree */
112 1.1 christos struct config_strlist* p;
113 1.1 christos struct name_tree_node* n;
114 1.1 christos uint8_t* nm, *nmr;
115 1.1 christos size_t nm_len;
116 1.1 christos int nm_labs;
117 1.1 christos
118 1.1 christos for(p = cfg->private_domain; p; p = p->next) {
119 1.1 christos log_assert(p->str);
120 1.1 christos nm = sldns_str2wire_dname(p->str, &nm_len);
121 1.1 christos if(!nm) {
122 1.1 christos log_err("cannot parse private-domain: %s", p->str);
123 1.1 christos return 0;
124 1.1 christos }
125 1.1 christos nm_labs = dname_count_size_labels(nm, &nm_len);
126 1.1 christos nmr = (uint8_t*)regional_alloc_init(priv->region, nm, nm_len);
127 1.1 christos free(nm);
128 1.1 christos if(!nmr) {
129 1.1 christos log_err("out of memory");
130 1.1 christos return 0;
131 1.1 christos }
132 1.1 christos n = (struct name_tree_node*)regional_alloc(priv->region,
133 1.1 christos sizeof(*n));
134 1.1 christos if(!n) {
135 1.1 christos log_err("out of memory");
136 1.1 christos return 0;
137 1.1 christos }
138 1.1 christos if(!name_tree_insert(&priv->n, n, nmr, nm_len, nm_labs,
139 1.1 christos LDNS_RR_CLASS_IN)) {
140 1.1 christos verbose(VERB_QUERY, "ignoring duplicate "
141 1.1 christos "private-domain: %s", p->str);
142 1.1 christos }
143 1.1 christos }
144 1.1 christos return 1;
145 1.1 christos }
146 1.1 christos
147 1.1 christos int priv_apply_cfg(struct iter_priv* priv, struct config_file* cfg)
148 1.1 christos {
149 1.1 christos /* empty the current contents */
150 1.1 christos regional_free_all(priv->region);
151 1.1 christos addr_tree_init(&priv->a);
152 1.1 christos name_tree_init(&priv->n);
153 1.1 christos
154 1.1 christos /* read new contents */
155 1.1 christos if(!read_addrs(priv, cfg))
156 1.1 christos return 0;
157 1.1 christos if(!read_names(priv, cfg))
158 1.1 christos return 0;
159 1.1 christos
160 1.1 christos /* prepare for lookups */
161 1.1 christos addr_tree_init_parents(&priv->a);
162 1.1 christos name_tree_init_parents(&priv->n);
163 1.1 christos return 1;
164 1.1 christos }
165 1.1 christos
166 1.1 christos /**
167 1.1 christos * See if an address is blocked.
168 1.1 christos * @param priv: structure for address storage.
169 1.1 christos * @param addr: address to check
170 1.1 christos * @param addrlen: length of addr.
171 1.1 christos * @return: true if the address must not be queried. false if unlisted.
172 1.1 christos */
173 1.1 christos static int
174 1.1 christos priv_lookup_addr(struct iter_priv* priv, struct sockaddr_storage* addr,
175 1.1 christos socklen_t addrlen)
176 1.1 christos {
177 1.1 christos return addr_tree_lookup(&priv->a, addr, addrlen) != NULL;
178 1.1 christos }
179 1.1 christos
180 1.1 christos /**
181 1.1 christos * See if a name is whitelisted.
182 1.1 christos * @param priv: structure for address storage.
183 1.1 christos * @param pkt: the packet (for compression ptrs).
184 1.1 christos * @param name: name to check.
185 1.1 christos * @param name_len: uncompressed length of the name to check.
186 1.1 christos * @param dclass: class to check.
187 1.1 christos * @return: true if the name is OK. false if unlisted.
188 1.1 christos */
189 1.1 christos static int
190 1.1 christos priv_lookup_name(struct iter_priv* priv, sldns_buffer* pkt,
191 1.1 christos uint8_t* name, size_t name_len, uint16_t dclass)
192 1.1 christos {
193 1.1 christos size_t len;
194 1.1 christos uint8_t decomp[256];
195 1.1 christos int labs;
196 1.1 christos if(name_len >= sizeof(decomp))
197 1.1 christos return 0;
198 1.1 christos dname_pkt_copy(pkt, decomp, name);
199 1.1 christos labs = dname_count_size_labels(decomp, &len);
200 1.1 christos log_assert(name_len == len);
201 1.1 christos return name_tree_lookup(&priv->n, decomp, len, labs, dclass) != NULL;
202 1.1 christos }
203 1.1 christos
204 1.1 christos size_t priv_get_mem(struct iter_priv* priv)
205 1.1 christos {
206 1.1 christos if(!priv) return 0;
207 1.1 christos return sizeof(*priv) + regional_get_mem(priv->region);
208 1.1 christos }
209 1.1 christos
210 1.1.1.2.4.1 martin /**
211 1.1.1.2.4.1 martin * Check if svcparam ipv4hint contains a private address.
212 1.1.1.2.4.1 martin * @param priv: private address lookup struct.
213 1.1.1.2.4.1 martin * @param d: the data bytes.
214 1.1.1.2.4.1 martin * @param data_len: number of data bytes in the svcparam.
215 1.1.1.2.4.1 martin * @param addr: address to return the private address to log in to.
216 1.1.1.2.4.1 martin * It has space for IPv4 and IPv6 addresses.
217 1.1.1.2.4.1 martin * @param addrlen: length of the addr. Returns the correct size for the addr.
218 1.1.1.2.4.1 martin * @return true if the rdata contains a private address.
219 1.1.1.2.4.1 martin */
220 1.1.1.2.4.1 martin static int svcb_ipv4hint_contains_priv_addr(struct iter_priv* priv,
221 1.1.1.2.4.1 martin uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
222 1.1.1.2.4.1 martin socklen_t* addrlen)
223 1.1.1.2.4.1 martin {
224 1.1.1.2.4.1 martin struct sockaddr_in sa;
225 1.1.1.2.4.1 martin *addrlen = (socklen_t)sizeof(struct sockaddr_in);
226 1.1.1.2.4.1 martin memset(&sa, 0, sizeof(struct sockaddr_in));
227 1.1.1.2.4.1 martin sa.sin_family = AF_INET;
228 1.1.1.2.4.1 martin sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
229 1.1.1.2.4.1 martin
230 1.1.1.2.4.1 martin while(data_len >= LDNS_IP4ADDRLEN) {
231 1.1.1.2.4.1 martin memmove(&sa.sin_addr, d, LDNS_IP4ADDRLEN);
232 1.1.1.2.4.1 martin memmove(addr, &sa, *addrlen);
233 1.1.1.2.4.1 martin if(priv_lookup_addr(priv, addr, *addrlen))
234 1.1.1.2.4.1 martin return 1;
235 1.1.1.2.4.1 martin
236 1.1.1.2.4.1 martin d += LDNS_IP4ADDRLEN;
237 1.1.1.2.4.1 martin data_len -= LDNS_IP4ADDRLEN;
238 1.1.1.2.4.1 martin }
239 1.1.1.2.4.1 martin /* if data_len != 0 here, then the svcparam is malformed. */
240 1.1.1.2.4.1 martin return 0;
241 1.1.1.2.4.1 martin }
242 1.1.1.2.4.1 martin
243 1.1.1.2.4.1 martin /**
244 1.1.1.2.4.1 martin * Check if svcparam ipv6hint contains a private address.
245 1.1.1.2.4.1 martin * @param priv: private address lookup struct.
246 1.1.1.2.4.1 martin * @param d: the data bytes.
247 1.1.1.2.4.1 martin * @param data_len: number of data bytes in the svcparam.
248 1.1.1.2.4.1 martin * @param addr: address to return the private address to log in to.
249 1.1.1.2.4.1 martin * It has space for IPv4 and IPv6 addresses.
250 1.1.1.2.4.1 martin * @param addrlen: length of the addr. Returns the correct size for the addr.
251 1.1.1.2.4.1 martin * @return true if the rdata contains a private address.
252 1.1.1.2.4.1 martin */
253 1.1.1.2.4.1 martin static int svcb_ipv6hint_contains_priv_addr(struct iter_priv* priv,
254 1.1.1.2.4.1 martin uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
255 1.1.1.2.4.1 martin socklen_t* addrlen)
256 1.1.1.2.4.1 martin {
257 1.1.1.2.4.1 martin struct sockaddr_in6 sa;
258 1.1.1.2.4.1 martin *addrlen = (socklen_t)sizeof(struct sockaddr_in6);
259 1.1.1.2.4.1 martin memset(&sa, 0, sizeof(struct sockaddr_in6));
260 1.1.1.2.4.1 martin sa.sin6_family = AF_INET6;
261 1.1.1.2.4.1 martin sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
262 1.1.1.2.4.1 martin
263 1.1.1.2.4.1 martin while(data_len >= LDNS_IP6ADDRLEN) {
264 1.1.1.2.4.1 martin memmove(&sa.sin6_addr, d, LDNS_IP6ADDRLEN);
265 1.1.1.2.4.1 martin memmove(addr, &sa, *addrlen);
266 1.1.1.2.4.1 martin if(priv_lookup_addr(priv, addr, *addrlen))
267 1.1.1.2.4.1 martin return 1;
268 1.1.1.2.4.1 martin
269 1.1.1.2.4.1 martin d += LDNS_IP6ADDRLEN;
270 1.1.1.2.4.1 martin data_len -= LDNS_IP6ADDRLEN;
271 1.1.1.2.4.1 martin }
272 1.1.1.2.4.1 martin /* if data_len != 0 here, then the svcparam is malformed. */
273 1.1.1.2.4.1 martin return 0;
274 1.1.1.2.4.1 martin }
275 1.1.1.2.4.1 martin
276 1.1.1.2.4.1 martin /**
277 1.1.1.2.4.1 martin * Check if type SVCB and HTTPS rdata contains a private address.
278 1.1.1.2.4.1 martin * @param priv: private address lookup struct.
279 1.1.1.2.4.1 martin * @param pkt: the packet.
280 1.1.1.2.4.1 martin * @param rr: the rr with rdata to check.
281 1.1.1.2.4.1 martin * @param addr: address to return the private address to log in to.
282 1.1.1.2.4.1 martin * @param addrlen: length of the addr. Initially the total size, on
283 1.1.1.2.4.1 martin * return the correct size for the addr.
284 1.1.1.2.4.1 martin * @return true if the rdata contains a private address.
285 1.1.1.2.4.1 martin */
286 1.1.1.2.4.1 martin static int svcb_rr_contains_priv_addr(struct iter_priv* priv,
287 1.1.1.2.4.1 martin sldns_buffer* pkt, struct rr_parse* rr, struct sockaddr_storage* addr,
288 1.1.1.2.4.1 martin socklen_t* addrlen)
289 1.1.1.2.4.1 martin {
290 1.1.1.2.4.1 martin uint8_t* d = rr->ttl_data;
291 1.1.1.2.4.1 martin uint16_t svcparamkey, data_len, rdatalen;
292 1.1.1.2.4.1 martin size_t oldpos, dname_len, dname_start, dname_compr_len;
293 1.1.1.2.4.1 martin d += 4; /* skip TTL */
294 1.1.1.2.4.1 martin rdatalen = sldns_read_uint16(d); /* read rdata length */
295 1.1.1.2.4.1 martin d += 2;
296 1.1.1.2.4.1 martin
297 1.1.1.2.4.1 martin if(rdatalen < 2 /* priority */ + 1 /* 1 length target */)
298 1.1.1.2.4.1 martin return 0; /* malformed, too short */
299 1.1.1.2.4.1 martin d += 2; /* skip priority */
300 1.1.1.2.4.1 martin rdatalen -= 2;
301 1.1.1.2.4.1 martin oldpos = sldns_buffer_position(pkt);
302 1.1.1.2.4.1 martin sldns_buffer_set_position(pkt, (size_t)(d - sldns_buffer_begin(pkt)));
303 1.1.1.2.4.1 martin dname_start = sldns_buffer_position(pkt);
304 1.1.1.2.4.1 martin dname_len = pkt_dname_len(pkt);
305 1.1.1.2.4.1 martin dname_compr_len = sldns_buffer_position(pkt) - dname_start;
306 1.1.1.2.4.1 martin sldns_buffer_set_position(pkt, oldpos);
307 1.1.1.2.4.1 martin if(dname_len == 0)
308 1.1.1.2.4.1 martin return 0; /* dname malformed */
309 1.1.1.2.4.1 martin if(dname_compr_len > rdatalen)
310 1.1.1.2.4.1 martin return 0; /* malformed */
311 1.1.1.2.4.1 martin d += dname_compr_len; /* skip target */
312 1.1.1.2.4.1 martin rdatalen -= dname_compr_len;
313 1.1.1.2.4.1 martin
314 1.1.1.2.4.1 martin while(rdatalen >= 4) {
315 1.1.1.2.4.1 martin svcparamkey = sldns_read_uint16(d);
316 1.1.1.2.4.1 martin data_len = sldns_read_uint16(d+2);
317 1.1.1.2.4.1 martin d += 4;
318 1.1.1.2.4.1 martin rdatalen -= 4;
319 1.1.1.2.4.1 martin
320 1.1.1.2.4.1 martin /* verify that we have data_len data */
321 1.1.1.2.4.1 martin if(data_len > rdatalen) {
322 1.1.1.2.4.1 martin /* It is malformed, but if there are addresses
323 1.1.1.2.4.1 martin * in there it can be rejected. */
324 1.1.1.2.4.1 martin data_len = rdatalen;
325 1.1.1.2.4.1 martin }
326 1.1.1.2.4.1 martin
327 1.1.1.2.4.1 martin if(!data_len)
328 1.1.1.2.4.1 martin continue; /* no data for the svcparamkey */
329 1.1.1.2.4.1 martin
330 1.1.1.2.4.1 martin if(svcparamkey == SVCB_KEY_IPV4HINT) {
331 1.1.1.2.4.1 martin if(svcb_ipv4hint_contains_priv_addr(priv, d, data_len,
332 1.1.1.2.4.1 martin addr, addrlen))
333 1.1.1.2.4.1 martin return 1;
334 1.1.1.2.4.1 martin } else if(svcparamkey == SVCB_KEY_IPV6HINT) {
335 1.1.1.2.4.1 martin if(svcb_ipv6hint_contains_priv_addr(priv, d, data_len,
336 1.1.1.2.4.1 martin addr, addrlen))
337 1.1.1.2.4.1 martin return 1;
338 1.1.1.2.4.1 martin }
339 1.1.1.2.4.1 martin d += data_len;
340 1.1.1.2.4.1 martin rdatalen -= data_len;
341 1.1.1.2.4.1 martin }
342 1.1.1.2.4.1 martin /* If rdatalen != 0 here, then the svcb rdata is malformed. */
343 1.1.1.2.4.1 martin return 0;
344 1.1.1.2.4.1 martin }
345 1.1.1.2.4.1 martin
346 1.1.1.2.4.1 martin /**
347 1.1.1.2.4.1 martin * Check if the SVCB and HTTPS rrset is bad.
348 1.1.1.2.4.1 martin * @param priv: private address lookup struct.
349 1.1.1.2.4.1 martin * @param pkt: the packet.
350 1.1.1.2.4.1 martin * @param rrset: the rrset to check.
351 1.1.1.2.4.1 martin * @return 1 if the entire rrset has to be removed. 0 if not.
352 1.1.1.2.4.1 martin * It removes RRs if they have private addresses, and log that.
353 1.1.1.2.4.1 martin */
354 1.1.1.2.4.1 martin static int priv_svcb_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
355 1.1.1.2.4.1 martin struct rrset_parse* rrset)
356 1.1.1.2.4.1 martin {
357 1.1.1.2.4.1 martin struct rr_parse* rr, *prev = NULL;
358 1.1.1.2.4.1 martin struct sockaddr_storage addr;
359 1.1.1.2.4.1 martin socklen_t addrlen = (socklen_t)sizeof(addr);
360 1.1.1.2.4.1 martin for(rr = rrset->rr_first; rr; rr = rr->next) {
361 1.1.1.2.4.1 martin if(svcb_rr_contains_priv_addr(priv, pkt, rr, &addr,
362 1.1.1.2.4.1 martin &addrlen)) {
363 1.1.1.2.4.1 martin if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, addrlen))
364 1.1.1.2.4.1 martin return 1;
365 1.1.1.2.4.1 martin continue;
366 1.1.1.2.4.1 martin }
367 1.1.1.2.4.1 martin prev = rr;
368 1.1.1.2.4.1 martin }
369 1.1.1.2.4.1 martin return 0;
370 1.1.1.2.4.1 martin }
371 1.1.1.2.4.1 martin
372 1.1 christos int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
373 1.1 christos struct rrset_parse* rrset)
374 1.1 christos {
375 1.1 christos if(priv->a.count == 0)
376 1.1 christos return 0; /* there are no blocked addresses */
377 1.1 christos
378 1.1 christos /* see if it is a private name, that is allowed to have any */
379 1.1 christos if(priv_lookup_name(priv, pkt, rrset->dname, rrset->dname_len,
380 1.1 christos ntohs(rrset->rrset_class))) {
381 1.1 christos return 0;
382 1.1 christos } else {
383 1.1 christos /* so its a public name, check the address */
384 1.1 christos socklen_t len;
385 1.1 christos struct rr_parse* rr, *prev = NULL;
386 1.1 christos if(rrset->type == LDNS_RR_TYPE_A) {
387 1.1 christos struct sockaddr_storage addr;
388 1.1 christos struct sockaddr_in sa;
389 1.1 christos
390 1.1 christos len = (socklen_t)sizeof(sa);
391 1.1 christos memset(&sa, 0, len);
392 1.1 christos sa.sin_family = AF_INET;
393 1.1 christos sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
394 1.1 christos for(rr = rrset->rr_first; rr; rr = rr->next) {
395 1.1 christos if(sldns_read_uint16(rr->ttl_data+4)
396 1.1 christos != INET_SIZE) {
397 1.1 christos prev = rr;
398 1.1 christos continue;
399 1.1 christos }
400 1.1 christos memmove(&sa.sin_addr, rr->ttl_data+4+2,
401 1.1 christos INET_SIZE);
402 1.1 christos memmove(&addr, &sa, len);
403 1.1 christos if(priv_lookup_addr(priv, &addr, len)) {
404 1.1.1.2 christos if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
405 1.1 christos return 1;
406 1.1 christos continue;
407 1.1 christos }
408 1.1 christos prev = rr;
409 1.1 christos }
410 1.1 christos } else if(rrset->type == LDNS_RR_TYPE_AAAA) {
411 1.1 christos struct sockaddr_storage addr;
412 1.1 christos struct sockaddr_in6 sa;
413 1.1 christos len = (socklen_t)sizeof(sa);
414 1.1 christos memset(&sa, 0, len);
415 1.1 christos sa.sin6_family = AF_INET6;
416 1.1 christos sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
417 1.1 christos for(rr = rrset->rr_first; rr; rr = rr->next) {
418 1.1 christos if(sldns_read_uint16(rr->ttl_data+4)
419 1.1 christos != INET6_SIZE) {
420 1.1 christos prev = rr;
421 1.1 christos continue;
422 1.1 christos }
423 1.1 christos memmove(&sa.sin6_addr, rr->ttl_data+4+2,
424 1.1 christos INET6_SIZE);
425 1.1 christos memmove(&addr, &sa, len);
426 1.1 christos if(priv_lookup_addr(priv, &addr, len)) {
427 1.1.1.2 christos if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
428 1.1 christos return 1;
429 1.1 christos continue;
430 1.1 christos }
431 1.1 christos prev = rr;
432 1.1 christos }
433 1.1.1.2.4.1 martin } else if(rrset->type == LDNS_RR_TYPE_SVCB ||
434 1.1.1.2.4.1 martin rrset->type == LDNS_RR_TYPE_HTTPS) {
435 1.1.1.2.4.1 martin if(priv_svcb_rrset_bad(priv, pkt, rrset))
436 1.1.1.2.4.1 martin return 1;
437 1.1.1.2.4.1 martin }
438 1.1 christos }
439 1.1 christos return 0;
440 1.1 christos }
441