Home | History | Annotate | Line # | Download | only in dns
rpz.c revision 1.12
      1  1.12  christos /*	$NetBSD: rpz.c,v 1.12 2023/01/25 21:43:30 christos Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*
      4   1.1  christos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5   1.1  christos  *
      6  1.11  christos  * SPDX-License-Identifier: MPL-2.0
      7  1.11  christos  *
      8   1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      9   1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10   1.9  christos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11   1.1  christos  *
     12   1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     13   1.1  christos  * information regarding copyright ownership.
     14   1.1  christos  */
     15   1.1  christos 
     16   1.1  christos /*! \file */
     17   1.1  christos 
     18   1.3  christos #include <inttypes.h>
     19   1.3  christos #include <stdbool.h>
     20   1.3  christos #include <stdlib.h>
     21   1.3  christos 
     22   1.1  christos #include <isc/buffer.h>
     23   1.1  christos #include <isc/mem.h>
     24   1.1  christos #include <isc/net.h>
     25   1.1  christos #include <isc/netaddr.h>
     26   1.1  christos #include <isc/print.h>
     27   1.1  christos #include <isc/rwlock.h>
     28   1.1  christos #include <isc/string.h>
     29   1.1  christos #include <isc/task.h>
     30   1.1  christos #include <isc/util.h>
     31   1.1  christos 
     32   1.1  christos #include <dns/db.h>
     33   1.1  christos #include <dns/dbiterator.h>
     34   1.1  christos #include <dns/dnsrps.h>
     35   1.1  christos #include <dns/events.h>
     36   1.1  christos #include <dns/fixedname.h>
     37   1.1  christos #include <dns/log.h>
     38   1.7  christos #include <dns/rbt.h>
     39   1.1  christos #include <dns/rdata.h>
     40   1.1  christos #include <dns/rdataset.h>
     41   1.7  christos #include <dns/rdatasetiter.h>
     42   1.1  christos #include <dns/rdatastruct.h>
     43   1.1  christos #include <dns/result.h>
     44   1.1  christos #include <dns/rpz.h>
     45   1.1  christos #include <dns/view.h>
     46   1.1  christos 
     47   1.1  christos /*
     48   1.1  christos  * Parallel radix trees for databases of response policy IP addresses
     49   1.1  christos  *
     50   1.1  christos  * The radix or patricia trees are somewhat specialized to handle response
     51   1.1  christos  * policy addresses by representing the two sets of IP addresses and name
     52   1.1  christos  * server IP addresses in a single tree.  One set of IP addresses is
     53   1.1  christos  * for rpz-ip policies or policies triggered by addresses in A or
     54   1.1  christos  * AAAA records in responses.
     55   1.1  christos  * The second set is for rpz-nsip policies or policies triggered by addresses
     56   1.1  christos  * in A or AAAA records for NS records that are authorities for responses.
     57   1.1  christos  *
     58   1.1  christos  * Each leaf indicates that an IP address is listed in the IP address or the
     59   1.1  christos  * name server IP address policy sub-zone (or both) of the corresponding
     60   1.1  christos  * response policy zone.  The policy data such as a CNAME or an A record
     61   1.1  christos  * is kept in the policy zone.  After an IP address has been found in a radix
     62   1.1  christos  * tree, the node in the policy zone's database is found by converting
     63   1.1  christos  * the IP address to a domain name in a canonical form.
     64   1.1  christos  *
     65   1.1  christos  *
     66   1.1  christos  * The response policy zone canonical form of an IPv6 address is one of:
     67   1.1  christos  *	prefix.W.W.W.W.W.W.W.W
     68   1.1  christos  *	prefix.WORDS.zz
     69   1.1  christos  *	prefix.WORDS.zz.WORDS
     70   1.1  christos  *	prefix.zz.WORDS
     71   1.1  christos  *  where
     72   1.1  christos  *	prefix	is the prefix length of the IPv6 address between 1 and 128
     73   1.1  christos  *	W	is a number between 0 and 65535
     74   1.1  christos  *	WORDS	is one or more numbers W separated with "."
     75   1.1  christos  *	zz	corresponds to :: in the standard IPv6 text representation
     76   1.1  christos  *
     77   1.1  christos  * The canonical form of IPv4 addresses is:
     78   1.1  christos  *	prefix.B.B.B.B
     79   1.1  christos  *  where
     80   1.1  christos  *	prefix	is the prefix length of the address between 1 and 32
     81   1.1  christos  *	B	is a number between 0 and 255
     82   1.1  christos  *
     83   1.1  christos  * Names for IPv4 addresses are distinguished from IPv6 addresses by having
     84   1.1  christos  * 5 labels all of which are numbers, and a prefix between 1 and 32.
     85   1.1  christos  */
     86   1.1  christos 
     87   1.1  christos /*
     88   1.1  christos  * Nodes hashtable calculation parameters
     89   1.1  christos  */
     90   1.7  christos #define DNS_RPZ_HTSIZE_MAX 24
     91   1.7  christos #define DNS_RPZ_HTSIZE_DIV 3
     92   1.1  christos 
     93   1.1  christos /*
     94   1.1  christos  * Maximum number of nodes to process per quantum
     95   1.1  christos  */
     96   1.1  christos #define DNS_RPZ_QUANTUM 1024
     97   1.1  christos 
     98   1.1  christos static void
     99   1.1  christos dns_rpz_update_from_db(dns_rpz_zone_t *rpz);
    100   1.1  christos 
    101   1.1  christos static void
    102   1.1  christos dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event);
    103   1.1  christos 
    104   1.1  christos /*
    105   1.1  christos  * Use a private definition of IPv6 addresses because s6_addr32 is not
    106   1.1  christos  * always defined and our IPv6 addresses are in non-standard byte order
    107   1.1  christos  */
    108   1.7  christos typedef uint32_t dns_rpz_cidr_word_t;
    109   1.7  christos #define DNS_RPZ_CIDR_WORD_BITS ((int)sizeof(dns_rpz_cidr_word_t) * 8)
    110   1.7  christos #define DNS_RPZ_CIDR_KEY_BITS  ((int)sizeof(dns_rpz_cidr_key_t) * 8)
    111   1.7  christos #define DNS_RPZ_CIDR_WORDS     (128 / DNS_RPZ_CIDR_WORD_BITS)
    112   1.1  christos typedef struct {
    113   1.7  christos 	dns_rpz_cidr_word_t w[DNS_RPZ_CIDR_WORDS];
    114   1.1  christos } dns_rpz_cidr_key_t;
    115   1.1  christos 
    116   1.7  christos #define ADDR_V4MAPPED 0xffff
    117   1.7  christos #define KEY_IS_IPV4(prefix, ip)                                  \
    118   1.7  christos 	((prefix) >= 96 && (ip)->w[0] == 0 && (ip)->w[1] == 0 && \
    119   1.7  christos 	 (ip)->w[2] == ADDR_V4MAPPED)
    120   1.7  christos 
    121   1.7  christos #define DNS_RPZ_WORD_MASK(b)                   \
    122   1.7  christos 	((b) == 0 ? (dns_rpz_cidr_word_t)(-1)  \
    123   1.7  christos 		  : ((dns_rpz_cidr_word_t)(-1) \
    124   1.7  christos 		     << (DNS_RPZ_CIDR_WORD_BITS - (b))))
    125   1.1  christos 
    126   1.1  christos /*
    127   1.1  christos  * Get bit #n from the array of words of an IP address.
    128   1.1  christos  */
    129   1.7  christos #define DNS_RPZ_IP_BIT(ip, n)                          \
    130   1.7  christos 	(1 & ((ip)->w[(n) / DNS_RPZ_CIDR_WORD_BITS] >> \
    131   1.7  christos 	      (DNS_RPZ_CIDR_WORD_BITS - 1 - ((n) % DNS_RPZ_CIDR_WORD_BITS))))
    132   1.1  christos 
    133   1.1  christos /*
    134   1.1  christos  * A triplet of arrays of bits flagging the existence of
    135   1.1  christos  * client-IP, IP, and NSIP policy triggers.
    136   1.1  christos  */
    137   1.1  christos typedef struct dns_rpz_addr_zbits dns_rpz_addr_zbits_t;
    138   1.1  christos struct dns_rpz_addr_zbits {
    139   1.7  christos 	dns_rpz_zbits_t client_ip;
    140   1.7  christos 	dns_rpz_zbits_t ip;
    141   1.7  christos 	dns_rpz_zbits_t nsip;
    142   1.1  christos };
    143   1.1  christos 
    144   1.1  christos /*
    145   1.1  christos  * A CIDR or radix tree node.
    146   1.1  christos  */
    147   1.1  christos struct dns_rpz_cidr_node {
    148   1.7  christos 	dns_rpz_cidr_node_t *parent;
    149   1.7  christos 	dns_rpz_cidr_node_t *child[2];
    150   1.7  christos 	dns_rpz_cidr_key_t ip;
    151   1.7  christos 	dns_rpz_prefix_t prefix;
    152   1.7  christos 	dns_rpz_addr_zbits_t set;
    153   1.7  christos 	dns_rpz_addr_zbits_t sum;
    154   1.1  christos };
    155   1.1  christos 
    156   1.1  christos /*
    157   1.1  christos  * A pair of arrays of bits flagging the existence of
    158   1.1  christos  * QNAME and NSDNAME policy triggers.
    159   1.1  christos  */
    160   1.1  christos typedef struct dns_rpz_nm_zbits dns_rpz_nm_zbits_t;
    161   1.1  christos struct dns_rpz_nm_zbits {
    162   1.7  christos 	dns_rpz_zbits_t qname;
    163   1.7  christos 	dns_rpz_zbits_t ns;
    164   1.1  christos };
    165   1.1  christos 
    166   1.1  christos /*
    167   1.1  christos  * The data in a RBT node has two pairs of bits for policy zones.
    168   1.1  christos  * One pair is for the corresponding name of the node such as example.com
    169   1.1  christos  * and the other pair is for a wildcard child such as *.example.com.
    170   1.1  christos  */
    171   1.1  christos typedef struct dns_rpz_nm_data dns_rpz_nm_data_t;
    172   1.1  christos struct dns_rpz_nm_data {
    173   1.7  christos 	dns_rpz_nm_zbits_t set;
    174   1.7  christos 	dns_rpz_nm_zbits_t wild;
    175   1.1  christos };
    176   1.1  christos 
    177   1.5  christos static void
    178   1.5  christos rpz_detach(dns_rpz_zone_t **rpzp);
    179   1.5  christos 
    180   1.5  christos static void
    181   1.5  christos rpz_detach_rpzs(dns_rpz_zones_t **rpzsp);
    182   1.5  christos 
    183   1.1  christos #if 0
    184   1.1  christos /*
    185   1.1  christos  * Catch a name while debugging.
    186   1.1  christos  */
    187   1.1  christos static void
    188   1.1  christos catch_name(const dns_name_t *src_name, const char *tgt, const char *str) {
    189   1.1  christos 	dns_fixedname_t tgt_namef;
    190   1.1  christos 	dns_name_t *tgt_name;
    191   1.1  christos 
    192   1.1  christos 	tgt_name = dns_fixedname_initname(&tgt_namef);
    193   1.1  christos 	dns_name_fromstring(tgt_name, tgt, DNS_NAME_DOWNCASE, NULL);
    194   1.1  christos 	if (dns_name_equal(src_name, tgt_name)) {
    195   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
    196   1.1  christos 			      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
    197   1.1  christos 			      "rpz hit failed: %s %s", str, tgt);
    198   1.1  christos 	}
    199   1.1  christos }
    200   1.7  christos #endif /* if 0 */
    201   1.1  christos 
    202   1.1  christos const char *
    203   1.1  christos dns_rpz_type2str(dns_rpz_type_t type) {
    204   1.1  christos 	switch (type) {
    205   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
    206   1.1  christos 		return ("CLIENT-IP");
    207   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
    208   1.1  christos 		return ("QNAME");
    209   1.1  christos 	case DNS_RPZ_TYPE_IP:
    210   1.1  christos 		return ("IP");
    211   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
    212   1.1  christos 		return ("NSIP");
    213   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
    214   1.1  christos 		return ("NSDNAME");
    215   1.1  christos 	case DNS_RPZ_TYPE_BAD:
    216   1.1  christos 		break;
    217   1.1  christos 	}
    218   1.1  christos 	FATAL_ERROR(__FILE__, __LINE__, "impossible rpz type %d", type);
    219   1.1  christos 	return ("impossible");
    220   1.1  christos }
    221   1.1  christos 
    222   1.1  christos dns_rpz_policy_t
    223   1.1  christos dns_rpz_str2policy(const char *str) {
    224   1.1  christos 	static struct {
    225   1.1  christos 		const char *str;
    226   1.1  christos 		dns_rpz_policy_t policy;
    227   1.1  christos 	} tbl[] = {
    228   1.7  christos 		{ "given", DNS_RPZ_POLICY_GIVEN },
    229   1.7  christos 		{ "disabled", DNS_RPZ_POLICY_DISABLED },
    230   1.7  christos 		{ "passthru", DNS_RPZ_POLICY_PASSTHRU },
    231   1.7  christos 		{ "drop", DNS_RPZ_POLICY_DROP },
    232   1.7  christos 		{ "tcp-only", DNS_RPZ_POLICY_TCP_ONLY },
    233   1.7  christos 		{ "nxdomain", DNS_RPZ_POLICY_NXDOMAIN },
    234   1.7  christos 		{ "nodata", DNS_RPZ_POLICY_NODATA },
    235   1.7  christos 		{ "cname", DNS_RPZ_POLICY_CNAME },
    236   1.7  christos 		{ "no-op", DNS_RPZ_POLICY_PASSTHRU }, /* old passthru */
    237   1.1  christos 	};
    238   1.1  christos 	unsigned int n;
    239   1.1  christos 
    240   1.7  christos 	if (str == NULL) {
    241   1.1  christos 		return (DNS_RPZ_POLICY_ERROR);
    242   1.7  christos 	}
    243   1.7  christos 	for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n) {
    244   1.7  christos 		if (!strcasecmp(tbl[n].str, str)) {
    245   1.1  christos 			return (tbl[n].policy);
    246   1.7  christos 		}
    247   1.1  christos 	}
    248   1.1  christos 	return (DNS_RPZ_POLICY_ERROR);
    249   1.1  christos }
    250   1.1  christos 
    251   1.1  christos const char *
    252   1.1  christos dns_rpz_policy2str(dns_rpz_policy_t policy) {
    253   1.1  christos 	const char *str;
    254   1.1  christos 
    255   1.1  christos 	switch (policy) {
    256   1.1  christos 	case DNS_RPZ_POLICY_PASSTHRU:
    257   1.1  christos 		str = "PASSTHRU";
    258   1.1  christos 		break;
    259   1.1  christos 	case DNS_RPZ_POLICY_DROP:
    260   1.1  christos 		str = "DROP";
    261   1.1  christos 		break;
    262   1.1  christos 	case DNS_RPZ_POLICY_TCP_ONLY:
    263   1.1  christos 		str = "TCP-ONLY";
    264   1.1  christos 		break;
    265   1.1  christos 	case DNS_RPZ_POLICY_NXDOMAIN:
    266   1.1  christos 		str = "NXDOMAIN";
    267   1.1  christos 		break;
    268   1.1  christos 	case DNS_RPZ_POLICY_NODATA:
    269   1.1  christos 		str = "NODATA";
    270   1.1  christos 		break;
    271   1.1  christos 	case DNS_RPZ_POLICY_RECORD:
    272   1.1  christos 		str = "Local-Data";
    273   1.1  christos 		break;
    274   1.1  christos 	case DNS_RPZ_POLICY_CNAME:
    275   1.1  christos 	case DNS_RPZ_POLICY_WILDCNAME:
    276   1.1  christos 		str = "CNAME";
    277   1.1  christos 		break;
    278   1.1  christos 	case DNS_RPZ_POLICY_MISS:
    279   1.1  christos 		str = "MISS";
    280   1.1  christos 		break;
    281   1.5  christos 	case DNS_RPZ_POLICY_DNS64:
    282   1.5  christos 		str = "DNS64";
    283   1.5  christos 		break;
    284  1.11  christos 	case DNS_RPZ_POLICY_ERROR:
    285  1.11  christos 		str = "ERROR";
    286  1.11  christos 		break;
    287   1.1  christos 	default:
    288  1.11  christos 		UNREACHABLE();
    289   1.1  christos 	}
    290   1.1  christos 	return (str);
    291   1.1  christos }
    292   1.1  christos 
    293   1.1  christos /*
    294   1.1  christos  * Return the bit number of the highest set bit in 'zbit'.
    295   1.1  christos  * (for example, 0x01 returns 0, 0xFF returns 7, etc.)
    296   1.1  christos  */
    297   1.1  christos static int
    298   1.1  christos zbit_to_num(dns_rpz_zbits_t zbit) {
    299   1.1  christos 	dns_rpz_num_t rpz_num;
    300   1.1  christos 
    301   1.1  christos 	REQUIRE(zbit != 0);
    302   1.1  christos 	rpz_num = 0;
    303   1.3  christos 	if ((zbit & 0xffffffff00000000ULL) != 0) {
    304   1.1  christos 		zbit >>= 32;
    305   1.1  christos 		rpz_num += 32;
    306   1.1  christos 	}
    307   1.1  christos 	if ((zbit & 0xffff0000) != 0) {
    308   1.1  christos 		zbit >>= 16;
    309   1.1  christos 		rpz_num += 16;
    310   1.1  christos 	}
    311   1.1  christos 	if ((zbit & 0xff00) != 0) {
    312   1.1  christos 		zbit >>= 8;
    313   1.1  christos 		rpz_num += 8;
    314   1.1  christos 	}
    315   1.1  christos 	if ((zbit & 0xf0) != 0) {
    316   1.1  christos 		zbit >>= 4;
    317   1.1  christos 		rpz_num += 4;
    318   1.1  christos 	}
    319   1.1  christos 	if ((zbit & 0xc) != 0) {
    320   1.1  christos 		zbit >>= 2;
    321   1.1  christos 		rpz_num += 2;
    322   1.1  christos 	}
    323   1.7  christos 	if ((zbit & 2) != 0) {
    324   1.1  christos 		++rpz_num;
    325   1.7  christos 	}
    326   1.1  christos 	return (rpz_num);
    327   1.1  christos }
    328   1.1  christos 
    329   1.1  christos /*
    330   1.1  christos  * Make a set of bit masks given one or more bits and their type.
    331   1.1  christos  */
    332   1.1  christos static void
    333   1.1  christos make_addr_set(dns_rpz_addr_zbits_t *tgt_set, dns_rpz_zbits_t zbits,
    334   1.7  christos 	      dns_rpz_type_t type) {
    335   1.1  christos 	switch (type) {
    336   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
    337   1.1  christos 		tgt_set->client_ip = zbits;
    338   1.1  christos 		tgt_set->ip = 0;
    339   1.1  christos 		tgt_set->nsip = 0;
    340   1.1  christos 		break;
    341   1.1  christos 	case DNS_RPZ_TYPE_IP:
    342   1.1  christos 		tgt_set->client_ip = 0;
    343   1.1  christos 		tgt_set->ip = zbits;
    344   1.1  christos 		tgt_set->nsip = 0;
    345   1.1  christos 		break;
    346   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
    347   1.1  christos 		tgt_set->client_ip = 0;
    348   1.1  christos 		tgt_set->ip = 0;
    349   1.1  christos 		tgt_set->nsip = zbits;
    350   1.1  christos 		break;
    351   1.1  christos 	default:
    352  1.11  christos 		UNREACHABLE();
    353   1.1  christos 	}
    354   1.1  christos }
    355   1.1  christos 
    356   1.1  christos static void
    357   1.7  christos make_nm_set(dns_rpz_nm_zbits_t *tgt_set, dns_rpz_num_t rpz_num,
    358   1.7  christos 	    dns_rpz_type_t type) {
    359   1.1  christos 	switch (type) {
    360   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
    361   1.1  christos 		tgt_set->qname = DNS_RPZ_ZBIT(rpz_num);
    362   1.1  christos 		tgt_set->ns = 0;
    363   1.1  christos 		break;
    364   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
    365   1.1  christos 		tgt_set->qname = 0;
    366   1.1  christos 		tgt_set->ns = DNS_RPZ_ZBIT(rpz_num);
    367   1.1  christos 		break;
    368   1.1  christos 	default:
    369  1.11  christos 		UNREACHABLE();
    370   1.1  christos 	}
    371   1.1  christos }
    372   1.1  christos 
    373   1.1  christos /*
    374   1.1  christos  * Mark a node and all of its parents as having client-IP, IP, or NSIP data
    375   1.1  christos  */
    376   1.1  christos static void
    377   1.1  christos set_sum_pair(dns_rpz_cidr_node_t *cnode) {
    378   1.1  christos 	dns_rpz_cidr_node_t *child;
    379   1.1  christos 	dns_rpz_addr_zbits_t sum;
    380   1.1  christos 
    381   1.1  christos 	do {
    382   1.1  christos 		sum = cnode->set;
    383   1.1  christos 
    384   1.1  christos 		child = cnode->child[0];
    385   1.1  christos 		if (child != NULL) {
    386   1.1  christos 			sum.client_ip |= child->sum.client_ip;
    387   1.1  christos 			sum.ip |= child->sum.ip;
    388   1.1  christos 			sum.nsip |= child->sum.nsip;
    389   1.1  christos 		}
    390   1.1  christos 
    391   1.1  christos 		child = cnode->child[1];
    392   1.1  christos 		if (child != NULL) {
    393   1.1  christos 			sum.client_ip |= child->sum.client_ip;
    394   1.1  christos 			sum.ip |= child->sum.ip;
    395   1.1  christos 			sum.nsip |= child->sum.nsip;
    396   1.1  christos 		}
    397   1.1  christos 
    398   1.1  christos 		if (cnode->sum.client_ip == sum.client_ip &&
    399   1.7  christos 		    cnode->sum.ip == sum.ip && cnode->sum.nsip == sum.nsip)
    400   1.7  christos 		{
    401   1.1  christos 			break;
    402   1.7  christos 		}
    403   1.1  christos 		cnode->sum = sum;
    404   1.1  christos 		cnode = cnode->parent;
    405   1.1  christos 	} while (cnode != NULL);
    406   1.1  christos }
    407   1.1  christos 
    408   1.1  christos /* Caller must hold rpzs->maint_lock */
    409   1.1  christos static void
    410   1.1  christos fix_qname_skip_recurse(dns_rpz_zones_t *rpzs) {
    411   1.1  christos 	dns_rpz_zbits_t mask;
    412   1.1  christos 
    413   1.1  christos 	/*
    414   1.1  christos 	 * qname_wait_recurse and qname_skip_recurse are used to
    415   1.1  christos 	 * implement the "qname-wait-recurse" config option.
    416   1.1  christos 	 *
    417   1.1  christos 	 * When "qname-wait-recurse" is yes, no processing happens without
    418   1.1  christos 	 * recursion. In this case, qname_wait_recurse is true, and
    419   1.1  christos 	 * qname_skip_recurse (a bit field indicating which policy zones
    420   1.1  christos 	 * can be processed without recursion) is set to all 0's by
    421   1.1  christos 	 * fix_qname_skip_recurse().
    422   1.1  christos 	 *
    423   1.1  christos 	 * When "qname-wait-recurse" is no, qname_skip_recurse may be
    424   1.1  christos 	 * set to a non-zero value by fix_qname_skip_recurse(). The mask
    425   1.1  christos 	 * has to have bits set for the policy zones for which
    426   1.1  christos 	 * processing may continue without recursion, and bits cleared
    427   1.1  christos 	 * for the rest.
    428   1.1  christos 	 *
    429   1.1  christos 	 * (1) The ARM says:
    430   1.1  christos 	 *
    431   1.1  christos 	 *   The "qname-wait-recurse no" option overrides that default
    432   1.1  christos 	 *   behavior when recursion cannot change a non-error
    433   1.1  christos 	 *   response. The option does not affect QNAME or client-IP
    434   1.1  christos 	 *   triggers in policy zones listed after other zones
    435   1.1  christos 	 *   containing IP, NSIP and NSDNAME triggers, because those may
    436   1.1  christos 	 *   depend on the A, AAAA, and NS records that would be found
    437   1.1  christos 	 *   during recursive resolution.
    438   1.1  christos 	 *
    439   1.1  christos 	 * Let's consider the following:
    440   1.1  christos 	 *
    441   1.1  christos 	 *     zbits_req = (rpzs->have.ipv4 | rpzs->have.ipv6 |
    442   1.1  christos 	 *		    rpzs->have.nsdname |
    443   1.1  christos 	 *		    rpzs->have.nsipv4 | rpzs->have.nsipv6);
    444   1.1  christos 	 *
    445   1.1  christos 	 * zbits_req now contains bits set for zones which require
    446   1.1  christos 	 * recursion.
    447   1.1  christos 	 *
    448   1.1  christos 	 * But going by the description in the ARM, if the first policy
    449   1.1  christos 	 * zone requires recursion, then all zones after that (higher
    450   1.1  christos 	 * order bits) have to wait as well.  If the Nth zone requires
    451   1.1  christos 	 * recursion, then (N+1)th zone onwards all need to wait.
    452   1.1  christos 	 *
    453   1.1  christos 	 * So mapping this, examples:
    454   1.1  christos 	 *
    455   1.1  christos 	 * zbits_req = 0b000  mask = 0xffffffff (no zones have to wait for
    456   1.1  christos 	 *					 recursion)
    457   1.1  christos 	 * zbits_req = 0b001  mask = 0x00000000 (all zones have to wait)
    458   1.1  christos 	 * zbits_req = 0b010  mask = 0x00000001 (the first zone doesn't have to
    459   1.1  christos 	 *					 wait, second zone onwards need
    460   1.1  christos 	 *					 to wait)
    461   1.1  christos 	 * zbits_req = 0b011  mask = 0x00000000 (all zones have to wait)
    462   1.1  christos 	 * zbits_req = 0b100  mask = 0x00000011 (the 1st and 2nd zones don't
    463   1.1  christos 	 *					 have to wait, third zone
    464   1.1  christos 	 *					 onwards need to wait)
    465   1.1  christos 	 *
    466   1.1  christos 	 * More generally, we have to count the number of trailing 0
    467   1.1  christos 	 * bits in zbits_req and only these can be processed without
    468   1.1  christos 	 * recursion. All the rest need to wait.
    469   1.1  christos 	 *
    470   1.1  christos 	 * (2) The ARM says that "qname-wait-recurse no" option
    471   1.1  christos 	 * overrides the default behavior when recursion cannot change a
    472   1.1  christos 	 * non-error response. So, in the order of listing of policy
    473   1.1  christos 	 * zones, within the first policy zone where recursion may be
    474   1.1  christos 	 * required, we should first allow CLIENT-IP and QNAME policy
    475   1.1  christos 	 * records to be attempted without recursion.
    476   1.1  christos 	 */
    477   1.1  christos 
    478   1.1  christos 	/*
    479   1.1  christos 	 * Get a mask covering all policy zones that are not subordinate to
    480   1.1  christos 	 * other policy zones containing triggers that require that the
    481   1.1  christos 	 * qname be resolved before they can be checked.
    482   1.1  christos 	 */
    483   1.1  christos 	rpzs->have.client_ip = rpzs->have.client_ipv4 | rpzs->have.client_ipv6;
    484   1.1  christos 	rpzs->have.ip = rpzs->have.ipv4 | rpzs->have.ipv6;
    485   1.1  christos 	rpzs->have.nsip = rpzs->have.nsipv4 | rpzs->have.nsipv6;
    486   1.1  christos 
    487   1.1  christos 	if (rpzs->p.qname_wait_recurse) {
    488   1.1  christos 		mask = 0;
    489   1.1  christos 	} else {
    490   1.1  christos 		dns_rpz_zbits_t zbits_req;
    491   1.1  christos 		dns_rpz_zbits_t zbits_notreq;
    492   1.1  christos 		dns_rpz_zbits_t mask2;
    493   1.1  christos 		dns_rpz_zbits_t req_mask;
    494   1.1  christos 
    495   1.1  christos 		/*
    496   1.1  christos 		 * Get the masks of zones with policies that
    497   1.1  christos 		 * do/don't require recursion
    498   1.1  christos 		 */
    499   1.1  christos 
    500   1.1  christos 		zbits_req = (rpzs->have.ipv4 | rpzs->have.ipv6 |
    501   1.7  christos 			     rpzs->have.nsdname | rpzs->have.nsipv4 |
    502   1.7  christos 			     rpzs->have.nsipv6);
    503   1.1  christos 		zbits_notreq = (rpzs->have.client_ip | rpzs->have.qname);
    504   1.1  christos 
    505   1.1  christos 		if (zbits_req == 0) {
    506   1.1  christos 			mask = DNS_RPZ_ALL_ZBITS;
    507   1.1  christos 			goto set;
    508   1.1  christos 		}
    509   1.1  christos 
    510   1.1  christos 		/*
    511   1.1  christos 		 * req_mask is a mask covering used bits in
    512   1.1  christos 		 * zbits_req. (For instance, 0b1 => 0b1, 0b101 => 0b111,
    513   1.1  christos 		 * 0b11010101 => 0b11111111).
    514   1.1  christos 		 */
    515   1.1  christos 		req_mask = zbits_req;
    516   1.1  christos 		req_mask |= req_mask >> 1;
    517   1.1  christos 		req_mask |= req_mask >> 2;
    518   1.1  christos 		req_mask |= req_mask >> 4;
    519   1.1  christos 		req_mask |= req_mask >> 8;
    520   1.1  christos 		req_mask |= req_mask >> 16;
    521   1.1  christos 		req_mask |= req_mask >> 32;
    522   1.1  christos 
    523   1.1  christos 		/*
    524   1.1  christos 		 * There's no point in skipping recursion for a later
    525   1.1  christos 		 * zone if it is required in a previous zone.
    526   1.1  christos 		 */
    527   1.1  christos 		if ((zbits_notreq & req_mask) == 0) {
    528   1.1  christos 			mask = 0;
    529   1.1  christos 			goto set;
    530   1.1  christos 		}
    531   1.1  christos 
    532   1.1  christos 		/*
    533   1.1  christos 		 * This bit arithmetic creates a mask of zones in which
    534   1.1  christos 		 * it is okay to skip recursion. After the first zone
    535   1.1  christos 		 * that has to wait for recursion, all the others have
    536   1.1  christos 		 * to wait as well, so we want to create a mask in which
    537   1.1  christos 		 * all the trailing zeroes in zbits_req are are 1, and
    538   1.1  christos 		 * more significant bits are 0. (For instance,
    539   1.1  christos 		 * 0x0700 => 0x00ff, 0x0007 => 0x0000)
    540   1.1  christos 		 */
    541   1.1  christos 		mask = ~(zbits_req | ((~zbits_req) + 1));
    542   1.1  christos 
    543   1.1  christos 		/*
    544   1.1  christos 		 * As mentioned in (2) above, the zone corresponding to
    545   1.1  christos 		 * the least significant zero could have its CLIENT-IP
    546   1.1  christos 		 * and QNAME policies checked before recursion, if it
    547   1.1  christos 		 * has any of those policies.  So if it does, we
    548   1.1  christos 		 * can set its 0 to 1.
    549   1.1  christos 		 *
    550   1.1  christos 		 * Locate the least significant 0 bit in the mask (for
    551   1.1  christos 		 * instance, 0xff => 0x100)...
    552   1.1  christos 		 */
    553   1.1  christos 		mask2 = (mask << 1) & ~mask;
    554   1.1  christos 
    555   1.1  christos 		/*
    556   1.1  christos 		 * Also set the bit for zone 0, because if it's in
    557   1.1  christos 		 * zbits_notreq then it's definitely okay to attempt to
    558   1.1  christos 		 * skip recursion for zone 0...
    559   1.1  christos 		 */
    560   1.1  christos 		mask2 |= 1;
    561   1.1  christos 
    562   1.1  christos 		/* Clear any bits *not* in zbits_notreq... */
    563   1.1  christos 		mask2 &= zbits_notreq;
    564   1.1  christos 
    565   1.1  christos 		/* And merge the result into the skip-recursion mask */
    566   1.1  christos 		mask |= mask2;
    567   1.1  christos 	}
    568   1.1  christos 
    569   1.7  christos set:
    570   1.1  christos 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, DNS_LOGMODULE_RBTDB,
    571   1.1  christos 		      DNS_RPZ_DEBUG_QUIET,
    572   1.3  christos 		      "computed RPZ qname_skip_recurse mask=0x%" PRIx64,
    573   1.7  christos 		      (uint64_t)mask);
    574   1.1  christos 	rpzs->have.qname_skip_recurse = mask;
    575   1.1  christos }
    576   1.1  christos 
    577   1.1  christos static void
    578   1.1  christos adj_trigger_cnt(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
    579   1.7  christos 		dns_rpz_type_t rpz_type, const dns_rpz_cidr_key_t *tgt_ip,
    580   1.7  christos 		dns_rpz_prefix_t tgt_prefix, bool inc) {
    581   1.3  christos 	dns_rpz_trigger_counter_t *cnt = NULL;
    582   1.3  christos 	dns_rpz_zbits_t *have = NULL;
    583   1.1  christos 
    584   1.1  christos 	switch (rpz_type) {
    585   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
    586   1.1  christos 		REQUIRE(tgt_ip != NULL);
    587   1.1  christos 		if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
    588   1.1  christos 			cnt = &rpzs->triggers[rpz_num].client_ipv4;
    589   1.1  christos 			have = &rpzs->have.client_ipv4;
    590   1.1  christos 		} else {
    591   1.1  christos 			cnt = &rpzs->triggers[rpz_num].client_ipv6;
    592   1.1  christos 			have = &rpzs->have.client_ipv6;
    593   1.1  christos 		}
    594   1.1  christos 		break;
    595   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
    596   1.1  christos 		cnt = &rpzs->triggers[rpz_num].qname;
    597   1.1  christos 		have = &rpzs->have.qname;
    598   1.1  christos 		break;
    599   1.1  christos 	case DNS_RPZ_TYPE_IP:
    600   1.1  christos 		REQUIRE(tgt_ip != NULL);
    601   1.1  christos 		if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
    602   1.1  christos 			cnt = &rpzs->triggers[rpz_num].ipv4;
    603   1.1  christos 			have = &rpzs->have.ipv4;
    604   1.1  christos 		} else {
    605   1.1  christos 			cnt = &rpzs->triggers[rpz_num].ipv6;
    606   1.1  christos 			have = &rpzs->have.ipv6;
    607   1.1  christos 		}
    608   1.1  christos 		break;
    609   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
    610   1.1  christos 		cnt = &rpzs->triggers[rpz_num].nsdname;
    611   1.1  christos 		have = &rpzs->have.nsdname;
    612   1.1  christos 		break;
    613   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
    614   1.1  christos 		REQUIRE(tgt_ip != NULL);
    615   1.1  christos 		if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
    616   1.1  christos 			cnt = &rpzs->triggers[rpz_num].nsipv4;
    617   1.1  christos 			have = &rpzs->have.nsipv4;
    618   1.1  christos 		} else {
    619   1.1  christos 			cnt = &rpzs->triggers[rpz_num].nsipv6;
    620   1.1  christos 			have = &rpzs->have.nsipv6;
    621   1.1  christos 		}
    622   1.1  christos 		break;
    623   1.1  christos 	default:
    624  1.11  christos 		UNREACHABLE();
    625   1.1  christos 	}
    626   1.1  christos 
    627   1.1  christos 	if (inc) {
    628   1.1  christos 		if (++*cnt == 1U) {
    629   1.1  christos 			*have |= DNS_RPZ_ZBIT(rpz_num);
    630   1.1  christos 			fix_qname_skip_recurse(rpzs);
    631   1.1  christos 		}
    632   1.1  christos 	} else {
    633   1.1  christos 		REQUIRE(*cnt != 0U);
    634   1.1  christos 		if (--*cnt == 0U) {
    635   1.1  christos 			*have &= ~DNS_RPZ_ZBIT(rpz_num);
    636   1.1  christos 			fix_qname_skip_recurse(rpzs);
    637   1.1  christos 		}
    638   1.1  christos 	}
    639   1.1  christos }
    640   1.1  christos 
    641   1.1  christos static dns_rpz_cidr_node_t *
    642   1.7  christos new_node(dns_rpz_zones_t *rpzs, const dns_rpz_cidr_key_t *ip,
    643   1.7  christos 	 dns_rpz_prefix_t prefix, const dns_rpz_cidr_node_t *child) {
    644   1.1  christos 	dns_rpz_cidr_node_t *node;
    645   1.1  christos 	int i, words, wlen;
    646   1.1  christos 
    647   1.1  christos 	node = isc_mem_get(rpzs->mctx, sizeof(*node));
    648   1.1  christos 	memset(node, 0, sizeof(*node));
    649   1.1  christos 
    650   1.7  christos 	if (child != NULL) {
    651   1.1  christos 		node->sum = child->sum;
    652   1.7  christos 	}
    653   1.1  christos 
    654   1.1  christos 	node->prefix = prefix;
    655   1.1  christos 	words = prefix / DNS_RPZ_CIDR_WORD_BITS;
    656   1.1  christos 	wlen = prefix % DNS_RPZ_CIDR_WORD_BITS;
    657   1.1  christos 	i = 0;
    658   1.1  christos 	while (i < words) {
    659   1.1  christos 		node->ip.w[i] = ip->w[i];
    660   1.1  christos 		++i;
    661   1.1  christos 	}
    662   1.1  christos 	if (wlen != 0) {
    663   1.1  christos 		node->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen);
    664   1.1  christos 		++i;
    665   1.1  christos 	}
    666   1.7  christos 	while (i < DNS_RPZ_CIDR_WORDS) {
    667   1.1  christos 		node->ip.w[i++] = 0;
    668   1.7  christos 	}
    669   1.1  christos 
    670   1.1  christos 	return (node);
    671   1.1  christos }
    672   1.1  christos 
    673   1.1  christos static void
    674   1.1  christos badname(int level, const dns_name_t *name, const char *str1, const char *str2) {
    675   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
    676   1.1  christos 
    677   1.1  christos 	/*
    678   1.1  christos 	 * bin/tests/system/rpz/tests.sh looks for "invalid rpz".
    679   1.1  christos 	 */
    680   1.7  christos 	if (level < DNS_RPZ_DEBUG_QUIET && isc_log_wouldlog(dns_lctx, level)) {
    681   1.1  christos 		dns_name_format(name, namebuf, sizeof(namebuf));
    682   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
    683   1.1  christos 			      DNS_LOGMODULE_RBTDB, level,
    684   1.7  christos 			      "invalid rpz IP address \"%s\"%s%s", namebuf,
    685   1.7  christos 			      str1, str2);
    686   1.1  christos 	}
    687   1.1  christos }
    688   1.1  christos 
    689   1.1  christos /*
    690   1.1  christos  * Convert an IP address from radix tree binary (host byte order) to
    691   1.1  christos  * to its canonical response policy domain name without the origin of the
    692   1.1  christos  * policy zone.
    693   1.1  christos  *
    694   1.1  christos  * Generate a name for an IPv6 address that fits RFC 5952, except that our
    695   1.1  christos  * reversed format requires that when the length of the consecutive 16-bit
    696   1.1  christos  * 0 fields are equal (e.g., 1.0.0.1.0.0.db8.2001 corresponding to
    697   1.1  christos  * 2001:db8:0:0:1:0:0:1), we shorted the last instead of the first
    698   1.1  christos  * (e.g., 1.0.0.1.zz.db8.2001 corresponding to 2001:db8::1:0:0:1).
    699   1.1  christos  */
    700   1.1  christos static isc_result_t
    701   1.1  christos ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix,
    702   1.7  christos 	const dns_name_t *base_name, dns_name_t *ip_name) {
    703   1.1  christos #ifndef INET6_ADDRSTRLEN
    704   1.1  christos #define INET6_ADDRSTRLEN 46
    705   1.7  christos #endif /* ifndef INET6_ADDRSTRLEN */
    706   1.7  christos 	int w[DNS_RPZ_CIDR_WORDS * 2];
    707   1.7  christos 	char str[1 + 8 + 1 + INET6_ADDRSTRLEN + 1];
    708   1.1  christos 	isc_buffer_t buffer;
    709   1.1  christos 	isc_result_t result;
    710   1.1  christos 	int best_first, best_len, cur_first, cur_len;
    711   1.1  christos 	int i, n, len;
    712   1.1  christos 
    713   1.1  christos 	if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) {
    714   1.1  christos 		len = snprintf(str, sizeof(str), "%u.%u.%u.%u.%u",
    715   1.7  christos 			       tgt_prefix - 96U, tgt_ip->w[3] & 0xffU,
    716   1.7  christos 			       (tgt_ip->w[3] >> 8) & 0xffU,
    717   1.7  christos 			       (tgt_ip->w[3] >> 16) & 0xffU,
    718   1.7  christos 			       (tgt_ip->w[3] >> 24) & 0xffU);
    719   1.7  christos 		if (len < 0 || (size_t)len >= sizeof(str)) {
    720   1.1  christos 			return (ISC_R_FAILURE);
    721   1.1  christos 		}
    722   1.1  christos 	} else {
    723   1.1  christos 		len = snprintf(str, sizeof(str), "%d", tgt_prefix);
    724   1.7  christos 		if (len < 0 || (size_t)len >= sizeof(str)) {
    725   1.1  christos 			return (ISC_R_FAILURE);
    726   1.1  christos 		}
    727   1.1  christos 
    728   1.1  christos 		for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) {
    729   1.7  christos 			w[i * 2 + 1] =
    730   1.7  christos 				((tgt_ip->w[DNS_RPZ_CIDR_WORDS - 1 - i] >> 16) &
    731   1.7  christos 				 0xffff);
    732   1.7  christos 			w[i * 2] = tgt_ip->w[DNS_RPZ_CIDR_WORDS - 1 - i] &
    733   1.7  christos 				   0xffff;
    734   1.1  christos 		}
    735   1.1  christos 		/*
    736   1.1  christos 		 * Find the start and length of the first longest sequence
    737   1.1  christos 		 * of zeros in the address.
    738   1.1  christos 		 */
    739   1.1  christos 		best_first = -1;
    740   1.1  christos 		best_len = 0;
    741   1.1  christos 		cur_first = -1;
    742   1.1  christos 		cur_len = 0;
    743   1.7  christos 		for (n = 0; n <= 7; ++n) {
    744   1.1  christos 			if (w[n] != 0) {
    745   1.1  christos 				cur_len = 0;
    746   1.1  christos 				cur_first = -1;
    747   1.1  christos 			} else {
    748   1.1  christos 				++cur_len;
    749   1.1  christos 				if (cur_first < 0) {
    750   1.1  christos 					cur_first = n;
    751   1.1  christos 				} else if (cur_len >= best_len) {
    752   1.1  christos 					best_first = cur_first;
    753   1.1  christos 					best_len = cur_len;
    754   1.1  christos 				}
    755   1.1  christos 			}
    756   1.1  christos 		}
    757   1.1  christos 
    758   1.1  christos 		for (n = 0; n <= 7; ++n) {
    759   1.7  christos 			INSIST(len > 0 && (size_t)len < sizeof(str));
    760   1.1  christos 			if (n == best_first) {
    761   1.7  christos 				i = snprintf(str + len, sizeof(str) - len,
    762   1.7  christos 					     ".zz");
    763   1.1  christos 				n += best_len - 1;
    764   1.1  christos 			} else {
    765   1.7  christos 				i = snprintf(str + len, sizeof(str) - len,
    766   1.7  christos 					     ".%x", w[n]);
    767   1.7  christos 			}
    768   1.7  christos 			if (i < 0 || (size_t)i >= (size_t)(sizeof(str) - len)) {
    769   1.7  christos 				return (ISC_R_FAILURE);
    770   1.1  christos 			}
    771   1.7  christos 			len += i;
    772   1.1  christos 		}
    773   1.1  christos 	}
    774   1.1  christos 
    775   1.1  christos 	isc_buffer_init(&buffer, str, sizeof(str));
    776   1.1  christos 	isc_buffer_add(&buffer, len);
    777   1.1  christos 	result = dns_name_fromtext(ip_name, &buffer, base_name, 0, NULL);
    778   1.1  christos 	return (result);
    779   1.1  christos }
    780   1.1  christos 
    781   1.1  christos /*
    782   1.1  christos  * Determine the type of a name in a response policy zone.
    783   1.1  christos  */
    784   1.1  christos static dns_rpz_type_t
    785   1.7  christos type_from_name(const dns_rpz_zones_t *rpzs, dns_rpz_zone_t *rpz,
    786   1.7  christos 	       const dns_name_t *name) {
    787   1.1  christos 	if (dns_name_issubdomain(name, &rpz->ip)) {
    788   1.1  christos 		return (DNS_RPZ_TYPE_IP);
    789   1.1  christos 	}
    790   1.1  christos 
    791   1.1  christos 	if (dns_name_issubdomain(name, &rpz->client_ip)) {
    792   1.1  christos 		return (DNS_RPZ_TYPE_CLIENT_IP);
    793   1.1  christos 	}
    794   1.1  christos 
    795   1.1  christos 	if ((rpzs->p.nsip_on & DNS_RPZ_ZBIT(rpz->num)) != 0 &&
    796   1.1  christos 	    dns_name_issubdomain(name, &rpz->nsip))
    797   1.1  christos 	{
    798   1.1  christos 		return (DNS_RPZ_TYPE_NSIP);
    799   1.1  christos 	}
    800   1.1  christos 
    801   1.1  christos 	if ((rpzs->p.nsdname_on & DNS_RPZ_ZBIT(rpz->num)) != 0 &&
    802   1.1  christos 	    dns_name_issubdomain(name, &rpz->nsdname))
    803   1.1  christos 	{
    804   1.1  christos 		return (DNS_RPZ_TYPE_NSDNAME);
    805   1.1  christos 	}
    806   1.1  christos 
    807   1.1  christos 	return (DNS_RPZ_TYPE_QNAME);
    808   1.1  christos }
    809   1.1  christos 
    810   1.1  christos /*
    811   1.1  christos  * Convert an IP address from canonical response policy domain name form
    812   1.1  christos  * to radix tree binary (host byte order) for adding or deleting IP or NSIP
    813   1.1  christos  * data.
    814   1.1  christos  */
    815   1.1  christos static isc_result_t
    816   1.7  christos name2ipkey(int log_level, const dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
    817   1.1  christos 	   dns_rpz_type_t rpz_type, const dns_name_t *src_name,
    818   1.1  christos 	   dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t *tgt_prefix,
    819   1.7  christos 	   dns_rpz_addr_zbits_t *new_set) {
    820   1.1  christos 	dns_rpz_zone_t *rpz;
    821   1.1  christos 	char ip_str[DNS_NAME_FORMATSIZE], ip2_str[DNS_NAME_FORMATSIZE];
    822   1.1  christos 	dns_offsets_t ip_name_offsets;
    823   1.1  christos 	dns_fixedname_t ip_name2f;
    824   1.1  christos 	dns_name_t ip_name, *ip_name2;
    825   1.1  christos 	const char *prefix_str, *cp, *end;
    826   1.1  christos 	char *cp2;
    827   1.1  christos 	int ip_labels;
    828   1.1  christos 	dns_rpz_prefix_t prefix;
    829   1.1  christos 	unsigned long prefix_num, l;
    830   1.1  christos 	isc_result_t result;
    831   1.1  christos 	int i;
    832   1.1  christos 
    833   1.1  christos 	REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
    834   1.1  christos 	rpz = rpzs->zones[rpz_num];
    835   1.1  christos 	REQUIRE(rpz != NULL);
    836   1.1  christos 
    837   1.1  christos 	make_addr_set(new_set, DNS_RPZ_ZBIT(rpz_num), rpz_type);
    838   1.1  christos 
    839   1.1  christos 	ip_labels = dns_name_countlabels(src_name);
    840   1.7  christos 	if (rpz_type == DNS_RPZ_TYPE_QNAME) {
    841   1.1  christos 		ip_labels -= dns_name_countlabels(&rpz->origin);
    842   1.7  christos 	} else {
    843   1.1  christos 		ip_labels -= dns_name_countlabels(&rpz->nsdname);
    844   1.7  christos 	}
    845   1.1  christos 	if (ip_labels < 2) {
    846   1.1  christos 		badname(log_level, src_name, "; too short", "");
    847   1.1  christos 		return (ISC_R_FAILURE);
    848   1.1  christos 	}
    849   1.1  christos 	dns_name_init(&ip_name, ip_name_offsets);
    850   1.1  christos 	dns_name_getlabelsequence(src_name, 0, ip_labels, &ip_name);
    851   1.1  christos 
    852   1.1  christos 	/*
    853   1.1  christos 	 * Get text for the IP address
    854   1.1  christos 	 */
    855   1.1  christos 	dns_name_format(&ip_name, ip_str, sizeof(ip_str));
    856   1.7  christos 	end = &ip_str[strlen(ip_str) + 1];
    857   1.1  christos 	prefix_str = ip_str;
    858   1.1  christos 
    859   1.1  christos 	prefix_num = strtoul(prefix_str, &cp2, 10);
    860   1.1  christos 	if (*cp2 != '.') {
    861   1.7  christos 		badname(log_level, src_name, "; invalid leading prefix length",
    862   1.7  christos 			"");
    863   1.1  christos 		return (ISC_R_FAILURE);
    864   1.1  christos 	}
    865   1.1  christos 	/*
    866   1.1  christos 	 * Patch in trailing nul character to print just the length
    867   1.1  christos 	 * label (for various cases below).
    868   1.1  christos 	 */
    869   1.1  christos 	*cp2 = '\0';
    870   1.1  christos 	if (prefix_num < 1U || prefix_num > 128U) {
    871   1.7  christos 		badname(log_level, src_name, "; invalid prefix length of ",
    872   1.7  christos 			prefix_str);
    873   1.1  christos 		return (ISC_R_FAILURE);
    874   1.1  christos 	}
    875   1.7  christos 	cp = cp2 + 1;
    876   1.1  christos 
    877   1.1  christos 	if (--ip_labels == 4 && !strchr(cp, 'z')) {
    878   1.1  christos 		/*
    879   1.1  christos 		 * Convert an IPv4 address
    880   1.1  christos 		 * from the form "prefix.z.y.x.w"
    881   1.1  christos 		 */
    882   1.1  christos 		if (prefix_num > 32U) {
    883   1.1  christos 			badname(log_level, src_name,
    884   1.1  christos 				"; invalid IPv4 prefix length of ", prefix_str);
    885   1.1  christos 			return (ISC_R_FAILURE);
    886   1.1  christos 		}
    887   1.1  christos 		prefix_num += 96;
    888   1.1  christos 		*tgt_prefix = (dns_rpz_prefix_t)prefix_num;
    889   1.1  christos 		tgt_ip->w[0] = 0;
    890   1.1  christos 		tgt_ip->w[1] = 0;
    891   1.1  christos 		tgt_ip->w[2] = ADDR_V4MAPPED;
    892   1.1  christos 		tgt_ip->w[3] = 0;
    893   1.1  christos 		for (i = 0; i < 32; i += 8) {
    894   1.1  christos 			l = strtoul(cp, &cp2, 10);
    895   1.1  christos 			if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) {
    896   1.7  christos 				if (*cp2 == '.') {
    897   1.1  christos 					*cp2 = '\0';
    898   1.7  christos 				}
    899   1.1  christos 				badname(log_level, src_name,
    900   1.1  christos 					"; invalid IPv4 octet ", cp);
    901   1.1  christos 				return (ISC_R_FAILURE);
    902   1.1  christos 			}
    903   1.1  christos 			tgt_ip->w[3] |= l << i;
    904   1.1  christos 			cp = cp2 + 1;
    905   1.1  christos 		}
    906   1.1  christos 	} else {
    907   1.1  christos 		/*
    908   1.1  christos 		 * Convert a text IPv6 address.
    909   1.1  christos 		 */
    910   1.1  christos 		*tgt_prefix = (dns_rpz_prefix_t)prefix_num;
    911   1.7  christos 		for (i = 0; ip_labels > 0 && i < DNS_RPZ_CIDR_WORDS * 2;
    912  1.12  christos 		     ip_labels--)
    913  1.12  christos 		{
    914   1.1  christos 			if (cp[0] == 'z' && cp[1] == 'z' &&
    915  1.12  christos 			    (cp[2] == '.' || cp[2] == '\0') && i <= 6)
    916  1.12  christos 			{
    917   1.1  christos 				do {
    918   1.7  christos 					if ((i & 1) == 0) {
    919   1.7  christos 						tgt_ip->w[3 - i / 2] = 0;
    920   1.7  christos 					}
    921   1.1  christos 					++i;
    922   1.1  christos 				} while (ip_labels + i <= 8);
    923   1.1  christos 				cp += 3;
    924   1.1  christos 			} else {
    925   1.1  christos 				l = strtoul(cp, &cp2, 16);
    926   1.1  christos 				if (l > 0xffffu ||
    927  1.12  christos 				    (*cp2 != '.' && *cp2 != '\0'))
    928  1.12  christos 				{
    929   1.7  christos 					if (*cp2 == '.') {
    930   1.7  christos 						*cp2 = '\0';
    931   1.7  christos 					}
    932   1.1  christos 					badname(log_level, src_name,
    933   1.1  christos 						"; invalid IPv6 word ", cp);
    934   1.1  christos 					return (ISC_R_FAILURE);
    935   1.1  christos 				}
    936   1.7  christos 				if ((i & 1) == 0) {
    937   1.7  christos 					tgt_ip->w[3 - i / 2] = l;
    938   1.7  christos 				} else {
    939   1.7  christos 					tgt_ip->w[3 - i / 2] |= l << 16;
    940   1.7  christos 				}
    941   1.1  christos 				i++;
    942   1.1  christos 				cp = cp2 + 1;
    943   1.1  christos 			}
    944   1.1  christos 		}
    945   1.1  christos 	}
    946   1.1  christos 	if (cp != end) {
    947   1.1  christos 		badname(log_level, src_name, "", "");
    948   1.1  christos 		return (ISC_R_FAILURE);
    949   1.1  christos 	}
    950   1.1  christos 
    951   1.1  christos 	/*
    952   1.1  christos 	 * Check for 1s after the prefix length.
    953   1.1  christos 	 */
    954   1.1  christos 	prefix = (dns_rpz_prefix_t)prefix_num;
    955   1.1  christos 	while (prefix < DNS_RPZ_CIDR_KEY_BITS) {
    956   1.1  christos 		dns_rpz_cidr_word_t aword;
    957   1.1  christos 
    958   1.1  christos 		i = prefix % DNS_RPZ_CIDR_WORD_BITS;
    959   1.1  christos 		aword = tgt_ip->w[prefix / DNS_RPZ_CIDR_WORD_BITS];
    960   1.1  christos 		if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) {
    961   1.1  christos 			badname(log_level, src_name,
    962   1.1  christos 				"; too small prefix length of ", prefix_str);
    963   1.1  christos 			return (ISC_R_FAILURE);
    964   1.1  christos 		}
    965   1.1  christos 		prefix -= i;
    966   1.1  christos 		prefix += DNS_RPZ_CIDR_WORD_BITS;
    967   1.1  christos 	}
    968   1.1  christos 
    969   1.1  christos 	/*
    970   1.1  christos 	 * Complain about bad names but be generous and accept them.
    971   1.1  christos 	 */
    972   1.1  christos 	if (log_level < DNS_RPZ_DEBUG_QUIET &&
    973  1.12  christos 	    isc_log_wouldlog(dns_lctx, log_level))
    974  1.12  christos 	{
    975   1.1  christos 		/*
    976   1.1  christos 		 * Convert the address back to a canonical domain name
    977   1.1  christos 		 * to ensure that the original name is in canonical form.
    978   1.1  christos 		 */
    979   1.1  christos 		ip_name2 = dns_fixedname_initname(&ip_name2f);
    980   1.7  christos 		result = ip2name(tgt_ip, (dns_rpz_prefix_t)prefix_num, NULL,
    981   1.7  christos 				 ip_name2);
    982   1.1  christos 		if (result != ISC_R_SUCCESS ||
    983  1.12  christos 		    !dns_name_equal(&ip_name, ip_name2))
    984  1.12  christos 		{
    985   1.1  christos 			dns_name_format(ip_name2, ip2_str, sizeof(ip2_str));
    986   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
    987   1.1  christos 				      DNS_LOGMODULE_RBTDB, log_level,
    988   1.1  christos 				      "rpz IP address \"%s\""
    989   1.1  christos 				      " is not the canonical \"%s\"",
    990   1.1  christos 				      ip_str, ip2_str);
    991   1.1  christos 		}
    992   1.1  christos 	}
    993   1.1  christos 
    994   1.1  christos 	return (ISC_R_SUCCESS);
    995   1.1  christos }
    996   1.1  christos 
    997   1.1  christos /*
    998   1.1  christos  * Get trigger name and data bits for adding or deleting summary NSDNAME
    999   1.1  christos  * or QNAME data.
   1000   1.1  christos  */
   1001   1.1  christos static void
   1002   1.7  christos name2data(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_rpz_type_t rpz_type,
   1003   1.7  christos 	  const dns_name_t *src_name, dns_name_t *trig_name,
   1004   1.7  christos 	  dns_rpz_nm_data_t *new_data) {
   1005   1.1  christos 	dns_rpz_zone_t *rpz;
   1006   1.1  christos 	dns_offsets_t tmp_name_offsets;
   1007   1.1  christos 	dns_name_t tmp_name;
   1008   1.1  christos 	unsigned int prefix_len, n;
   1009   1.1  christos 
   1010   1.1  christos 	REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
   1011   1.1  christos 	rpz = rpzs->zones[rpz_num];
   1012   1.1  christos 	REQUIRE(rpz != NULL);
   1013   1.1  christos 
   1014   1.1  christos 	/*
   1015   1.1  christos 	 * Handle wildcards by putting only the parent into the
   1016   1.1  christos 	 * summary RBT.  The summary database only causes a check of the
   1017   1.1  christos 	 * real policy zone where wildcards will be handled.
   1018   1.1  christos 	 */
   1019   1.1  christos 	if (dns_name_iswildcard(src_name)) {
   1020   1.1  christos 		prefix_len = 1;
   1021   1.1  christos 		memset(&new_data->set, 0, sizeof(new_data->set));
   1022   1.1  christos 		make_nm_set(&new_data->wild, rpz_num, rpz_type);
   1023   1.1  christos 	} else {
   1024   1.1  christos 		prefix_len = 0;
   1025   1.1  christos 		make_nm_set(&new_data->set, rpz_num, rpz_type);
   1026   1.1  christos 		memset(&new_data->wild, 0, sizeof(new_data->wild));
   1027   1.1  christos 	}
   1028   1.1  christos 
   1029   1.1  christos 	dns_name_init(&tmp_name, tmp_name_offsets);
   1030   1.1  christos 	n = dns_name_countlabels(src_name);
   1031   1.1  christos 	n -= prefix_len;
   1032   1.7  christos 	if (rpz_type == DNS_RPZ_TYPE_QNAME) {
   1033   1.1  christos 		n -= dns_name_countlabels(&rpz->origin);
   1034   1.7  christos 	} else {
   1035   1.1  christos 		n -= dns_name_countlabels(&rpz->nsdname);
   1036   1.7  christos 	}
   1037   1.1  christos 	dns_name_getlabelsequence(src_name, prefix_len, n, &tmp_name);
   1038   1.1  christos 	(void)dns_name_concatenate(&tmp_name, dns_rootname, trig_name, NULL);
   1039   1.1  christos }
   1040   1.1  christos 
   1041   1.1  christos #ifndef HAVE_BUILTIN_CLZ
   1042   1.1  christos /**
   1043   1.1  christos  * \brief Count Leading Zeros: Find the location of the left-most set
   1044   1.1  christos  * bit.
   1045   1.1  christos  */
   1046  1.11  christos static unsigned int
   1047   1.1  christos clz(dns_rpz_cidr_word_t w) {
   1048   1.1  christos 	unsigned int bit;
   1049   1.1  christos 
   1050   1.7  christos 	bit = DNS_RPZ_CIDR_WORD_BITS - 1;
   1051   1.1  christos 
   1052   1.1  christos 	if ((w & 0xffff0000) != 0) {
   1053   1.1  christos 		w >>= 16;
   1054   1.1  christos 		bit -= 16;
   1055   1.1  christos 	}
   1056   1.1  christos 
   1057   1.1  christos 	if ((w & 0xff00) != 0) {
   1058   1.1  christos 		w >>= 8;
   1059   1.1  christos 		bit -= 8;
   1060   1.1  christos 	}
   1061   1.1  christos 
   1062   1.1  christos 	if ((w & 0xf0) != 0) {
   1063   1.1  christos 		w >>= 4;
   1064   1.1  christos 		bit -= 4;
   1065   1.1  christos 	}
   1066   1.1  christos 
   1067   1.1  christos 	if ((w & 0xc) != 0) {
   1068   1.1  christos 		w >>= 2;
   1069   1.1  christos 		bit -= 2;
   1070   1.1  christos 	}
   1071   1.1  christos 
   1072   1.7  christos 	if ((w & 2) != 0) {
   1073   1.1  christos 		--bit;
   1074   1.7  christos 	}
   1075   1.1  christos 
   1076   1.1  christos 	return (bit);
   1077   1.1  christos }
   1078   1.7  christos #endif /* ifndef HAVE_BUILTIN_CLZ */
   1079   1.1  christos 
   1080   1.1  christos /*
   1081   1.1  christos  * Find the first differing bit in two keys (IP addresses).
   1082   1.1  christos  */
   1083   1.1  christos static int
   1084   1.1  christos diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1,
   1085   1.7  christos 	  const dns_rpz_cidr_key_t *key2, dns_rpz_prefix_t prefix2) {
   1086   1.1  christos 	dns_rpz_cidr_word_t delta;
   1087   1.1  christos 	dns_rpz_prefix_t maxbit, bit;
   1088   1.1  christos 	int i;
   1089   1.1  christos 
   1090   1.1  christos 	bit = 0;
   1091   1.1  christos 	maxbit = ISC_MIN(prefix1, prefix2);
   1092   1.1  christos 
   1093   1.1  christos 	/*
   1094   1.1  christos 	 * find the first differing words
   1095   1.1  christos 	 */
   1096   1.1  christos 	for (i = 0; bit < maxbit; i++, bit += DNS_RPZ_CIDR_WORD_BITS) {
   1097   1.1  christos 		delta = key1->w[i] ^ key2->w[i];
   1098   1.1  christos 		if (ISC_UNLIKELY(delta != 0)) {
   1099   1.1  christos #ifdef HAVE_BUILTIN_CLZ
   1100   1.1  christos 			bit += __builtin_clz(delta);
   1101   1.7  christos #else  /* ifdef HAVE_BUILTIN_CLZ */
   1102   1.1  christos 			bit += clz(delta);
   1103   1.7  christos #endif /* ifdef HAVE_BUILTIN_CLZ */
   1104   1.1  christos 			break;
   1105   1.1  christos 		}
   1106   1.1  christos 	}
   1107   1.1  christos 	return (ISC_MIN(bit, maxbit));
   1108   1.1  christos }
   1109   1.1  christos 
   1110   1.1  christos /*
   1111   1.1  christos  * Given a hit while searching the radix trees,
   1112   1.1  christos  * clear all bits for higher numbered zones.
   1113   1.1  christos  */
   1114  1.11  christos static dns_rpz_zbits_t
   1115   1.1  christos trim_zbits(dns_rpz_zbits_t zbits, dns_rpz_zbits_t found) {
   1116   1.1  christos 	dns_rpz_zbits_t x;
   1117   1.1  christos 
   1118   1.1  christos 	/*
   1119   1.1  christos 	 * Isolate the first or smallest numbered hit bit.
   1120   1.1  christos 	 * Make a mask of that bit and all smaller numbered bits.
   1121   1.1  christos 	 */
   1122   1.1  christos 	x = zbits & found;
   1123   1.1  christos 	x &= (~x + 1);
   1124   1.1  christos 	x = (x << 1) - 1;
   1125   1.7  christos 	zbits &= x;
   1126   1.7  christos 	return (zbits);
   1127   1.1  christos }
   1128   1.1  christos 
   1129   1.1  christos /*
   1130   1.1  christos  * Search a radix tree for an IP address for ordinary lookup
   1131   1.1  christos  *	or for a CIDR block adding or deleting an entry
   1132   1.1  christos  *
   1133   1.1  christos  * Return ISC_R_SUCCESS, DNS_R_PARTIALMATCH, ISC_R_NOTFOUND,
   1134   1.1  christos  *	    and *found=longest match node
   1135   1.3  christos  *	or with create==true, ISC_R_EXISTS or ISC_R_NOMEMORY
   1136   1.1  christos  */
   1137   1.1  christos static isc_result_t
   1138   1.7  christos search(dns_rpz_zones_t *rpzs, const dns_rpz_cidr_key_t *tgt_ip,
   1139   1.7  christos        dns_rpz_prefix_t tgt_prefix, const dns_rpz_addr_zbits_t *tgt_set,
   1140   1.7  christos        bool create, dns_rpz_cidr_node_t **found) {
   1141   1.1  christos 	dns_rpz_cidr_node_t *cur, *parent, *child, *new_parent, *sibling;
   1142   1.1  christos 	dns_rpz_addr_zbits_t set;
   1143   1.1  christos 	int cur_num, child_num;
   1144   1.1  christos 	dns_rpz_prefix_t dbit;
   1145   1.1  christos 	isc_result_t find_result;
   1146   1.1  christos 
   1147   1.1  christos 	set = *tgt_set;
   1148   1.1  christos 	find_result = ISC_R_NOTFOUND;
   1149   1.1  christos 	*found = NULL;
   1150   1.1  christos 	cur = rpzs->cidr;
   1151   1.1  christos 	parent = NULL;
   1152   1.1  christos 	cur_num = 0;
   1153   1.1  christos 	for (;;) {
   1154   1.1  christos 		if (cur == NULL) {
   1155   1.1  christos 			/*
   1156   1.1  christos 			 * No child so we cannot go down.
   1157   1.1  christos 			 * Quit with whatever we already found
   1158   1.1  christos 			 * or add the target as a child of the current parent.
   1159   1.1  christos 			 */
   1160   1.7  christos 			if (!create) {
   1161   1.1  christos 				return (find_result);
   1162   1.7  christos 			}
   1163   1.1  christos 			child = new_node(rpzs, tgt_ip, tgt_prefix, NULL);
   1164   1.7  christos 			if (child == NULL) {
   1165   1.1  christos 				return (ISC_R_NOMEMORY);
   1166   1.7  christos 			}
   1167   1.7  christos 			if (parent == NULL) {
   1168   1.1  christos 				rpzs->cidr = child;
   1169   1.7  christos 			} else {
   1170   1.1  christos 				parent->child[cur_num] = child;
   1171   1.7  christos 			}
   1172   1.1  christos 			child->parent = parent;
   1173   1.1  christos 			child->set.client_ip |= tgt_set->client_ip;
   1174   1.1  christos 			child->set.ip |= tgt_set->ip;
   1175   1.1  christos 			child->set.nsip |= tgt_set->nsip;
   1176   1.1  christos 			set_sum_pair(child);
   1177   1.1  christos 			*found = child;
   1178   1.1  christos 			return (ISC_R_SUCCESS);
   1179   1.1  christos 		}
   1180   1.1  christos 
   1181   1.1  christos 		if ((cur->sum.client_ip & set.client_ip) == 0 &&
   1182   1.1  christos 		    (cur->sum.ip & set.ip) == 0 &&
   1183   1.7  christos 		    (cur->sum.nsip & set.nsip) == 0)
   1184   1.7  christos 		{
   1185   1.1  christos 			/*
   1186   1.1  christos 			 * This node has no relevant data
   1187   1.1  christos 			 * and is in none of the target trees.
   1188   1.1  christos 			 * Pretend it does not exist if we are not adding.
   1189   1.1  christos 			 *
   1190   1.1  christos 			 * If we are adding, continue down to eventually add
   1191   1.1  christos 			 * a node and mark/put this node in the correct tree.
   1192   1.1  christos 			 */
   1193   1.7  christos 			if (!create) {
   1194   1.1  christos 				return (find_result);
   1195   1.7  christos 			}
   1196   1.1  christos 		}
   1197   1.1  christos 
   1198   1.1  christos 		dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->prefix);
   1199   1.1  christos 		/*
   1200   1.1  christos 		 * dbit <= tgt_prefix and dbit <= cur->prefix always.
   1201   1.1  christos 		 * We are finished searching if we matched all of the target.
   1202   1.1  christos 		 */
   1203   1.1  christos 		if (dbit == tgt_prefix) {
   1204   1.1  christos 			if (tgt_prefix == cur->prefix) {
   1205   1.1  christos 				/*
   1206   1.1  christos 				 * The node's key matches the target exactly.
   1207   1.1  christos 				 */
   1208   1.1  christos 				if ((cur->set.client_ip & set.client_ip) != 0 ||
   1209   1.1  christos 				    (cur->set.ip & set.ip) != 0 ||
   1210   1.7  christos 				    (cur->set.nsip & set.nsip) != 0)
   1211   1.7  christos 				{
   1212   1.1  christos 					/*
   1213   1.1  christos 					 * It is the answer if it has data.
   1214   1.1  christos 					 */
   1215   1.1  christos 					*found = cur;
   1216   1.1  christos 					if (create) {
   1217   1.7  christos 						find_result = ISC_R_EXISTS;
   1218   1.1  christos 					} else {
   1219   1.7  christos 						find_result = ISC_R_SUCCESS;
   1220   1.1  christos 					}
   1221   1.1  christos 				} else if (create) {
   1222   1.1  christos 					/*
   1223   1.1  christos 					 * The node lacked relevant data,
   1224   1.1  christos 					 * but will have it now.
   1225   1.1  christos 					 */
   1226   1.1  christos 					cur->set.client_ip |=
   1227   1.1  christos 						tgt_set->client_ip;
   1228   1.1  christos 					cur->set.ip |= tgt_set->ip;
   1229   1.1  christos 					cur->set.nsip |= tgt_set->nsip;
   1230   1.1  christos 					set_sum_pair(cur);
   1231   1.1  christos 					*found = cur;
   1232   1.1  christos 					find_result = ISC_R_SUCCESS;
   1233   1.1  christos 				}
   1234   1.1  christos 				return (find_result);
   1235   1.1  christos 			}
   1236   1.1  christos 
   1237   1.1  christos 			/*
   1238   1.1  christos 			 * We know tgt_prefix < cur->prefix which means that
   1239   1.1  christos 			 * the target is shorter than the current node.
   1240   1.1  christos 			 * Add the target as the current node's parent.
   1241   1.1  christos 			 */
   1242   1.7  christos 			if (!create) {
   1243   1.1  christos 				return (find_result);
   1244   1.7  christos 			}
   1245   1.1  christos 
   1246   1.1  christos 			new_parent = new_node(rpzs, tgt_ip, tgt_prefix, cur);
   1247   1.7  christos 			if (new_parent == NULL) {
   1248   1.1  christos 				return (ISC_R_NOMEMORY);
   1249   1.7  christos 			}
   1250   1.1  christos 			new_parent->parent = parent;
   1251   1.7  christos 			if (parent == NULL) {
   1252   1.1  christos 				rpzs->cidr = new_parent;
   1253   1.7  christos 			} else {
   1254   1.1  christos 				parent->child[cur_num] = new_parent;
   1255   1.7  christos 			}
   1256   1.1  christos 			child_num = DNS_RPZ_IP_BIT(&cur->ip, tgt_prefix);
   1257   1.1  christos 			new_parent->child[child_num] = cur;
   1258   1.1  christos 			cur->parent = new_parent;
   1259   1.1  christos 			new_parent->set = *tgt_set;
   1260   1.1  christos 			set_sum_pair(new_parent);
   1261   1.1  christos 			*found = new_parent;
   1262   1.1  christos 			return (ISC_R_SUCCESS);
   1263   1.1  christos 		}
   1264   1.1  christos 
   1265   1.1  christos 		if (dbit == cur->prefix) {
   1266   1.1  christos 			if ((cur->set.client_ip & set.client_ip) != 0 ||
   1267   1.1  christos 			    (cur->set.ip & set.ip) != 0 ||
   1268   1.7  christos 			    (cur->set.nsip & set.nsip) != 0)
   1269   1.7  christos 			{
   1270   1.1  christos 				/*
   1271   1.1  christos 				 * We have a partial match between of all of the
   1272   1.1  christos 				 * current node but only part of the target.
   1273   1.1  christos 				 * Continue searching for other hits in the
   1274   1.1  christos 				 * same or lower numbered trees.
   1275   1.1  christos 				 */
   1276   1.1  christos 				find_result = DNS_R_PARTIALMATCH;
   1277   1.1  christos 				*found = cur;
   1278   1.1  christos 				set.client_ip = trim_zbits(set.client_ip,
   1279   1.1  christos 							   cur->set.client_ip);
   1280   1.7  christos 				set.ip = trim_zbits(set.ip, cur->set.ip);
   1281   1.7  christos 				set.nsip = trim_zbits(set.nsip, cur->set.nsip);
   1282   1.1  christos 			}
   1283   1.1  christos 			parent = cur;
   1284   1.1  christos 			cur_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
   1285   1.1  christos 			cur = cur->child[cur_num];
   1286   1.1  christos 			continue;
   1287   1.1  christos 		}
   1288   1.1  christos 
   1289   1.1  christos 		/*
   1290   1.1  christos 		 * dbit < tgt_prefix and dbit < cur->prefix,
   1291   1.1  christos 		 * so we failed to match both the target and the current node.
   1292   1.1  christos 		 * Insert a fork of a parent above the current node and
   1293   1.1  christos 		 * add the target as a sibling of the current node
   1294   1.1  christos 		 */
   1295   1.7  christos 		if (!create) {
   1296   1.1  christos 			return (find_result);
   1297   1.7  christos 		}
   1298   1.1  christos 
   1299   1.1  christos 		sibling = new_node(rpzs, tgt_ip, tgt_prefix, NULL);
   1300   1.7  christos 		if (sibling == NULL) {
   1301   1.1  christos 			return (ISC_R_NOMEMORY);
   1302   1.7  christos 		}
   1303   1.1  christos 		new_parent = new_node(rpzs, tgt_ip, dbit, cur);
   1304   1.1  christos 		if (new_parent == NULL) {
   1305   1.1  christos 			isc_mem_put(rpzs->mctx, sibling, sizeof(*sibling));
   1306   1.1  christos 			return (ISC_R_NOMEMORY);
   1307   1.1  christos 		}
   1308   1.1  christos 		new_parent->parent = parent;
   1309   1.7  christos 		if (parent == NULL) {
   1310   1.1  christos 			rpzs->cidr = new_parent;
   1311   1.7  christos 		} else {
   1312   1.1  christos 			parent->child[cur_num] = new_parent;
   1313   1.7  christos 		}
   1314   1.1  christos 		child_num = DNS_RPZ_IP_BIT(tgt_ip, dbit);
   1315   1.1  christos 		new_parent->child[child_num] = sibling;
   1316   1.7  christos 		new_parent->child[1 - child_num] = cur;
   1317   1.1  christos 		cur->parent = new_parent;
   1318   1.1  christos 		sibling->parent = new_parent;
   1319   1.1  christos 		sibling->set = *tgt_set;
   1320   1.1  christos 		set_sum_pair(sibling);
   1321   1.1  christos 		*found = sibling;
   1322   1.1  christos 		return (ISC_R_SUCCESS);
   1323   1.1  christos 	}
   1324   1.1  christos }
   1325   1.1  christos 
   1326   1.1  christos /*
   1327   1.1  christos  * Add an IP address to the radix tree.
   1328   1.1  christos  */
   1329   1.1  christos static isc_result_t
   1330   1.7  christos add_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_rpz_type_t rpz_type,
   1331   1.7  christos 	 const dns_name_t *src_name) {
   1332   1.1  christos 	dns_rpz_cidr_key_t tgt_ip;
   1333   1.1  christos 	dns_rpz_prefix_t tgt_prefix;
   1334   1.1  christos 	dns_rpz_addr_zbits_t set;
   1335   1.1  christos 	dns_rpz_cidr_node_t *found;
   1336   1.1  christos 	isc_result_t result;
   1337   1.1  christos 
   1338   1.1  christos 	result = name2ipkey(DNS_RPZ_ERROR_LEVEL, rpzs, rpz_num, rpz_type,
   1339   1.1  christos 			    src_name, &tgt_ip, &tgt_prefix, &set);
   1340   1.1  christos 	/*
   1341   1.1  christos 	 * Log complaints about bad owner names but let the zone load.
   1342   1.1  christos 	 */
   1343   1.7  christos 	if (result != ISC_R_SUCCESS) {
   1344   1.1  christos 		return (ISC_R_SUCCESS);
   1345   1.7  christos 	}
   1346   1.1  christos 
   1347   1.3  christos 	result = search(rpzs, &tgt_ip, tgt_prefix, &set, true, &found);
   1348   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1349   1.1  christos 		char namebuf[DNS_NAME_FORMATSIZE];
   1350   1.1  christos 
   1351   1.1  christos 		/*
   1352   1.1  christos 		 * Do not worry if the radix tree already exists,
   1353   1.1  christos 		 * because diff_apply() likes to add nodes before deleting.
   1354   1.1  christos 		 */
   1355   1.7  christos 		if (result == ISC_R_EXISTS) {
   1356   1.1  christos 			return (ISC_R_SUCCESS);
   1357   1.7  christos 		}
   1358   1.1  christos 
   1359   1.1  christos 		/*
   1360   1.1  christos 		 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
   1361   1.1  christos 		 */
   1362   1.1  christos 		dns_name_format(src_name, namebuf, sizeof(namebuf));
   1363   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
   1364   1.1  christos 			      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
   1365   1.7  christos 			      "rpz add_cidr(%s) failed: %s", namebuf,
   1366   1.7  christos 			      isc_result_totext(result));
   1367   1.1  christos 		return (result);
   1368   1.1  christos 	}
   1369   1.1  christos 
   1370   1.3  christos 	adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, true);
   1371   1.1  christos 	return (result);
   1372   1.1  christos }
   1373   1.1  christos 
   1374   1.1  christos static isc_result_t
   1375   1.1  christos add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name,
   1376   1.7  christos        const dns_rpz_nm_data_t *new_data) {
   1377   1.1  christos 	dns_rbtnode_t *nmnode;
   1378   1.1  christos 	dns_rpz_nm_data_t *nm_data;
   1379   1.1  christos 	isc_result_t result;
   1380   1.1  christos 
   1381   1.1  christos 	nmnode = NULL;
   1382   1.1  christos 	result = dns_rbt_addnode(rpzs->rbt, trig_name, &nmnode);
   1383   1.1  christos 	switch (result) {
   1384   1.1  christos 	case ISC_R_SUCCESS:
   1385   1.1  christos 	case ISC_R_EXISTS:
   1386   1.1  christos 		nm_data = nmnode->data;
   1387   1.1  christos 		if (nm_data == NULL) {
   1388   1.1  christos 			nm_data = isc_mem_get(rpzs->mctx, sizeof(*nm_data));
   1389   1.1  christos 			*nm_data = *new_data;
   1390   1.1  christos 			nmnode->data = nm_data;
   1391   1.1  christos 			return (ISC_R_SUCCESS);
   1392   1.1  christos 		}
   1393   1.1  christos 		break;
   1394   1.1  christos 	default:
   1395   1.1  christos 		return (result);
   1396   1.1  christos 	}
   1397   1.1  christos 
   1398   1.1  christos 	/*
   1399   1.1  christos 	 * Do not count bits that are already present
   1400   1.1  christos 	 */
   1401   1.1  christos 	if ((nm_data->set.qname & new_data->set.qname) != 0 ||
   1402   1.1  christos 	    (nm_data->set.ns & new_data->set.ns) != 0 ||
   1403   1.1  christos 	    (nm_data->wild.qname & new_data->wild.qname) != 0 ||
   1404   1.1  christos 	    (nm_data->wild.ns & new_data->wild.ns) != 0)
   1405   1.7  christos 	{
   1406   1.1  christos 		return (ISC_R_EXISTS);
   1407   1.7  christos 	}
   1408   1.1  christos 
   1409   1.1  christos 	nm_data->set.qname |= new_data->set.qname;
   1410   1.1  christos 	nm_data->set.ns |= new_data->set.ns;
   1411   1.1  christos 	nm_data->wild.qname |= new_data->wild.qname;
   1412   1.1  christos 	nm_data->wild.ns |= new_data->wild.ns;
   1413   1.1  christos 	return (ISC_R_SUCCESS);
   1414   1.1  christos }
   1415   1.1  christos 
   1416   1.1  christos static isc_result_t
   1417   1.7  christos add_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_rpz_type_t rpz_type,
   1418   1.7  christos 	 const dns_name_t *src_name) {
   1419   1.1  christos 	dns_rpz_nm_data_t new_data;
   1420   1.1  christos 	dns_fixedname_t trig_namef;
   1421   1.1  christos 	dns_name_t *trig_name;
   1422   1.1  christos 	isc_result_t result;
   1423   1.1  christos 
   1424   1.1  christos 	/*
   1425   1.1  christos 	 * We need a summary database of names even with 1 policy zone,
   1426   1.1  christos 	 * because wildcard triggers are handled differently.
   1427   1.1  christos 	 */
   1428   1.1  christos 
   1429   1.1  christos 	trig_name = dns_fixedname_initname(&trig_namef);
   1430   1.1  christos 	name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &new_data);
   1431   1.1  christos 
   1432   1.1  christos 	result = add_nm(rpzs, trig_name, &new_data);
   1433   1.1  christos 
   1434   1.1  christos 	/*
   1435   1.1  christos 	 * Do not worry if the node already exists,
   1436   1.1  christos 	 * because diff_apply() likes to add nodes before deleting.
   1437   1.1  christos 	 */
   1438   1.7  christos 	if (result == ISC_R_EXISTS) {
   1439   1.1  christos 		return (ISC_R_SUCCESS);
   1440   1.7  christos 	}
   1441   1.7  christos 	if (result == ISC_R_SUCCESS) {
   1442   1.3  christos 		adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, true);
   1443   1.7  christos 	}
   1444   1.1  christos 	return (result);
   1445   1.1  christos }
   1446   1.1  christos 
   1447   1.1  christos /*
   1448   1.1  christos  * Callback to free the data for a node in the summary RBT database.
   1449   1.1  christos  */
   1450   1.1  christos static void
   1451   1.1  christos rpz_node_deleter(void *nm_data, void *mctx) {
   1452   1.1  christos 	isc_mem_put(mctx, nm_data, sizeof(dns_rpz_nm_data_t));
   1453   1.1  christos }
   1454   1.1  christos 
   1455   1.1  christos /*
   1456   1.1  christos  * Get ready for a new set of policy zones for a view.
   1457   1.1  christos  */
   1458   1.1  christos isc_result_t
   1459   1.7  christos dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, char *rps_cstr, size_t rps_cstr_size,
   1460   1.7  christos 		  isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
   1461   1.7  christos 		  isc_timermgr_t *timermgr) {
   1462   1.1  christos 	dns_rpz_zones_t *zones;
   1463  1.10  christos 	isc_result_t result = ISC_R_SUCCESS;
   1464   1.1  christos 
   1465   1.1  christos 	REQUIRE(rpzsp != NULL && *rpzsp == NULL);
   1466   1.1  christos 
   1467   1.1  christos 	zones = isc_mem_get(mctx, sizeof(*zones));
   1468   1.1  christos 	memset(zones, 0, sizeof(*zones));
   1469   1.1  christos 
   1470  1.10  christos 	isc_rwlock_init(&zones->search_lock, 0, 0);
   1471   1.3  christos 	isc_mutex_init(&zones->maint_lock);
   1472   1.3  christos 	isc_refcount_init(&zones->refs, 1);
   1473   1.5  christos 	isc_refcount_init(&zones->irefs, 1);
   1474   1.1  christos 
   1475   1.1  christos 	zones->rps_cstr = rps_cstr;
   1476   1.1  christos 	zones->rps_cstr_size = rps_cstr_size;
   1477   1.1  christos #ifdef USE_DNSRPS
   1478   1.1  christos 	if (rps_cstr != NULL) {
   1479   1.1  christos 		result = dns_dnsrps_view_init(zones, rps_cstr);
   1480   1.1  christos 	}
   1481   1.7  christos #else  /* ifdef USE_DNSRPS */
   1482   1.1  christos 	INSIST(!zones->p.dnsrps_enabled);
   1483   1.7  christos #endif /* ifdef USE_DNSRPS */
   1484   1.1  christos 	if (result == ISC_R_SUCCESS && !zones->p.dnsrps_enabled) {
   1485   1.7  christos 		result = dns_rbt_create(mctx, rpz_node_deleter, mctx,
   1486   1.7  christos 					&zones->rbt);
   1487   1.1  christos 	}
   1488   1.1  christos 
   1489   1.7  christos 	if (result != ISC_R_SUCCESS) {
   1490   1.1  christos 		goto cleanup_rbt;
   1491   1.7  christos 	}
   1492   1.1  christos 
   1493   1.1  christos 	result = isc_task_create(taskmgr, 0, &zones->updater);
   1494   1.7  christos 	if (result != ISC_R_SUCCESS) {
   1495   1.1  christos 		goto cleanup_task;
   1496   1.7  christos 	}
   1497   1.1  christos 
   1498   1.1  christos 	isc_mem_attach(mctx, &zones->mctx);
   1499   1.1  christos 	zones->timermgr = timermgr;
   1500   1.1  christos 	zones->taskmgr = taskmgr;
   1501   1.1  christos 
   1502   1.1  christos 	*rpzsp = zones;
   1503   1.1  christos 	return (ISC_R_SUCCESS);
   1504   1.1  christos 
   1505   1.1  christos cleanup_task:
   1506   1.1  christos 	dns_rbt_destroy(&zones->rbt);
   1507   1.1  christos 
   1508   1.1  christos cleanup_rbt:
   1509   1.9  christos 	isc_refcount_decrementz(&zones->irefs);
   1510   1.5  christos 	isc_refcount_destroy(&zones->irefs);
   1511   1.9  christos 	isc_refcount_decrementz(&zones->refs);
   1512   1.1  christos 	isc_refcount_destroy(&zones->refs);
   1513   1.3  christos 	isc_mutex_destroy(&zones->maint_lock);
   1514   1.1  christos 	isc_rwlock_destroy(&zones->search_lock);
   1515   1.1  christos 	isc_mem_put(mctx, zones, sizeof(*zones));
   1516   1.1  christos 
   1517   1.1  christos 	return (result);
   1518   1.1  christos }
   1519   1.1  christos 
   1520   1.1  christos isc_result_t
   1521   1.1  christos dns_rpz_new_zone(dns_rpz_zones_t *rpzs, dns_rpz_zone_t **rpzp) {
   1522   1.1  christos 	dns_rpz_zone_t *zone;
   1523   1.1  christos 	isc_result_t result;
   1524   1.1  christos 
   1525   1.1  christos 	REQUIRE(rpzp != NULL && *rpzp == NULL);
   1526   1.1  christos 	REQUIRE(rpzs != NULL);
   1527   1.1  christos 	if (rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) {
   1528   1.1  christos 		return (ISC_R_NOSPACE);
   1529   1.1  christos 	}
   1530   1.1  christos 
   1531   1.1  christos 	zone = isc_mem_get(rpzs->mctx, sizeof(*zone));
   1532   1.1  christos 
   1533   1.1  christos 	memset(zone, 0, sizeof(*zone));
   1534   1.3  christos 	isc_refcount_init(&zone->refs, 1);
   1535   1.1  christos 
   1536   1.7  christos 	result = isc_timer_create(rpzs->timermgr, isc_timertype_inactive, NULL,
   1537   1.7  christos 				  NULL, rpzs->updater,
   1538   1.7  christos 				  dns_rpz_update_taskaction, zone,
   1539   1.7  christos 				  &zone->updatetimer);
   1540   1.7  christos 	if (result != ISC_R_SUCCESS) {
   1541   1.1  christos 		goto cleanup_timer;
   1542   1.7  christos 	}
   1543   1.1  christos 
   1544   1.1  christos 	/*
   1545   1.1  christos 	 * This will never be used, but costs us nothing and
   1546   1.1  christos 	 * simplifies update_from_db
   1547   1.1  christos 	 */
   1548   1.1  christos 
   1549  1.11  christos 	isc_ht_init(&zone->nodes, rpzs->mctx, 1);
   1550   1.1  christos 
   1551   1.1  christos 	dns_name_init(&zone->origin, NULL);
   1552   1.1  christos 	dns_name_init(&zone->client_ip, NULL);
   1553   1.1  christos 	dns_name_init(&zone->ip, NULL);
   1554   1.1  christos 	dns_name_init(&zone->nsdname, NULL);
   1555   1.1  christos 	dns_name_init(&zone->nsip, NULL);
   1556   1.1  christos 	dns_name_init(&zone->passthru, NULL);
   1557   1.1  christos 	dns_name_init(&zone->drop, NULL);
   1558   1.1  christos 	dns_name_init(&zone->tcp_only, NULL);
   1559   1.1  christos 	dns_name_init(&zone->cname, NULL);
   1560   1.1  christos 
   1561   1.1  christos 	isc_time_settoepoch(&zone->lastupdated);
   1562   1.3  christos 	zone->updatepending = false;
   1563   1.3  christos 	zone->updaterunning = false;
   1564   1.1  christos 	zone->db = NULL;
   1565   1.1  christos 	zone->dbversion = NULL;
   1566   1.1  christos 	zone->updb = NULL;
   1567   1.1  christos 	zone->updbversion = NULL;
   1568   1.1  christos 	zone->updbit = NULL;
   1569   1.5  christos 	isc_refcount_increment(&rpzs->irefs);
   1570   1.1  christos 	zone->rpzs = rpzs;
   1571   1.3  christos 	zone->db_registered = false;
   1572   1.4  christos 	zone->addsoa = true;
   1573   1.7  christos 	ISC_EVENT_INIT(&zone->updateevent, sizeof(zone->updateevent), 0, NULL,
   1574   1.7  christos 		       0, NULL, NULL, NULL, NULL, NULL);
   1575   1.1  christos 
   1576   1.1  christos 	zone->num = rpzs->p.num_zones++;
   1577   1.1  christos 	rpzs->zones[zone->num] = zone;
   1578   1.1  christos 
   1579   1.1  christos 	*rpzp = zone;
   1580   1.1  christos 
   1581   1.1  christos 	return (ISC_R_SUCCESS);
   1582   1.1  christos 
   1583   1.1  christos cleanup_timer:
   1584   1.9  christos 	isc_refcount_decrementz(&zone->refs);
   1585   1.1  christos 	isc_refcount_destroy(&zone->refs);
   1586   1.1  christos 
   1587   1.5  christos 	isc_mem_put(rpzs->mctx, zone, sizeof(*zone));
   1588   1.1  christos 
   1589   1.1  christos 	return (result);
   1590   1.1  christos }
   1591   1.1  christos 
   1592   1.1  christos isc_result_t
   1593   1.1  christos dns_rpz_dbupdate_callback(dns_db_t *db, void *fn_arg) {
   1594   1.7  christos 	dns_rpz_zone_t *zone = (dns_rpz_zone_t *)fn_arg;
   1595   1.1  christos 	isc_time_t now;
   1596   1.3  christos 	uint64_t tdiff;
   1597   1.1  christos 	isc_result_t result = ISC_R_SUCCESS;
   1598   1.1  christos 	char dname[DNS_NAME_FORMATSIZE];
   1599   1.1  christos 
   1600   1.1  christos 	REQUIRE(DNS_DB_VALID(db));
   1601   1.1  christos 	REQUIRE(zone != NULL);
   1602   1.1  christos 
   1603   1.1  christos 	LOCK(&zone->rpzs->maint_lock);
   1604   1.1  christos 
   1605   1.1  christos 	/* New zone came as AXFR */
   1606   1.1  christos 	if (zone->db != NULL && zone->db != db) {
   1607   1.1  christos 		/* We need to clean up the old DB */
   1608   1.7  christos 		if (zone->dbversion != NULL) {
   1609   1.7  christos 			dns_db_closeversion(zone->db, &zone->dbversion, false);
   1610   1.7  christos 		}
   1611   1.1  christos 		dns_db_updatenotify_unregister(zone->db,
   1612   1.7  christos 					       dns_rpz_dbupdate_callback, zone);
   1613   1.1  christos 		dns_db_detach(&zone->db);
   1614   1.1  christos 	}
   1615   1.1  christos 
   1616   1.1  christos 	if (zone->db == NULL) {
   1617   1.1  christos 		RUNTIME_CHECK(zone->dbversion == NULL);
   1618   1.1  christos 		dns_db_attach(db, &zone->db);
   1619   1.1  christos 	}
   1620   1.1  christos 
   1621   1.1  christos 	if (!zone->updatepending && !zone->updaterunning) {
   1622   1.3  christos 		zone->updatepending = true;
   1623   1.1  christos 		isc_time_now(&now);
   1624   1.1  christos 		tdiff = isc_time_microdiff(&now, &zone->lastupdated) / 1000000;
   1625   1.1  christos 		if (tdiff < zone->min_update_interval) {
   1626   1.3  christos 			uint64_t defer = zone->min_update_interval - tdiff;
   1627   1.1  christos 			isc_interval_t interval;
   1628   1.1  christos 			dns_name_format(&zone->origin, dname,
   1629   1.1  christos 					DNS_NAME_FORMATSIZE);
   1630   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1631   1.1  christos 				      DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
   1632   1.1  christos 				      "rpz: %s: new zone version came "
   1633   1.1  christos 				      "too soon, deferring update for "
   1634   1.7  christos 				      "%" PRIu64 " seconds",
   1635   1.7  christos 				      dname, defer);
   1636   1.1  christos 			isc_interval_set(&interval, (unsigned int)defer, 0);
   1637   1.1  christos 			dns_db_currentversion(zone->db, &zone->dbversion);
   1638   1.1  christos 			result = isc_timer_reset(zone->updatetimer,
   1639   1.7  christos 						 isc_timertype_once, NULL,
   1640   1.7  christos 						 &interval, true);
   1641   1.7  christos 			if (result != ISC_R_SUCCESS) {
   1642   1.1  christos 				goto cleanup;
   1643   1.7  christos 			}
   1644   1.1  christos 		} else {
   1645   1.1  christos 			isc_event_t *event;
   1646   1.1  christos 
   1647   1.1  christos 			dns_db_currentversion(zone->db, &zone->dbversion);
   1648   1.1  christos 			INSIST(!ISC_LINK_LINKED(&zone->updateevent, ev_link));
   1649   1.1  christos 			ISC_EVENT_INIT(&zone->updateevent,
   1650   1.1  christos 				       sizeof(zone->updateevent), 0, NULL,
   1651   1.1  christos 				       DNS_EVENT_RPZUPDATED,
   1652   1.7  christos 				       dns_rpz_update_taskaction, zone, zone,
   1653   1.7  christos 				       NULL, NULL);
   1654   1.1  christos 			event = &zone->updateevent;
   1655   1.1  christos 			isc_task_send(zone->rpzs->updater, &event);
   1656   1.1  christos 		}
   1657   1.1  christos 	} else {
   1658   1.3  christos 		zone->updatepending = true;
   1659   1.1  christos 		dns_name_format(&zone->origin, dname, DNS_NAME_FORMATSIZE);
   1660   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1661   1.1  christos 			      DNS_LOGMODULE_MASTER, ISC_LOG_DEBUG(3),
   1662   1.6  christos 			      "rpz: %s: update already queued or running",
   1663   1.6  christos 			      dname);
   1664   1.6  christos 		if (zone->dbversion != NULL) {
   1665   1.7  christos 			dns_db_closeversion(zone->db, &zone->dbversion, false);
   1666   1.6  christos 		}
   1667   1.1  christos 		dns_db_currentversion(zone->db, &zone->dbversion);
   1668   1.1  christos 	}
   1669   1.1  christos 
   1670   1.7  christos cleanup:
   1671   1.1  christos 	UNLOCK(&zone->rpzs->maint_lock);
   1672   1.1  christos 
   1673   1.1  christos 	return (result);
   1674   1.1  christos }
   1675   1.1  christos 
   1676   1.1  christos static void
   1677   1.1  christos dns_rpz_update_taskaction(isc_task_t *task, isc_event_t *event) {
   1678   1.1  christos 	isc_result_t result;
   1679   1.1  christos 	dns_rpz_zone_t *zone;
   1680   1.1  christos 
   1681   1.1  christos 	REQUIRE(event != NULL);
   1682   1.1  christos 	REQUIRE(event->ev_arg != NULL);
   1683   1.1  christos 
   1684   1.1  christos 	UNUSED(task);
   1685   1.7  christos 	zone = (dns_rpz_zone_t *)event->ev_arg;
   1686   1.1  christos 	isc_event_free(&event);
   1687   1.1  christos 	LOCK(&zone->rpzs->maint_lock);
   1688   1.3  christos 	zone->updatepending = false;
   1689   1.3  christos 	zone->updaterunning = true;
   1690   1.1  christos 	dns_rpz_update_from_db(zone);
   1691   1.1  christos 	result = isc_timer_reset(zone->updatetimer, isc_timertype_inactive,
   1692   1.3  christos 				 NULL, NULL, true);
   1693   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1694   1.1  christos 	result = isc_time_now(&zone->lastupdated);
   1695   1.1  christos 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
   1696   1.1  christos 	UNLOCK(&zone->rpzs->maint_lock);
   1697   1.1  christos }
   1698   1.1  christos 
   1699   1.1  christos static isc_result_t
   1700   1.1  christos setup_update(dns_rpz_zone_t *rpz) {
   1701   1.1  christos 	isc_result_t result;
   1702   1.1  christos 	char domain[DNS_NAME_FORMATSIZE];
   1703   1.1  christos 	unsigned int nodecount;
   1704   1.3  christos 	uint32_t hashsize;
   1705   1.1  christos 
   1706   1.1  christos 	dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
   1707   1.7  christos 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
   1708   1.7  christos 		      ISC_LOG_INFO, "rpz: %s: reload start", domain);
   1709   1.1  christos 
   1710   1.1  christos 	nodecount = dns_db_nodecount(rpz->updb);
   1711   1.1  christos 	hashsize = 1;
   1712   1.1  christos 	while (nodecount != 0 &&
   1713  1.12  christos 	       hashsize <= (DNS_RPZ_HTSIZE_MAX + DNS_RPZ_HTSIZE_DIV))
   1714  1.12  christos 	{
   1715   1.1  christos 		hashsize++;
   1716   1.7  christos 		nodecount >>= 1;
   1717   1.1  christos 	}
   1718   1.1  christos 
   1719   1.7  christos 	if (hashsize > DNS_RPZ_HTSIZE_DIV) {
   1720   1.1  christos 		hashsize -= DNS_RPZ_HTSIZE_DIV;
   1721   1.7  christos 	}
   1722   1.1  christos 
   1723   1.7  christos 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_MASTER,
   1724   1.7  christos 		      ISC_LOG_DEBUG(1), "rpz: %s: using hashtable size %d",
   1725   1.7  christos 		      domain, hashsize);
   1726   1.1  christos 
   1727  1.11  christos 	isc_ht_init(&rpz->newnodes, rpz->rpzs->mctx, hashsize);
   1728   1.1  christos 
   1729   1.1  christos 	result = dns_db_createiterator(rpz->updb, DNS_DB_NONSEC3, &rpz->updbit);
   1730   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1731   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1732   1.1  christos 			      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1733   1.1  christos 			      "rpz: %s: failed to create DB iterator - %s",
   1734   1.1  christos 			      domain, isc_result_totext(result));
   1735   1.1  christos 		goto cleanup;
   1736   1.1  christos 	}
   1737   1.1  christos 
   1738   1.1  christos 	result = dns_dbiterator_first(rpz->updbit);
   1739   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1740   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1741   1.1  christos 			      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1742   1.7  christos 			      "rpz: %s: failed to get db iterator - %s", domain,
   1743   1.7  christos 			      isc_result_totext(result));
   1744   1.1  christos 		goto cleanup;
   1745   1.1  christos 	}
   1746   1.1  christos 
   1747   1.4  christos 	result = dns_dbiterator_pause(rpz->updbit);
   1748   1.4  christos 	if (result != ISC_R_SUCCESS) {
   1749   1.4  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1750   1.4  christos 			      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1751   1.4  christos 			      "rpz: %s: failed to pause db iterator - %s",
   1752   1.4  christos 			      domain, isc_result_totext(result));
   1753   1.4  christos 		goto cleanup;
   1754   1.4  christos 	}
   1755   1.4  christos 
   1756   1.7  christos cleanup:
   1757   1.1  christos 	if (result != ISC_R_SUCCESS) {
   1758   1.7  christos 		if (rpz->updbit != NULL) {
   1759   1.1  christos 			dns_dbiterator_destroy(&rpz->updbit);
   1760   1.7  christos 		}
   1761   1.7  christos 		if (rpz->newnodes != NULL) {
   1762   1.1  christos 			isc_ht_destroy(&rpz->newnodes);
   1763   1.7  christos 		}
   1764   1.3  christos 		dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
   1765   1.1  christos 	}
   1766   1.1  christos 
   1767   1.1  christos 	return (result);
   1768   1.1  christos }
   1769   1.1  christos 
   1770   1.1  christos static void
   1771   1.1  christos finish_update(dns_rpz_zone_t *rpz) {
   1772   1.1  christos 	LOCK(&rpz->rpzs->maint_lock);
   1773   1.3  christos 	rpz->updaterunning = false;
   1774   1.7  christos 
   1775   1.1  christos 	/*
   1776   1.7  christos 	 * If there's an update pending, schedule it.
   1777   1.1  christos 	 */
   1778   1.8  christos 	if (rpz->updatepending) {
   1779   1.3  christos 		if (rpz->min_update_interval > 0) {
   1780   1.3  christos 			uint64_t defer = rpz->min_update_interval;
   1781   1.7  christos 			char dname[DNS_NAME_FORMATSIZE];
   1782   1.3  christos 			isc_interval_t interval;
   1783   1.7  christos 
   1784   1.3  christos 			dns_name_format(&rpz->origin, dname,
   1785   1.3  christos 					DNS_NAME_FORMATSIZE);
   1786   1.3  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1787   1.3  christos 				      DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
   1788   1.3  christos 				      "rpz: %s: new zone version came "
   1789   1.3  christos 				      "too soon, deferring update for "
   1790   1.7  christos 				      "%" PRIu64 " seconds",
   1791   1.7  christos 				      dname, defer);
   1792   1.3  christos 			isc_interval_set(&interval, (unsigned int)defer, 0);
   1793   1.3  christos 			isc_timer_reset(rpz->updatetimer, isc_timertype_once,
   1794   1.3  christos 					NULL, &interval, true);
   1795   1.3  christos 		} else {
   1796   1.7  christos 			isc_event_t *event = NULL;
   1797   1.3  christos 			INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
   1798   1.3  christos 			ISC_EVENT_INIT(&rpz->updateevent,
   1799   1.3  christos 				       sizeof(rpz->updateevent), 0, NULL,
   1800   1.3  christos 				       DNS_EVENT_RPZUPDATED,
   1801   1.7  christos 				       dns_rpz_update_taskaction, rpz, rpz,
   1802   1.7  christos 				       NULL, NULL);
   1803   1.3  christos 			event = &rpz->updateevent;
   1804   1.3  christos 			isc_task_send(rpz->rpzs->updater, &event);
   1805   1.3  christos 		}
   1806   1.1  christos 	}
   1807   1.1  christos 	UNLOCK(&rpz->rpzs->maint_lock);
   1808   1.7  christos }
   1809   1.7  christos 
   1810   1.7  christos static void
   1811   1.7  christos cleanup_quantum(isc_task_t *task, isc_event_t *event) {
   1812   1.7  christos 	isc_result_t result = ISC_R_SUCCESS;
   1813   1.7  christos 	char domain[DNS_NAME_FORMATSIZE];
   1814   1.7  christos 	dns_rpz_zone_t *rpz = NULL;
   1815   1.7  christos 	isc_ht_iter_t *iter = NULL;
   1816   1.7  christos 	dns_fixedname_t fname;
   1817   1.7  christos 	dns_name_t *name = NULL;
   1818   1.7  christos 	int count = 0;
   1819   1.7  christos 
   1820   1.7  christos 	UNUSED(task);
   1821   1.7  christos 
   1822   1.7  christos 	REQUIRE(event != NULL);
   1823   1.7  christos 	REQUIRE(event->ev_sender != NULL);
   1824   1.7  christos 
   1825   1.7  christos 	rpz = (dns_rpz_zone_t *)event->ev_sender;
   1826   1.7  christos 	iter = (isc_ht_iter_t *)event->ev_arg;
   1827   1.7  christos 	isc_event_free(&event);
   1828   1.7  christos 
   1829   1.7  christos 	if (iter == NULL) {
   1830   1.7  christos 		/*
   1831   1.7  christos 		 * Iterate over old ht with existing nodes deleted to
   1832   1.7  christos 		 * delete deleted nodes from RPZ
   1833   1.7  christos 		 */
   1834  1.11  christos 		isc_ht_iter_create(rpz->nodes, &iter);
   1835   1.7  christos 	}
   1836   1.7  christos 
   1837   1.7  christos 	name = dns_fixedname_initname(&fname);
   1838   1.1  christos 
   1839   1.7  christos 	LOCK(&rpz->rpzs->maint_lock);
   1840   1.7  christos 
   1841   1.7  christos 	/* Check that we aren't shutting down. */
   1842   1.7  christos 	if (rpz->rpzs->zones[rpz->num] == NULL) {
   1843   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   1844   1.7  christos 		goto cleanup;
   1845   1.7  christos 	}
   1846   1.7  christos 
   1847   1.7  christos 	for (result = isc_ht_iter_first(iter);
   1848   1.7  christos 	     result == ISC_R_SUCCESS && count++ < DNS_RPZ_QUANTUM;
   1849   1.7  christos 	     result = isc_ht_iter_delcurrent_next(iter))
   1850   1.7  christos 	{
   1851   1.7  christos 		isc_region_t region;
   1852   1.7  christos 		unsigned char *key = NULL;
   1853   1.7  christos 		size_t keysize;
   1854   1.7  christos 
   1855   1.7  christos 		isc_ht_iter_currentkey(iter, &key, &keysize);
   1856   1.7  christos 		region.base = key;
   1857   1.7  christos 		region.length = (unsigned int)keysize;
   1858   1.7  christos 		dns_name_fromregion(name, &region);
   1859   1.7  christos 		dns_rpz_delete(rpz->rpzs, rpz->num, name);
   1860   1.7  christos 	}
   1861   1.7  christos 
   1862   1.7  christos 	if (result == ISC_R_SUCCESS) {
   1863   1.7  christos 		isc_event_t *nevent = NULL;
   1864   1.7  christos 
   1865   1.7  christos 		/*
   1866   1.7  christos 		 * We finished a quantum; trigger the next one and return.
   1867   1.7  christos 		 */
   1868   1.7  christos 
   1869   1.7  christos 		INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
   1870   1.7  christos 		ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
   1871   1.7  christos 			       NULL, DNS_EVENT_RPZUPDATED, cleanup_quantum,
   1872   1.7  christos 			       iter, rpz, NULL, NULL);
   1873   1.7  christos 		nevent = &rpz->updateevent;
   1874   1.7  christos 		isc_task_send(rpz->rpzs->updater, &nevent);
   1875   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   1876   1.7  christos 		return;
   1877   1.7  christos 	} else if (result == ISC_R_NOMORE) {
   1878   1.7  christos 		isc_ht_t *tmpht = NULL;
   1879   1.7  christos 
   1880   1.7  christos 		/*
   1881   1.7  christos 		 * Done with cleanup of deleted nodes; finalize
   1882   1.7  christos 		 * the update.
   1883   1.7  christos 		 */
   1884   1.7  christos 		tmpht = rpz->nodes;
   1885   1.7  christos 		rpz->nodes = rpz->newnodes;
   1886   1.7  christos 		rpz->newnodes = tmpht;
   1887   1.7  christos 
   1888   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   1889   1.7  christos 		finish_update(rpz);
   1890   1.7  christos 		dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
   1891   1.7  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1892   1.7  christos 			      DNS_LOGMODULE_MASTER, ISC_LOG_INFO,
   1893   1.7  christos 			      "rpz: %s: reload done", domain);
   1894   1.7  christos 	} else {
   1895   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   1896   1.7  christos 	}
   1897   1.7  christos 
   1898   1.7  christos 	/*
   1899   1.7  christos 	 * If we're here, we're finished or something went wrong.
   1900   1.7  christos 	 */
   1901   1.1  christos cleanup:
   1902   1.7  christos 	if (iter != NULL) {
   1903   1.1  christos 		isc_ht_iter_destroy(&iter);
   1904   1.7  christos 	}
   1905   1.7  christos 	if (rpz->newnodes != NULL) {
   1906   1.7  christos 		isc_ht_destroy(&rpz->newnodes);
   1907   1.7  christos 	}
   1908   1.7  christos 	dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
   1909   1.7  christos 	dns_db_detach(&rpz->updb);
   1910   1.7  christos 	rpz_detach(&rpz);
   1911   1.1  christos }
   1912   1.1  christos 
   1913   1.1  christos static void
   1914   1.1  christos update_quantum(isc_task_t *task, isc_event_t *event) {
   1915   1.1  christos 	isc_result_t result = ISC_R_SUCCESS;
   1916   1.1  christos 	dns_dbnode_t *node = NULL;
   1917   1.7  christos 	dns_rpz_zone_t *rpz = NULL;
   1918   1.1  christos 	char domain[DNS_NAME_FORMATSIZE];
   1919   1.1  christos 	dns_fixedname_t fixname;
   1920   1.7  christos 	dns_name_t *name = NULL;
   1921   1.7  christos 	isc_event_t *nevent = NULL;
   1922   1.1  christos 	int count = 0;
   1923   1.1  christos 
   1924   1.1  christos 	UNUSED(task);
   1925   1.1  christos 
   1926   1.1  christos 	REQUIRE(event != NULL);
   1927   1.1  christos 	REQUIRE(event->ev_arg != NULL);
   1928   1.1  christos 
   1929   1.7  christos 	rpz = (dns_rpz_zone_t *)event->ev_arg;
   1930   1.1  christos 	isc_event_free(&event);
   1931   1.1  christos 
   1932   1.1  christos 	REQUIRE(rpz->updbit != NULL);
   1933   1.1  christos 	REQUIRE(rpz->newnodes != NULL);
   1934   1.1  christos 
   1935   1.1  christos 	name = dns_fixedname_initname(&fixname);
   1936   1.1  christos 
   1937   1.1  christos 	dns_name_format(&rpz->origin, domain, DNS_NAME_FORMATSIZE);
   1938   1.1  christos 
   1939   1.7  christos 	LOCK(&rpz->rpzs->maint_lock);
   1940   1.7  christos 
   1941   1.7  christos 	/* Check that we aren't shutting down. */
   1942   1.7  christos 	if (rpz->rpzs->zones[rpz->num] == NULL) {
   1943   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   1944   1.7  christos 		goto cleanup;
   1945   1.7  christos 	}
   1946   1.7  christos 
   1947   1.1  christos 	while (result == ISC_R_SUCCESS && count++ < DNS_RPZ_QUANTUM) {
   1948   1.1  christos 		char namebuf[DNS_NAME_FORMATSIZE];
   1949   1.1  christos 		dns_rdatasetiter_t *rdsiter = NULL;
   1950   1.1  christos 
   1951   1.1  christos 		result = dns_dbiterator_current(rpz->updbit, &node, name);
   1952   1.1  christos 		if (result != ISC_R_SUCCESS) {
   1953   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1954   1.1  christos 				      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1955   1.1  christos 				      "rpz: %s: failed to get dbiterator - %s",
   1956   1.1  christos 				      domain, isc_result_totext(result));
   1957   1.1  christos 			dns_db_detachnode(rpz->updb, &node);
   1958   1.1  christos 			break;
   1959   1.1  christos 		}
   1960   1.1  christos 
   1961   1.1  christos 		result = dns_db_allrdatasets(rpz->updb, node, rpz->updbversion,
   1962  1.12  christos 					     0, 0, &rdsiter);
   1963   1.1  christos 		if (result != ISC_R_SUCCESS) {
   1964   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1965   1.1  christos 				      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1966   1.1  christos 				      "rpz: %s: failed to fetch "
   1967   1.1  christos 				      "rrdatasets - %s",
   1968   1.1  christos 				      domain, isc_result_totext(result));
   1969   1.1  christos 			dns_db_detachnode(rpz->updb, &node);
   1970   1.1  christos 			break;
   1971   1.1  christos 		}
   1972   1.1  christos 
   1973   1.1  christos 		result = dns_rdatasetiter_first(rdsiter);
   1974   1.1  christos 		dns_rdatasetiter_destroy(&rdsiter);
   1975   1.1  christos 		if (result != ISC_R_SUCCESS) { /* empty non-terminal */
   1976   1.7  christos 			if (result != ISC_R_NOMORE) {
   1977   1.7  christos 				isc_log_write(
   1978   1.7  christos 					dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1979   1.7  christos 					DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1980   1.7  christos 					"rpz: %s: error %s while creating "
   1981   1.7  christos 					"rdatasetiter",
   1982   1.7  christos 					domain, isc_result_totext(result));
   1983   1.7  christos 			}
   1984   1.1  christos 			dns_db_detachnode(rpz->updb, &node);
   1985   1.1  christos 			result = dns_dbiterator_next(rpz->updbit);
   1986   1.1  christos 			continue;
   1987   1.1  christos 		}
   1988   1.1  christos 
   1989   1.9  christos 		dns_name_downcase(name, name, NULL);
   1990   1.7  christos 		result = isc_ht_add(rpz->newnodes, name->ndata, name->length,
   1991   1.7  christos 				    rpz);
   1992   1.1  christos 		if (result != ISC_R_SUCCESS) {
   1993   1.1  christos 			dns_name_format(name, namebuf, sizeof(namebuf));
   1994   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   1995   1.1  christos 				      DNS_LOGMODULE_MASTER, ISC_LOG_ERROR,
   1996   1.1  christos 				      "rpz: %s, adding node %s to HT error %s",
   1997   1.1  christos 				      domain, namebuf,
   1998   1.1  christos 				      isc_result_totext(result));
   1999   1.1  christos 			dns_db_detachnode(rpz->updb, &node);
   2000   1.1  christos 			result = dns_dbiterator_next(rpz->updbit);
   2001   1.1  christos 			continue;
   2002   1.1  christos 		}
   2003   1.1  christos 
   2004   1.7  christos 		result = isc_ht_find(rpz->nodes, name->ndata, name->length,
   2005   1.7  christos 				     NULL);
   2006   1.1  christos 		if (result == ISC_R_SUCCESS) {
   2007   1.1  christos 			isc_ht_delete(rpz->nodes, name->ndata, name->length);
   2008   1.1  christos 		} else { /* not found */
   2009   1.1  christos 			result = dns_rpz_add(rpz->rpzs, rpz->num, name);
   2010   1.1  christos 			if (result != ISC_R_SUCCESS) {
   2011   1.1  christos 				dns_name_format(name, namebuf, sizeof(namebuf));
   2012   1.7  christos 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2013   1.1  christos 					      DNS_LOGMODULE_MASTER,
   2014   1.1  christos 					      ISC_LOG_ERROR,
   2015   1.1  christos 					      "rpz: %s: adding node %s "
   2016   1.1  christos 					      "to RPZ error %s",
   2017   1.1  christos 					      domain, namebuf,
   2018   1.1  christos 					      isc_result_totext(result));
   2019   1.1  christos 			} else {
   2020   1.1  christos 				dns_name_format(name, namebuf, sizeof(namebuf));
   2021   1.7  christos 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
   2022   1.1  christos 					      DNS_LOGMODULE_MASTER,
   2023   1.1  christos 					      ISC_LOG_DEBUG(3),
   2024   1.7  christos 					      "rpz: %s: adding node %s", domain,
   2025   1.7  christos 					      namebuf);
   2026   1.1  christos 			}
   2027   1.1  christos 		}
   2028   1.1  christos 
   2029   1.1  christos 		dns_db_detachnode(rpz->updb, &node);
   2030   1.1  christos 		result = dns_dbiterator_next(rpz->updbit);
   2031   1.1  christos 	}
   2032   1.1  christos 
   2033   1.1  christos 	if (result == ISC_R_SUCCESS) {
   2034   1.1  christos 		/*
   2035   1.7  christos 		 * Pause the iterator so that the DB is not locked.
   2036   1.1  christos 		 */
   2037   1.1  christos 		dns_dbiterator_pause(rpz->updbit);
   2038   1.7  christos 
   2039   1.1  christos 		/*
   2040   1.7  christos 		 * We finished a quantum; trigger the next one and return.
   2041   1.1  christos 		 */
   2042   1.1  christos 		INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
   2043   1.7  christos 		ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
   2044   1.7  christos 			       NULL, DNS_EVENT_RPZUPDATED, update_quantum, rpz,
   2045   1.7  christos 			       rpz, NULL, NULL);
   2046   1.1  christos 		nevent = &rpz->updateevent;
   2047   1.1  christos 		isc_task_send(rpz->rpzs->updater, &nevent);
   2048   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   2049   1.1  christos 		return;
   2050   1.1  christos 	} else if (result == ISC_R_NOMORE) {
   2051   1.1  christos 		/*
   2052   1.7  christos 		 * Done with the new database; now we just need to
   2053   1.7  christos 		 * clean up the old.
   2054   1.1  christos 		 */
   2055   1.7  christos 		dns_dbiterator_destroy(&rpz->updbit);
   2056   1.7  christos 
   2057   1.7  christos 		INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
   2058   1.7  christos 		ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0,
   2059   1.7  christos 			       NULL, DNS_EVENT_RPZUPDATED, cleanup_quantum,
   2060   1.7  christos 			       NULL, rpz, NULL, NULL);
   2061   1.7  christos 		nevent = &rpz->updateevent;
   2062   1.7  christos 		isc_task_send(rpz->rpzs->updater, &nevent);
   2063   1.7  christos 		UNLOCK(&rpz->rpzs->maint_lock);
   2064   1.7  christos 		return;
   2065   1.1  christos 	}
   2066   1.1  christos 
   2067   1.1  christos 	/*
   2068   1.7  christos 	 * If we're here, something went wrong, so clean up.
   2069   1.1  christos 	 */
   2070   1.7  christos 	UNLOCK(&rpz->rpzs->maint_lock);
   2071   1.7  christos 
   2072   1.7  christos cleanup:
   2073   1.7  christos 	if (rpz->updbit != NULL) {
   2074   1.1  christos 		dns_dbiterator_destroy(&rpz->updbit);
   2075   1.7  christos 	}
   2076   1.7  christos 	if (rpz->newnodes != NULL) {
   2077   1.1  christos 		isc_ht_destroy(&rpz->newnodes);
   2078   1.7  christos 	}
   2079   1.3  christos 	dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
   2080   1.1  christos 	dns_db_detach(&rpz->updb);
   2081   1.5  christos 	rpz_detach(&rpz);
   2082   1.1  christos }
   2083   1.1  christos 
   2084   1.1  christos static void
   2085   1.1  christos dns_rpz_update_from_db(dns_rpz_zone_t *rpz) {
   2086   1.1  christos 	isc_result_t result;
   2087   1.1  christos 	isc_event_t *event;
   2088   1.1  christos 
   2089   1.1  christos 	REQUIRE(rpz != NULL);
   2090   1.1  christos 	REQUIRE(DNS_DB_VALID(rpz->db));
   2091   1.1  christos 	REQUIRE(rpz->updb == NULL);
   2092   1.1  christos 	REQUIRE(rpz->updbversion == NULL);
   2093   1.1  christos 	REQUIRE(rpz->updbit == NULL);
   2094   1.1  christos 	REQUIRE(rpz->newnodes == NULL);
   2095   1.1  christos 
   2096   1.5  christos 	isc_refcount_increment(&rpz->refs);
   2097   1.1  christos 	dns_db_attach(rpz->db, &rpz->updb);
   2098   1.1  christos 	rpz->updbversion = rpz->dbversion;
   2099   1.1  christos 	rpz->dbversion = NULL;
   2100   1.1  christos 
   2101   1.1  christos 	result = setup_update(rpz);
   2102   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2103   1.1  christos 		goto cleanup;
   2104   1.1  christos 	}
   2105   1.1  christos 
   2106   1.1  christos 	event = &rpz->updateevent;
   2107   1.1  christos 	INSIST(!ISC_LINK_LINKED(&rpz->updateevent, ev_link));
   2108   1.7  christos 	ISC_EVENT_INIT(&rpz->updateevent, sizeof(rpz->updateevent), 0, NULL,
   2109   1.7  christos 		       DNS_EVENT_RPZUPDATED, update_quantum, rpz, rpz, NULL,
   2110   1.7  christos 		       NULL);
   2111   1.1  christos 	isc_task_send(rpz->rpzs->updater, &event);
   2112   1.1  christos 	return;
   2113   1.1  christos 
   2114   1.7  christos cleanup:
   2115   1.7  christos 	if (rpz->updbit != NULL) {
   2116   1.1  christos 		dns_dbiterator_destroy(&rpz->updbit);
   2117   1.7  christos 	}
   2118   1.7  christos 	if (rpz->newnodes != NULL) {
   2119   1.1  christos 		isc_ht_destroy(&rpz->newnodes);
   2120   1.7  christos 	}
   2121   1.3  christos 	dns_db_closeversion(rpz->updb, &rpz->updbversion, false);
   2122   1.1  christos 	dns_db_detach(&rpz->updb);
   2123   1.5  christos 	rpz_detach(&rpz);
   2124   1.1  christos }
   2125   1.1  christos 
   2126   1.1  christos /*
   2127   1.1  christos  * Free the radix tree of a response policy database.
   2128   1.1  christos  */
   2129   1.1  christos static void
   2130   1.1  christos cidr_free(dns_rpz_zones_t *rpzs) {
   2131   1.1  christos 	dns_rpz_cidr_node_t *cur, *child, *parent;
   2132   1.1  christos 
   2133   1.1  christos 	cur = rpzs->cidr;
   2134   1.1  christos 	while (cur != NULL) {
   2135   1.1  christos 		/* Depth first. */
   2136   1.1  christos 		child = cur->child[0];
   2137   1.1  christos 		if (child != NULL) {
   2138   1.1  christos 			cur = child;
   2139   1.1  christos 			continue;
   2140   1.1  christos 		}
   2141   1.1  christos 		child = cur->child[1];
   2142   1.1  christos 		if (child != NULL) {
   2143   1.1  christos 			cur = child;
   2144   1.1  christos 			continue;
   2145   1.1  christos 		}
   2146   1.1  christos 
   2147   1.1  christos 		/* Delete this leaf and go up. */
   2148   1.1  christos 		parent = cur->parent;
   2149   1.7  christos 		if (parent == NULL) {
   2150   1.1  christos 			rpzs->cidr = NULL;
   2151   1.7  christos 		} else {
   2152   1.1  christos 			parent->child[parent->child[1] == cur] = NULL;
   2153   1.7  christos 		}
   2154   1.1  christos 		isc_mem_put(rpzs->mctx, cur, sizeof(*cur));
   2155   1.1  christos 		cur = parent;
   2156   1.1  christos 	}
   2157   1.1  christos }
   2158   1.1  christos 
   2159   1.1  christos /*
   2160   1.1  christos  * Discard a response policy zone blob
   2161   1.1  christos  * before discarding the overall rpz structure.
   2162   1.1  christos  */
   2163   1.1  christos static void
   2164   1.5  christos rpz_detach(dns_rpz_zone_t **rpzp) {
   2165   1.1  christos 	dns_rpz_zone_t *rpz;
   2166   1.5  christos 	dns_rpz_zones_t *rpzs;
   2167   1.3  christos 
   2168   1.3  christos 	REQUIRE(rpzp != NULL && *rpzp != NULL);
   2169   1.1  christos 
   2170   1.1  christos 	rpz = *rpzp;
   2171   1.1  christos 	*rpzp = NULL;
   2172   1.3  christos 
   2173   1.7  christos 	if (isc_refcount_decrement(&rpz->refs) == 1) {
   2174   1.7  christos 		isc_refcount_destroy(&rpz->refs);
   2175   1.3  christos 
   2176   1.7  christos 		rpzs = rpz->rpzs;
   2177   1.7  christos 		rpz->rpzs = NULL;
   2178   1.1  christos 
   2179   1.7  christos 		if (dns_name_dynamic(&rpz->origin)) {
   2180   1.7  christos 			dns_name_free(&rpz->origin, rpzs->mctx);
   2181   1.7  christos 		}
   2182   1.7  christos 		if (dns_name_dynamic(&rpz->client_ip)) {
   2183   1.7  christos 			dns_name_free(&rpz->client_ip, rpzs->mctx);
   2184   1.7  christos 		}
   2185   1.7  christos 		if (dns_name_dynamic(&rpz->ip)) {
   2186   1.7  christos 			dns_name_free(&rpz->ip, rpzs->mctx);
   2187   1.7  christos 		}
   2188   1.7  christos 		if (dns_name_dynamic(&rpz->nsdname)) {
   2189   1.7  christos 			dns_name_free(&rpz->nsdname, rpzs->mctx);
   2190   1.7  christos 		}
   2191   1.7  christos 		if (dns_name_dynamic(&rpz->nsip)) {
   2192   1.7  christos 			dns_name_free(&rpz->nsip, rpzs->mctx);
   2193   1.7  christos 		}
   2194   1.7  christos 		if (dns_name_dynamic(&rpz->passthru)) {
   2195   1.7  christos 			dns_name_free(&rpz->passthru, rpzs->mctx);
   2196   1.7  christos 		}
   2197   1.7  christos 		if (dns_name_dynamic(&rpz->drop)) {
   2198   1.7  christos 			dns_name_free(&rpz->drop, rpzs->mctx);
   2199   1.7  christos 		}
   2200   1.7  christos 		if (dns_name_dynamic(&rpz->tcp_only)) {
   2201   1.7  christos 			dns_name_free(&rpz->tcp_only, rpzs->mctx);
   2202   1.7  christos 		}
   2203   1.7  christos 		if (dns_name_dynamic(&rpz->cname)) {
   2204   1.7  christos 			dns_name_free(&rpz->cname, rpzs->mctx);
   2205   1.3  christos 		}
   2206   1.7  christos 		if (rpz->db != NULL) {
   2207   1.7  christos 			if (rpz->dbversion != NULL) {
   2208   1.7  christos 				dns_db_closeversion(rpz->db, &rpz->dbversion,
   2209   1.7  christos 						    false);
   2210   1.7  christos 			}
   2211   1.7  christos 			dns_db_updatenotify_unregister(
   2212   1.7  christos 				rpz->db, dns_rpz_dbupdate_callback, rpz);
   2213   1.7  christos 			dns_db_detach(&rpz->db);
   2214   1.7  christos 		}
   2215   1.7  christos 		if (rpz->updaterunning) {
   2216   1.7  christos 			isc_task_purgeevent(rpzs->updater, &rpz->updateevent);
   2217   1.7  christos 			if (rpz->updbit != NULL) {
   2218   1.7  christos 				dns_dbiterator_destroy(&rpz->updbit);
   2219   1.7  christos 			}
   2220   1.7  christos 			if (rpz->newnodes != NULL) {
   2221   1.7  christos 				isc_ht_destroy(&rpz->newnodes);
   2222   1.7  christos 			}
   2223   1.7  christos 			if (rpz->updb != NULL) {
   2224   1.7  christos 				if (rpz->updbversion != NULL) {
   2225   1.7  christos 					dns_db_closeversion(rpz->updb,
   2226   1.7  christos 							    &rpz->updbversion,
   2227   1.7  christos 							    false);
   2228   1.7  christos 				}
   2229   1.7  christos 				dns_db_detach(&rpz->updb);
   2230   1.7  christos 			}
   2231   1.3  christos 		}
   2232   1.3  christos 
   2233   1.7  christos 		isc_timer_reset(rpz->updatetimer, isc_timertype_inactive, NULL,
   2234   1.7  christos 				NULL, true);
   2235   1.7  christos 		isc_timer_detach(&rpz->updatetimer);
   2236   1.1  christos 
   2237   1.7  christos 		isc_ht_destroy(&rpz->nodes);
   2238   1.5  christos 
   2239   1.7  christos 		isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz));
   2240   1.7  christos 		rpz_detach_rpzs(&rpzs);
   2241   1.7  christos 	}
   2242   1.1  christos }
   2243   1.1  christos 
   2244   1.1  christos void
   2245   1.1  christos dns_rpz_attach_rpzs(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **rpzsp) {
   2246   1.1  christos 	REQUIRE(rpzsp != NULL && *rpzsp == NULL);
   2247   1.3  christos 	isc_refcount_increment(&rpzs->refs);
   2248   1.1  christos 	*rpzsp = rpzs;
   2249   1.1  christos }
   2250   1.1  christos 
   2251   1.1  christos /*
   2252   1.1  christos  * Forget a view's policy zones.
   2253   1.1  christos  */
   2254   1.1  christos void
   2255   1.1  christos dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
   2256   1.3  christos 	REQUIRE(rpzsp != NULL && *rpzsp != NULL);
   2257   1.3  christos 	dns_rpz_zones_t *rpzs = *rpzsp;
   2258   1.3  christos 	*rpzsp = NULL;
   2259   1.1  christos 
   2260   1.3  christos 	if (isc_refcount_decrement(&rpzs->refs) == 1) {
   2261   1.7  christos 		LOCK(&rpzs->maint_lock);
   2262   1.3  christos 		/*
   2263   1.3  christos 		 * Forget the last of view's rpz machinery after
   2264   1.3  christos 		 * the last reference.
   2265   1.3  christos 		 */
   2266   1.7  christos 		for (dns_rpz_num_t rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES;
   2267  1.12  christos 		     ++rpz_num)
   2268  1.12  christos 		{
   2269   1.3  christos 			dns_rpz_zone_t *rpz = rpzs->zones[rpz_num];
   2270   1.3  christos 			rpzs->zones[rpz_num] = NULL;
   2271   1.3  christos 			if (rpz != NULL) {
   2272   1.5  christos 				rpz_detach(&rpz);
   2273   1.3  christos 			}
   2274   1.1  christos 		}
   2275   1.7  christos 		UNLOCK(&rpzs->maint_lock);
   2276   1.5  christos 		rpz_detach_rpzs(&rpzs);
   2277   1.5  christos 	}
   2278   1.5  christos }
   2279   1.5  christos 
   2280   1.5  christos static void
   2281   1.5  christos rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) {
   2282   1.5  christos 	REQUIRE(rpzsp != NULL && *rpzsp != NULL);
   2283   1.5  christos 	dns_rpz_zones_t *rpzs = *rpzsp;
   2284   1.5  christos 	*rpzsp = NULL;
   2285   1.1  christos 
   2286   1.5  christos 	if (isc_refcount_decrement(&rpzs->irefs) == 1) {
   2287   1.3  christos 		if (rpzs->rps_cstr_size != 0) {
   2288   1.1  christos #ifdef USE_DNSRPS
   2289   1.3  christos 			librpz->client_detach(&rpzs->rps_client);
   2290   1.7  christos #endif /* ifdef USE_DNSRPS */
   2291   1.3  christos 			isc_mem_put(rpzs->mctx, rpzs->rps_cstr,
   2292   1.3  christos 				    rpzs->rps_cstr_size);
   2293   1.3  christos 		}
   2294   1.3  christos 
   2295   1.3  christos 		cidr_free(rpzs);
   2296   1.3  christos 		if (rpzs->rbt != NULL) {
   2297   1.3  christos 			dns_rbt_destroy(&rpzs->rbt);
   2298   1.3  christos 		}
   2299   1.7  christos 		isc_task_destroy(&rpzs->updater);
   2300   1.3  christos 		isc_mutex_destroy(&rpzs->maint_lock);
   2301   1.3  christos 		isc_rwlock_destroy(&rpzs->search_lock);
   2302   1.3  christos 		isc_refcount_destroy(&rpzs->refs);
   2303   1.3  christos 		isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs));
   2304   1.1  christos 	}
   2305   1.1  christos }
   2306   1.1  christos 
   2307   1.1  christos /*
   2308   1.1  christos  * Deprecated and removed.
   2309   1.1  christos  */
   2310   1.1  christos isc_result_t
   2311   1.7  christos dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp, dns_rpz_zones_t *rpzs,
   2312   1.7  christos 		  dns_rpz_num_t rpz_num) {
   2313   1.1  christos 	UNUSED(load_rpzsp);
   2314   1.1  christos 	UNUSED(rpzs);
   2315   1.1  christos 	UNUSED(rpz_num);
   2316   1.1  christos 
   2317   1.1  christos 	return (ISC_R_NOTIMPLEMENTED);
   2318   1.1  christos }
   2319   1.1  christos 
   2320   1.1  christos /*
   2321   1.1  christos  * Deprecated and removed.
   2322   1.1  christos  */
   2323   1.1  christos isc_result_t
   2324   1.7  christos dns_rpz_ready(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **load_rpzsp,
   2325   1.7  christos 	      dns_rpz_num_t rpz_num) {
   2326   1.1  christos 	UNUSED(rpzs);
   2327   1.1  christos 	UNUSED(load_rpzsp);
   2328   1.1  christos 	UNUSED(rpz_num);
   2329   1.1  christos 
   2330   1.1  christos 	return (ISC_R_NOTIMPLEMENTED);
   2331   1.1  christos }
   2332   1.1  christos 
   2333   1.1  christos /*
   2334   1.1  christos  * Add an IP address to the radix tree or a name to the summary database.
   2335   1.1  christos  */
   2336   1.1  christos isc_result_t
   2337   1.1  christos dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
   2338   1.7  christos 	    const dns_name_t *src_name) {
   2339   1.1  christos 	dns_rpz_zone_t *rpz;
   2340   1.1  christos 	dns_rpz_type_t rpz_type;
   2341   1.1  christos 	isc_result_t result = ISC_R_FAILURE;
   2342   1.1  christos 
   2343   1.1  christos 	REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
   2344   1.1  christos 	rpz = rpzs->zones[rpz_num];
   2345   1.1  christos 	REQUIRE(rpz != NULL);
   2346   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
   2347   1.1  christos 
   2348   1.1  christos 	rpz_type = type_from_name(rpzs, rpz, src_name);
   2349   1.1  christos 
   2350   1.1  christos 	switch (rpz_type) {
   2351   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
   2352   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
   2353   1.1  christos 		result = add_name(rpzs, rpz_num, rpz_type, src_name);
   2354   1.1  christos 		break;
   2355   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   2356   1.1  christos 	case DNS_RPZ_TYPE_IP:
   2357   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   2358   1.1  christos 		result = add_cidr(rpzs, rpz_num, rpz_type, src_name);
   2359   1.1  christos 		break;
   2360   1.1  christos 	case DNS_RPZ_TYPE_BAD:
   2361   1.1  christos 		break;
   2362   1.1  christos 	}
   2363   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
   2364   1.1  christos 
   2365   1.1  christos 	return (result);
   2366   1.1  christos }
   2367   1.1  christos 
   2368   1.1  christos /*
   2369   1.1  christos  * Remove an IP address from the radix tree.
   2370   1.1  christos  */
   2371   1.1  christos static void
   2372   1.7  christos del_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_rpz_type_t rpz_type,
   2373   1.7  christos 	 const dns_name_t *src_name) {
   2374   1.1  christos 	isc_result_t result;
   2375   1.1  christos 	dns_rpz_cidr_key_t tgt_ip;
   2376   1.1  christos 	dns_rpz_prefix_t tgt_prefix;
   2377   1.1  christos 	dns_rpz_addr_zbits_t tgt_set;
   2378   1.1  christos 	dns_rpz_cidr_node_t *tgt, *parent, *child;
   2379   1.1  christos 
   2380   1.1  christos 	/*
   2381   1.1  christos 	 * Do not worry about invalid rpz IP address names.  If we
   2382   1.1  christos 	 * are here, then something relevant was added and so was
   2383   1.1  christos 	 * valid.  Invalid names here are usually internal RBTDB nodes.
   2384   1.1  christos 	 */
   2385   1.1  christos 	result = name2ipkey(DNS_RPZ_DEBUG_QUIET, rpzs, rpz_num, rpz_type,
   2386   1.1  christos 			    src_name, &tgt_ip, &tgt_prefix, &tgt_set);
   2387   1.7  christos 	if (result != ISC_R_SUCCESS) {
   2388   1.1  christos 		return;
   2389   1.7  christos 	}
   2390   1.1  christos 
   2391   1.3  christos 	result = search(rpzs, &tgt_ip, tgt_prefix, &tgt_set, false, &tgt);
   2392   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2393   1.1  christos 		INSIST(result == ISC_R_NOTFOUND ||
   2394   1.1  christos 		       result == DNS_R_PARTIALMATCH);
   2395   1.1  christos 		/*
   2396   1.1  christos 		 * Do not worry about missing summary RBT nodes that probably
   2397   1.1  christos 		 * correspond to RBTDB nodes that were implicit RBT nodes
   2398   1.1  christos 		 * that were later added for (often empty) wildcards
   2399   1.1  christos 		 * and then to the RBTDB deferred cleanup list.
   2400   1.1  christos 		 */
   2401   1.1  christos 		return;
   2402   1.1  christos 	}
   2403   1.1  christos 
   2404   1.1  christos 	/*
   2405   1.1  christos 	 * Mark the node and its parents to reflect the deleted IP address.
   2406   1.1  christos 	 * Do not count bits that are already clear for internal RBTDB nodes.
   2407   1.1  christos 	 */
   2408   1.1  christos 	tgt_set.client_ip &= tgt->set.client_ip;
   2409   1.1  christos 	tgt_set.ip &= tgt->set.ip;
   2410   1.1  christos 	tgt_set.nsip &= tgt->set.nsip;
   2411   1.1  christos 	tgt->set.client_ip &= ~tgt_set.client_ip;
   2412   1.1  christos 	tgt->set.ip &= ~tgt_set.ip;
   2413   1.1  christos 	tgt->set.nsip &= ~tgt_set.nsip;
   2414   1.1  christos 	set_sum_pair(tgt);
   2415   1.1  christos 
   2416   1.7  christos 	adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, false);
   2417   1.1  christos 
   2418   1.1  christos 	/*
   2419   1.1  christos 	 * We might need to delete 2 nodes.
   2420   1.1  christos 	 */
   2421   1.1  christos 	do {
   2422   1.1  christos 		/*
   2423   1.1  christos 		 * The node is now useless if it has no data of its own
   2424   1.1  christos 		 * and 0 or 1 children.  We are finished if it is not useless.
   2425   1.1  christos 		 */
   2426   1.1  christos 		if ((child = tgt->child[0]) != NULL) {
   2427   1.7  christos 			if (tgt->child[1] != NULL) {
   2428   1.1  christos 				break;
   2429   1.7  christos 			}
   2430   1.1  christos 		} else {
   2431   1.1  christos 			child = tgt->child[1];
   2432   1.1  christos 		}
   2433   1.7  christos 		if (tgt->set.client_ip != 0 || tgt->set.ip != 0 ||
   2434  1.12  christos 		    tgt->set.nsip != 0)
   2435  1.12  christos 		{
   2436   1.1  christos 			break;
   2437   1.7  christos 		}
   2438   1.1  christos 
   2439   1.1  christos 		/*
   2440   1.1  christos 		 * Replace the pointer to this node in the parent with
   2441   1.1  christos 		 * the remaining child or NULL.
   2442   1.1  christos 		 */
   2443   1.1  christos 		parent = tgt->parent;
   2444   1.1  christos 		if (parent == NULL) {
   2445   1.1  christos 			rpzs->cidr = child;
   2446   1.1  christos 		} else {
   2447   1.1  christos 			parent->child[parent->child[1] == tgt] = child;
   2448   1.1  christos 		}
   2449   1.1  christos 		/*
   2450   1.1  christos 		 * If the child exists fix up its parent pointer.
   2451   1.1  christos 		 */
   2452   1.7  christos 		if (child != NULL) {
   2453   1.1  christos 			child->parent = parent;
   2454   1.7  christos 		}
   2455   1.1  christos 		isc_mem_put(rpzs->mctx, tgt, sizeof(*tgt));
   2456   1.1  christos 
   2457   1.1  christos 		tgt = parent;
   2458   1.1  christos 	} while (tgt != NULL);
   2459   1.1  christos }
   2460   1.1  christos 
   2461   1.1  christos static void
   2462   1.7  christos del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_rpz_type_t rpz_type,
   2463   1.7  christos 	 const dns_name_t *src_name) {
   2464   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
   2465   1.1  christos 	dns_fixedname_t trig_namef;
   2466   1.1  christos 	dns_name_t *trig_name;
   2467   1.1  christos 	dns_rbtnode_t *nmnode;
   2468   1.1  christos 	dns_rpz_nm_data_t *nm_data, del_data;
   2469   1.1  christos 	isc_result_t result;
   2470   1.3  christos 	bool exists;
   2471   1.1  christos 
   2472   1.1  christos 	/*
   2473   1.1  christos 	 * We need a summary database of names even with 1 policy zone,
   2474   1.1  christos 	 * because wildcard triggers are handled differently.
   2475   1.1  christos 	 */
   2476   1.1  christos 
   2477   1.1  christos 	trig_name = dns_fixedname_initname(&trig_namef);
   2478   1.1  christos 	name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &del_data);
   2479   1.1  christos 
   2480   1.1  christos 	nmnode = NULL;
   2481   1.1  christos 	result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL, 0,
   2482   1.1  christos 				  NULL, NULL);
   2483   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2484   1.1  christos 		/*
   2485   1.1  christos 		 * Do not worry about missing summary RBT nodes that probably
   2486   1.1  christos 		 * correspond to RBTDB nodes that were implicit RBT nodes
   2487   1.1  christos 		 * that were later added for (often empty) wildcards
   2488   1.1  christos 		 * and then to the RBTDB deferred cleanup list.
   2489   1.1  christos 		 */
   2490   1.7  christos 		if (result == ISC_R_NOTFOUND || result == DNS_R_PARTIALMATCH) {
   2491   1.1  christos 			return;
   2492   1.7  christos 		}
   2493   1.1  christos 		dns_name_format(src_name, namebuf, sizeof(namebuf));
   2494   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
   2495   1.1  christos 			      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
   2496   1.1  christos 			      "rpz del_name(%s) node search failed: %s",
   2497   1.1  christos 			      namebuf, isc_result_totext(result));
   2498   1.1  christos 		return;
   2499   1.1  christos 	}
   2500   1.1  christos 
   2501   1.1  christos 	nm_data = nmnode->data;
   2502   1.1  christos 	INSIST(nm_data != NULL);
   2503   1.1  christos 
   2504   1.1  christos 	/*
   2505   1.1  christos 	 * Do not count bits that next existed for RBT nodes that would we
   2506   1.1  christos 	 * would not have found in a summary for a single RBTDB tree.
   2507   1.1  christos 	 */
   2508   1.1  christos 	del_data.set.qname &= nm_data->set.qname;
   2509   1.1  christos 	del_data.set.ns &= nm_data->set.ns;
   2510   1.1  christos 	del_data.wild.qname &= nm_data->wild.qname;
   2511   1.1  christos 	del_data.wild.ns &= nm_data->wild.ns;
   2512   1.1  christos 
   2513   1.3  christos 	exists = (del_data.set.qname != 0 || del_data.set.ns != 0 ||
   2514   1.3  christos 		  del_data.wild.qname != 0 || del_data.wild.ns != 0);
   2515   1.1  christos 
   2516   1.1  christos 	nm_data->set.qname &= ~del_data.set.qname;
   2517   1.1  christos 	nm_data->set.ns &= ~del_data.set.ns;
   2518   1.1  christos 	nm_data->wild.qname &= ~del_data.wild.qname;
   2519   1.1  christos 	nm_data->wild.ns &= ~del_data.wild.ns;
   2520   1.1  christos 
   2521   1.1  christos 	if (nm_data->set.qname == 0 && nm_data->set.ns == 0 &&
   2522   1.7  christos 	    nm_data->wild.qname == 0 && nm_data->wild.ns == 0)
   2523   1.7  christos 	{
   2524   1.3  christos 		result = dns_rbt_deletenode(rpzs->rbt, nmnode, false);
   2525   1.1  christos 		if (result != ISC_R_SUCCESS) {
   2526   1.1  christos 			/*
   2527   1.1  christos 			 * bin/tests/system/rpz/tests.sh looks for
   2528   1.1  christos 			 * "rpz.*failed".
   2529   1.1  christos 			 */
   2530   1.1  christos 			dns_name_format(src_name, namebuf, sizeof(namebuf));
   2531   1.1  christos 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
   2532   1.1  christos 				      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
   2533   1.1  christos 				      "rpz del_name(%s) node delete failed: %s",
   2534   1.1  christos 				      namebuf, isc_result_totext(result));
   2535   1.1  christos 		}
   2536   1.1  christos 	}
   2537   1.1  christos 
   2538   1.7  christos 	if (exists) {
   2539   1.3  christos 		adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, false);
   2540   1.7  christos 	}
   2541   1.1  christos }
   2542   1.1  christos 
   2543   1.1  christos /*
   2544   1.1  christos  * Remove an IP address from the radix tree or a name from the summary database.
   2545   1.1  christos  */
   2546   1.1  christos void
   2547   1.1  christos dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num,
   2548   1.7  christos 	       const dns_name_t *src_name) {
   2549   1.1  christos 	dns_rpz_zone_t *rpz;
   2550   1.1  christos 	dns_rpz_type_t rpz_type;
   2551   1.1  christos 
   2552   1.1  christos 	REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones);
   2553   1.1  christos 	rpz = rpzs->zones[rpz_num];
   2554   1.1  christos 	REQUIRE(rpz != NULL);
   2555   1.1  christos 
   2556   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_write);
   2557   1.1  christos 
   2558   1.1  christos 	rpz_type = type_from_name(rpzs, rpz, src_name);
   2559   1.1  christos 
   2560   1.1  christos 	switch (rpz_type) {
   2561   1.1  christos 	case DNS_RPZ_TYPE_QNAME:
   2562   1.1  christos 	case DNS_RPZ_TYPE_NSDNAME:
   2563   1.1  christos 		del_name(rpzs, rpz_num, rpz_type, src_name);
   2564   1.1  christos 		break;
   2565   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   2566   1.1  christos 	case DNS_RPZ_TYPE_IP:
   2567   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   2568   1.1  christos 		del_cidr(rpzs, rpz_num, rpz_type, src_name);
   2569   1.1  christos 		break;
   2570   1.1  christos 	case DNS_RPZ_TYPE_BAD:
   2571   1.1  christos 		break;
   2572   1.1  christos 	}
   2573   1.1  christos 
   2574   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_write);
   2575   1.1  christos }
   2576   1.1  christos 
   2577   1.1  christos /*
   2578   1.1  christos  * Search the summary radix tree to get a relative owner name in a
   2579   1.1  christos  * policy zone relevant to a triggering IP address.
   2580   1.1  christos  *	rpz_type and zbits limit the search for IP address netaddr
   2581   1.1  christos  *	return the policy zone's number or DNS_RPZ_INVALID_NUM
   2582   1.1  christos  *	ip_name is the relative owner name found and
   2583   1.1  christos  *	*prefixp is its prefix length.
   2584   1.1  christos  */
   2585   1.1  christos dns_rpz_num_t
   2586   1.1  christos dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
   2587   1.1  christos 		dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr,
   2588   1.7  christos 		dns_name_t *ip_name, dns_rpz_prefix_t *prefixp) {
   2589   1.1  christos 	dns_rpz_cidr_key_t tgt_ip;
   2590   1.1  christos 	dns_rpz_addr_zbits_t tgt_set;
   2591   1.1  christos 	dns_rpz_cidr_node_t *found;
   2592   1.1  christos 	isc_result_t result;
   2593   1.3  christos 	dns_rpz_num_t rpz_num = 0;
   2594   1.1  christos 	dns_rpz_have_t have;
   2595   1.1  christos 	int i;
   2596   1.1  christos 
   2597   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2598   1.1  christos 	have = rpzs->have;
   2599   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2600   1.1  christos 
   2601   1.1  christos 	/*
   2602   1.1  christos 	 * Convert IP address to CIDR tree key.
   2603   1.1  christos 	 */
   2604   1.1  christos 	if (netaddr->family == AF_INET) {
   2605   1.1  christos 		tgt_ip.w[0] = 0;
   2606   1.1  christos 		tgt_ip.w[1] = 0;
   2607   1.1  christos 		tgt_ip.w[2] = ADDR_V4MAPPED;
   2608   1.1  christos 		tgt_ip.w[3] = ntohl(netaddr->type.in.s_addr);
   2609   1.1  christos 		switch (rpz_type) {
   2610   1.1  christos 		case DNS_RPZ_TYPE_CLIENT_IP:
   2611   1.1  christos 			zbits &= have.client_ipv4;
   2612   1.1  christos 			break;
   2613   1.1  christos 		case DNS_RPZ_TYPE_IP:
   2614   1.1  christos 			zbits &= have.ipv4;
   2615   1.1  christos 			break;
   2616   1.1  christos 		case DNS_RPZ_TYPE_NSIP:
   2617   1.1  christos 			zbits &= have.nsipv4;
   2618   1.1  christos 			break;
   2619   1.1  christos 		default:
   2620  1.11  christos 			UNREACHABLE();
   2621   1.1  christos 		}
   2622   1.1  christos 	} else if (netaddr->family == AF_INET6) {
   2623   1.1  christos 		dns_rpz_cidr_key_t src_ip6;
   2624   1.1  christos 
   2625   1.1  christos 		/*
   2626   1.1  christos 		 * Given the int aligned struct in_addr member of netaddr->type
   2627   1.1  christos 		 * one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *,
   2628   1.1  christos 		 * but some people object.
   2629   1.1  christos 		 */
   2630   1.1  christos 		memmove(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w));
   2631   1.1  christos 		for (i = 0; i < 4; i++) {
   2632   1.1  christos 			tgt_ip.w[i] = ntohl(src_ip6.w[i]);
   2633   1.1  christos 		}
   2634   1.1  christos 		switch (rpz_type) {
   2635   1.1  christos 		case DNS_RPZ_TYPE_CLIENT_IP:
   2636   1.1  christos 			zbits &= have.client_ipv6;
   2637   1.1  christos 			break;
   2638   1.1  christos 		case DNS_RPZ_TYPE_IP:
   2639   1.1  christos 			zbits &= have.ipv6;
   2640   1.1  christos 			break;
   2641   1.1  christos 		case DNS_RPZ_TYPE_NSIP:
   2642   1.1  christos 			zbits &= have.nsipv6;
   2643   1.1  christos 			break;
   2644   1.1  christos 		default:
   2645  1.11  christos 			UNREACHABLE();
   2646   1.1  christos 		}
   2647   1.1  christos 	} else {
   2648   1.1  christos 		return (DNS_RPZ_INVALID_NUM);
   2649   1.1  christos 	}
   2650   1.1  christos 
   2651   1.7  christos 	if (zbits == 0) {
   2652   1.1  christos 		return (DNS_RPZ_INVALID_NUM);
   2653   1.7  christos 	}
   2654   1.1  christos 	make_addr_set(&tgt_set, zbits, rpz_type);
   2655   1.1  christos 
   2656   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2657   1.3  christos 	result = search(rpzs, &tgt_ip, 128, &tgt_set, false, &found);
   2658   1.1  christos 	if (result == ISC_R_NOTFOUND) {
   2659   1.1  christos 		/*
   2660   1.1  christos 		 * There are no eligible zones for this IP address.
   2661   1.1  christos 		 */
   2662   1.1  christos 		RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2663   1.1  christos 		return (DNS_RPZ_INVALID_NUM);
   2664   1.1  christos 	}
   2665   1.1  christos 
   2666   1.1  christos 	/*
   2667   1.1  christos 	 * Construct the trigger name for the longest matching trigger
   2668   1.1  christos 	 * in the first eligible zone with a match.
   2669   1.1  christos 	 */
   2670   1.1  christos 	*prefixp = found->prefix;
   2671   1.1  christos 	switch (rpz_type) {
   2672   1.1  christos 	case DNS_RPZ_TYPE_CLIENT_IP:
   2673   1.1  christos 		rpz_num = zbit_to_num(found->set.client_ip & tgt_set.client_ip);
   2674   1.1  christos 		break;
   2675   1.1  christos 	case DNS_RPZ_TYPE_IP:
   2676   1.1  christos 		rpz_num = zbit_to_num(found->set.ip & tgt_set.ip);
   2677   1.1  christos 		break;
   2678   1.1  christos 	case DNS_RPZ_TYPE_NSIP:
   2679   1.1  christos 		rpz_num = zbit_to_num(found->set.nsip & tgt_set.nsip);
   2680   1.1  christos 		break;
   2681   1.1  christos 	default:
   2682  1.11  christos 		UNREACHABLE();
   2683   1.1  christos 	}
   2684   1.1  christos 	result = ip2name(&found->ip, found->prefix, dns_rootname, ip_name);
   2685   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2686   1.1  christos 	if (result != ISC_R_SUCCESS) {
   2687   1.1  christos 		/*
   2688   1.1  christos 		 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
   2689   1.1  christos 		 */
   2690   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
   2691   1.1  christos 			      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
   2692   1.1  christos 			      "rpz ip2name() failed: %s",
   2693   1.1  christos 			      isc_result_totext(result));
   2694   1.1  christos 		return (DNS_RPZ_INVALID_NUM);
   2695   1.1  christos 	}
   2696   1.1  christos 	return (rpz_num);
   2697   1.1  christos }
   2698   1.1  christos 
   2699   1.1  christos /*
   2700   1.1  christos  * Search the summary radix tree for policy zones with triggers matching
   2701   1.1  christos  * a name.
   2702   1.1  christos  */
   2703   1.1  christos dns_rpz_zbits_t
   2704   1.1  christos dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
   2705   1.7  christos 		  dns_rpz_zbits_t zbits, dns_name_t *trig_name) {
   2706   1.1  christos 	char namebuf[DNS_NAME_FORMATSIZE];
   2707   1.1  christos 	dns_rbtnode_t *nmnode;
   2708   1.1  christos 	const dns_rpz_nm_data_t *nm_data;
   2709   1.1  christos 	dns_rpz_zbits_t found_zbits;
   2710   1.6  christos 	dns_rbtnodechain_t chain;
   2711   1.1  christos 	isc_result_t result;
   2712   1.6  christos 	int i;
   2713   1.1  christos 
   2714   1.6  christos 	if (zbits == 0) {
   2715   1.1  christos 		return (0);
   2716   1.6  christos 	}
   2717   1.1  christos 
   2718   1.1  christos 	found_zbits = 0;
   2719   1.1  christos 
   2720   1.7  christos 	dns_rbtnodechain_init(&chain);
   2721   1.6  christos 
   2722   1.1  christos 	RWLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2723   1.1  christos 
   2724   1.1  christos 	nmnode = NULL;
   2725   1.7  christos 	result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, &chain,
   2726   1.7  christos 				  DNS_RBTFIND_EMPTYDATA, NULL, NULL);
   2727   1.9  christos 
   2728   1.1  christos 	switch (result) {
   2729   1.1  christos 	case ISC_R_SUCCESS:
   2730   1.1  christos 		nm_data = nmnode->data;
   2731   1.1  christos 		if (nm_data != NULL) {
   2732   1.6  christos 			if (rpz_type == DNS_RPZ_TYPE_QNAME) {
   2733   1.1  christos 				found_zbits = nm_data->set.qname;
   2734   1.6  christos 			} else {
   2735   1.1  christos 				found_zbits = nm_data->set.ns;
   2736   1.6  christos 			}
   2737   1.1  christos 		}
   2738  1.11  christos 		FALLTHROUGH;
   2739   1.6  christos 
   2740   1.1  christos 	case DNS_R_PARTIALMATCH:
   2741   1.6  christos 		i = chain.level_matches;
   2742   1.9  christos 		nmnode = chain.levels[chain.level_matches];
   2743   1.9  christos 
   2744   1.9  christos 		/*
   2745   1.9  christos 		 * Whenever an exact match is found by dns_rbt_findnode(),
   2746   1.9  christos 		 * the highest level node in the chain will not be put into
   2747   1.9  christos 		 * chain->levels[] array, but instead the chain->end
   2748   1.9  christos 		 * pointer will be adjusted to point to that node.
   2749   1.9  christos 		 *
   2750   1.9  christos 		 * Suppose we have the following entries in a rpz zone:
   2751   1.9  christos 		 *   example.com     CNAME rpz-passthru.
   2752   1.9  christos 		 *   *.example.com   CNAME rpz-passthru.
   2753   1.9  christos 		 *
   2754   1.9  christos 		 * A query for www.example.com would result in the
   2755   1.9  christos 		 * following chain object returned by dns_rbt_findnode():
   2756   1.9  christos 		 *   chain->level_count = 2
   2757   1.9  christos 		 *   chain->level_matches = 2
   2758   1.9  christos 		 *   chain->levels[0] = .
   2759   1.9  christos 		 *   chain->levels[1] = example.com
   2760   1.9  christos 		 *   chain->levels[2] = NULL
   2761   1.9  christos 		 *   chain->end = www
   2762   1.9  christos 		 *
   2763   1.9  christos 		 * Since exact matches only care for testing rpz set bits,
   2764   1.9  christos 		 * we need to test for rpz wild bits through iterating the
   2765   1.9  christos 		 * nodechain, and that includes testing the rpz wild bits
   2766   1.9  christos 		 * in the highest level node found. In the case of an exact
   2767   1.9  christos 		 * match, chain->levels[chain->level_matches] will be NULL,
   2768   1.9  christos 		 * to address that we must use chain->end as the start
   2769   1.9  christos 		 * point, then iterate over the remaining levels in the
   2770   1.9  christos 		 * chain.
   2771   1.9  christos 		 */
   2772   1.9  christos 		if (nmnode == NULL) {
   2773   1.9  christos 			--i;
   2774   1.9  christos 			nmnode = chain.end;
   2775   1.9  christos 		}
   2776   1.9  christos 
   2777   1.9  christos 		while (nmnode != NULL) {
   2778   1.1  christos 			nm_data = nmnode->data;
   2779   1.1  christos 			if (nm_data != NULL) {
   2780   1.6  christos 				if (rpz_type == DNS_RPZ_TYPE_QNAME) {
   2781   1.1  christos 					found_zbits |= nm_data->wild.qname;
   2782   1.6  christos 				} else {
   2783   1.1  christos 					found_zbits |= nm_data->wild.ns;
   2784   1.6  christos 				}
   2785   1.1  christos 			}
   2786   1.9  christos 
   2787   1.9  christos 			if (i >= 0) {
   2788   1.9  christos 				nmnode = chain.levels[i];
   2789   1.9  christos 				--i;
   2790   1.9  christos 			} else {
   2791   1.9  christos 				break;
   2792   1.9  christos 			}
   2793   1.1  christos 		}
   2794   1.1  christos 		break;
   2795   1.1  christos 
   2796   1.1  christos 	case ISC_R_NOTFOUND:
   2797   1.1  christos 		break;
   2798   1.1  christos 
   2799   1.1  christos 	default:
   2800   1.1  christos 		/*
   2801   1.1  christos 		 * bin/tests/system/rpz/tests.sh looks for "rpz.*failed".
   2802   1.1  christos 		 */
   2803   1.1  christos 		dns_name_format(trig_name, namebuf, sizeof(namebuf));
   2804   1.1  christos 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ,
   2805   1.1  christos 			      DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL,
   2806   1.7  christos 			      "dns_rpz_find_name(%s) failed: %s", namebuf,
   2807   1.7  christos 			      isc_result_totext(result));
   2808   1.1  christos 		break;
   2809   1.1  christos 	}
   2810   1.1  christos 
   2811   1.1  christos 	RWUNLOCK(&rpzs->search_lock, isc_rwlocktype_read);
   2812   1.6  christos 
   2813   1.6  christos 	dns_rbtnodechain_invalidate(&chain);
   2814   1.6  christos 
   2815   1.1  christos 	return (zbits & found_zbits);
   2816   1.1  christos }
   2817   1.1  christos 
   2818   1.1  christos /*
   2819   1.1  christos  * Translate CNAME rdata to a QNAME response policy action.
   2820   1.1  christos  */
   2821   1.1  christos dns_rpz_policy_t
   2822   1.1  christos dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset,
   2823   1.7  christos 		     dns_name_t *selfname) {
   2824   1.1  christos 	dns_rdata_t rdata = DNS_RDATA_INIT;
   2825   1.1  christos 	dns_rdata_cname_t cname;
   2826   1.1  christos 	isc_result_t result;
   2827   1.1  christos 
   2828   1.1  christos 	result = dns_rdataset_first(rdataset);
   2829   1.1  christos 	INSIST(result == ISC_R_SUCCESS);
   2830   1.1  christos 	dns_rdataset_current(rdataset, &rdata);
   2831   1.1  christos 	result = dns_rdata_tostruct(&rdata, &cname, NULL);
   2832   1.1  christos 	INSIST(result == ISC_R_SUCCESS);
   2833   1.1  christos 	dns_rdata_reset(&rdata);
   2834   1.1  christos 
   2835   1.1  christos 	/*
   2836   1.1  christos 	 * CNAME . means NXDOMAIN
   2837   1.1  christos 	 */
   2838   1.7  christos 	if (dns_name_equal(&cname.cname, dns_rootname)) {
   2839   1.1  christos 		return (DNS_RPZ_POLICY_NXDOMAIN);
   2840   1.7  christos 	}
   2841   1.1  christos 
   2842   1.1  christos 	if (dns_name_iswildcard(&cname.cname)) {
   2843   1.1  christos 		/*
   2844   1.1  christos 		 * CNAME *. means NODATA
   2845   1.1  christos 		 */
   2846   1.7  christos 		if (dns_name_countlabels(&cname.cname) == 2) {
   2847   1.1  christos 			return (DNS_RPZ_POLICY_NODATA);
   2848   1.7  christos 		}
   2849   1.1  christos 
   2850   1.1  christos 		/*
   2851   1.1  christos 		 * A qname of www.evil.com and a policy of
   2852   1.1  christos 		 *	*.evil.com    CNAME   *.garden.net
   2853   1.1  christos 		 * gives a result of
   2854   1.1  christos 		 *	evil.com    CNAME   evil.com.garden.net
   2855   1.1  christos 		 */
   2856   1.7  christos 		if (dns_name_countlabels(&cname.cname) > 2) {
   2857   1.1  christos 			return (DNS_RPZ_POLICY_WILDCNAME);
   2858   1.7  christos 		}
   2859   1.1  christos 	}
   2860   1.1  christos 
   2861   1.1  christos 	/*
   2862   1.1  christos 	 * CNAME rpz-tcp-only. means "send truncated UDP responses."
   2863   1.1  christos 	 */
   2864   1.7  christos 	if (dns_name_equal(&cname.cname, &rpz->tcp_only)) {
   2865   1.1  christos 		return (DNS_RPZ_POLICY_TCP_ONLY);
   2866   1.7  christos 	}
   2867   1.1  christos 
   2868   1.1  christos 	/*
   2869   1.1  christos 	 * CNAME rpz-drop. means "do not respond."
   2870   1.1  christos 	 */
   2871   1.7  christos 	if (dns_name_equal(&cname.cname, &rpz->drop)) {
   2872   1.1  christos 		return (DNS_RPZ_POLICY_DROP);
   2873   1.7  christos 	}
   2874   1.1  christos 
   2875   1.1  christos 	/*
   2876   1.1  christos 	 * CNAME rpz-passthru. means "do not rewrite."
   2877   1.1  christos 	 */
   2878   1.7  christos 	if (dns_name_equal(&cname.cname, &rpz->passthru)) {
   2879   1.1  christos 		return (DNS_RPZ_POLICY_PASSTHRU);
   2880   1.7  christos 	}
   2881   1.1  christos 
   2882   1.1  christos 	/*
   2883   1.1  christos 	 * 128.1.0.127.rpz-ip CNAME  128.1.0.0.127. is obsolete PASSTHRU
   2884   1.1  christos 	 */
   2885   1.7  christos 	if (selfname != NULL && dns_name_equal(&cname.cname, selfname)) {
   2886   1.1  christos 		return (DNS_RPZ_POLICY_PASSTHRU);
   2887   1.7  christos 	}
   2888   1.1  christos 
   2889   1.1  christos 	/*
   2890   1.1  christos 	 * Any other rdata gives a response consisting of the rdata.
   2891   1.1  christos 	 */
   2892   1.1  christos 	return (DNS_RPZ_POLICY_RECORD);
   2893   1.1  christos }
   2894