Home | History | Annotate | Line # | Download | only in iterator
      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.3  christos /**
    211  1.1.1.3  christos  * Check if svcparam ipv4hint contains a private address.
    212  1.1.1.3  christos  * @param priv: private address lookup struct.
    213  1.1.1.3  christos  * @param d: the data bytes.
    214  1.1.1.3  christos  * @param data_len: number of data bytes in the svcparam.
    215  1.1.1.3  christos  * @param addr: address to return the private address to log in to.
    216  1.1.1.3  christos  *	It has space for IPv4 and IPv6 addresses.
    217  1.1.1.3  christos  * @param addrlen: length of the addr. Returns the correct size for the addr.
    218  1.1.1.3  christos  * @return true if the rdata contains a private address.
    219  1.1.1.3  christos  */
    220  1.1.1.3  christos static int svcb_ipv4hint_contains_priv_addr(struct iter_priv* priv,
    221  1.1.1.3  christos 	uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
    222  1.1.1.3  christos 	socklen_t* addrlen)
    223  1.1.1.3  christos {
    224  1.1.1.3  christos 	struct sockaddr_in sa;
    225  1.1.1.3  christos 	*addrlen = (socklen_t)sizeof(struct sockaddr_in);
    226  1.1.1.3  christos 	memset(&sa, 0, sizeof(struct sockaddr_in));
    227  1.1.1.3  christos 	sa.sin_family = AF_INET;
    228  1.1.1.3  christos 	sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
    229  1.1.1.3  christos 
    230  1.1.1.3  christos 	while(data_len >= LDNS_IP4ADDRLEN) {
    231  1.1.1.3  christos 		memmove(&sa.sin_addr, d, LDNS_IP4ADDRLEN);
    232  1.1.1.3  christos 		memmove(addr, &sa, *addrlen);
    233  1.1.1.3  christos 		if(priv_lookup_addr(priv, addr, *addrlen))
    234  1.1.1.3  christos 			return 1;
    235  1.1.1.3  christos 
    236  1.1.1.3  christos 		d += LDNS_IP4ADDRLEN;
    237  1.1.1.3  christos 		data_len -= LDNS_IP4ADDRLEN;
    238  1.1.1.3  christos 	}
    239  1.1.1.3  christos 	/* if data_len != 0 here, then the svcparam is malformed. */
    240  1.1.1.3  christos 	return 0;
    241  1.1.1.3  christos }
    242  1.1.1.3  christos 
    243  1.1.1.3  christos /**
    244  1.1.1.3  christos  * Check if svcparam ipv6hint contains a private address.
    245  1.1.1.3  christos  * @param priv: private address lookup struct.
    246  1.1.1.3  christos  * @param d: the data bytes.
    247  1.1.1.3  christos  * @param data_len: number of data bytes in the svcparam.
    248  1.1.1.3  christos  * @param addr: address to return the private address to log in to.
    249  1.1.1.3  christos  *	It has space for IPv4 and IPv6 addresses.
    250  1.1.1.3  christos  * @param addrlen: length of the addr. Returns the correct size for the addr.
    251  1.1.1.3  christos  * @return true if the rdata contains a private address.
    252  1.1.1.3  christos  */
    253  1.1.1.3  christos static int svcb_ipv6hint_contains_priv_addr(struct iter_priv* priv,
    254  1.1.1.3  christos 	uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
    255  1.1.1.3  christos 	socklen_t* addrlen)
    256  1.1.1.3  christos {
    257  1.1.1.3  christos 	struct sockaddr_in6 sa;
    258  1.1.1.3  christos 	*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
    259  1.1.1.3  christos 	memset(&sa, 0, sizeof(struct sockaddr_in6));
    260  1.1.1.3  christos 	sa.sin6_family = AF_INET6;
    261  1.1.1.3  christos 	sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
    262  1.1.1.3  christos 
    263  1.1.1.3  christos 	while(data_len >= LDNS_IP6ADDRLEN) {
    264  1.1.1.3  christos 		memmove(&sa.sin6_addr, d, LDNS_IP6ADDRLEN);
    265  1.1.1.3  christos 		memmove(addr, &sa, *addrlen);
    266  1.1.1.3  christos 		if(priv_lookup_addr(priv, addr, *addrlen))
    267  1.1.1.3  christos 			return 1;
    268  1.1.1.3  christos 
    269  1.1.1.3  christos 		d += LDNS_IP6ADDRLEN;
    270  1.1.1.3  christos 		data_len -= LDNS_IP6ADDRLEN;
    271  1.1.1.3  christos 	}
    272  1.1.1.3  christos 	/* if data_len != 0 here, then the svcparam is malformed. */
    273  1.1.1.3  christos 	return 0;
    274  1.1.1.3  christos }
    275  1.1.1.3  christos 
    276  1.1.1.3  christos /**
    277  1.1.1.3  christos  * Check if type SVCB and HTTPS rdata contains a private address.
    278  1.1.1.3  christos  * @param priv: private address lookup struct.
    279  1.1.1.3  christos  * @param pkt: the packet.
    280  1.1.1.3  christos  * @param rr: the rr with rdata to check.
    281  1.1.1.3  christos  * @param addr: address to return the private address to log in to.
    282  1.1.1.3  christos  * @param addrlen: length of the addr. Initially the total size, on
    283  1.1.1.3  christos  *	return the correct size for the addr.
    284  1.1.1.3  christos  * @return true if the rdata contains a private address.
    285  1.1.1.3  christos  */
    286  1.1.1.3  christos static int svcb_rr_contains_priv_addr(struct iter_priv* priv,
    287  1.1.1.3  christos 	sldns_buffer* pkt, struct rr_parse* rr, struct sockaddr_storage* addr,
    288  1.1.1.3  christos 	socklen_t* addrlen)
    289  1.1.1.3  christos {
    290  1.1.1.3  christos 	uint8_t* d = rr->ttl_data;
    291  1.1.1.3  christos 	uint16_t svcparamkey, data_len, rdatalen;
    292  1.1.1.3  christos 	size_t oldpos, dname_len, dname_start, dname_compr_len;
    293  1.1.1.3  christos 	d += 4; /* skip TTL */
    294  1.1.1.3  christos 	rdatalen = sldns_read_uint16(d); /* read rdata length */
    295  1.1.1.3  christos 	d += 2;
    296  1.1.1.3  christos 
    297  1.1.1.3  christos 	if(rdatalen < 2 /* priority */ + 1 /* 1 length target */)
    298  1.1.1.3  christos 		return 0; /* malformed, too short */
    299  1.1.1.3  christos 	d += 2; /* skip priority */
    300  1.1.1.3  christos 	rdatalen -= 2;
    301  1.1.1.3  christos 	oldpos = sldns_buffer_position(pkt);
    302  1.1.1.3  christos 	sldns_buffer_set_position(pkt, (size_t)(d - sldns_buffer_begin(pkt)));
    303  1.1.1.3  christos 	dname_start = sldns_buffer_position(pkt);
    304  1.1.1.3  christos 	dname_len = pkt_dname_len(pkt);
    305  1.1.1.3  christos 	dname_compr_len = sldns_buffer_position(pkt) - dname_start;
    306  1.1.1.3  christos 	sldns_buffer_set_position(pkt, oldpos);
    307  1.1.1.3  christos 	if(dname_len == 0)
    308  1.1.1.3  christos 		return 0; /* dname malformed */
    309  1.1.1.3  christos 	if(dname_compr_len > rdatalen)
    310  1.1.1.3  christos 		return 0; /* malformed */
    311  1.1.1.3  christos 	d += dname_compr_len; /* skip target */
    312  1.1.1.3  christos 	rdatalen -= dname_compr_len;
    313  1.1.1.3  christos 
    314  1.1.1.3  christos 	while(rdatalen >= 4) {
    315  1.1.1.3  christos 		svcparamkey = sldns_read_uint16(d);
    316  1.1.1.3  christos 		data_len = sldns_read_uint16(d+2);
    317  1.1.1.3  christos 		d += 4;
    318  1.1.1.3  christos 		rdatalen -= 4;
    319  1.1.1.3  christos 
    320  1.1.1.3  christos 		/* verify that we have data_len data */
    321  1.1.1.3  christos 		if(data_len > rdatalen) {
    322  1.1.1.3  christos 			/* It is malformed, but if there are addresses
    323  1.1.1.3  christos 			 * in there it can be rejected. */
    324  1.1.1.3  christos 			data_len = rdatalen;
    325  1.1.1.3  christos 		}
    326  1.1.1.3  christos 
    327  1.1.1.3  christos 		if(!data_len)
    328  1.1.1.3  christos 			continue; /* no data for the svcparamkey */
    329  1.1.1.3  christos 
    330  1.1.1.3  christos 		if(svcparamkey == SVCB_KEY_IPV4HINT) {
    331  1.1.1.3  christos 			if(svcb_ipv4hint_contains_priv_addr(priv, d, data_len,
    332  1.1.1.3  christos 				addr, addrlen))
    333  1.1.1.3  christos 				return 1;
    334  1.1.1.3  christos 		} else if(svcparamkey == SVCB_KEY_IPV6HINT) {
    335  1.1.1.3  christos 			if(svcb_ipv6hint_contains_priv_addr(priv, d, data_len,
    336  1.1.1.3  christos 				addr, addrlen))
    337  1.1.1.3  christos 				return 1;
    338  1.1.1.3  christos 		}
    339  1.1.1.3  christos 		d += data_len;
    340  1.1.1.3  christos 		rdatalen -= data_len;
    341  1.1.1.3  christos 	}
    342  1.1.1.3  christos 	/* If rdatalen != 0 here, then the svcb rdata is malformed. */
    343  1.1.1.3  christos 	return 0;
    344  1.1.1.3  christos }
    345  1.1.1.3  christos 
    346  1.1.1.3  christos /**
    347  1.1.1.3  christos  * Check if the SVCB and HTTPS rrset is bad.
    348  1.1.1.3  christos  * @param priv: private address lookup struct.
    349  1.1.1.3  christos  * @param pkt: the packet.
    350  1.1.1.3  christos  * @param rrset: the rrset to check.
    351  1.1.1.3  christos  * @return 1 if the entire rrset has to be removed. 0 if not.
    352  1.1.1.3  christos  * It removes RRs if they have private addresses, and log that.
    353  1.1.1.3  christos  */
    354  1.1.1.3  christos static int priv_svcb_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
    355  1.1.1.3  christos 	struct rrset_parse* rrset)
    356  1.1.1.3  christos {
    357  1.1.1.3  christos 	struct rr_parse* rr, *prev = NULL;
    358  1.1.1.3  christos 	struct sockaddr_storage addr;
    359  1.1.1.3  christos 	socklen_t addrlen = (socklen_t)sizeof(addr);
    360  1.1.1.3  christos 	for(rr = rrset->rr_first; rr; rr = rr->next) {
    361  1.1.1.3  christos 		if(svcb_rr_contains_priv_addr(priv, pkt, rr, &addr,
    362  1.1.1.3  christos 			&addrlen)) {
    363  1.1.1.3  christos 			if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, addrlen))
    364  1.1.1.3  christos 				return 1;
    365  1.1.1.3  christos 			continue;
    366  1.1.1.3  christos 		}
    367  1.1.1.3  christos 		prev = rr;
    368  1.1.1.3  christos 	}
    369  1.1.1.3  christos 	return 0;
    370  1.1.1.3  christos }
    371  1.1.1.3  christos 
    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.3  christos 		} else if(rrset->type == LDNS_RR_TYPE_SVCB ||
    434  1.1.1.3  christos 			rrset->type == LDNS_RR_TYPE_HTTPS) {
    435  1.1.1.3  christos 			if(priv_svcb_rrset_bad(priv, pkt, rrset))
    436  1.1.1.3  christos 				return 1;
    437  1.1.1.3  christos 		}
    438      1.1  christos 	}
    439      1.1  christos 	return 0;
    440      1.1  christos }
    441