Home | History | Annotate | Line # | Download | only in iterator
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