diff --git a/Makefile.in.diff b/Makefile.in.diff index 95eda63..9a651cf 100644 --- a/Makefile.in.diff +++ b/Makefile.in.diff @@ -2,7 +2,7 @@ Index: bind-9.9.3-P1/bin/named/Makefile.in =================================================================== --- bind-9.9.3-P1.orig/bin/named/Makefile.in +++ bind-9.9.3-P1/bin/named/Makefile.in -@@ -176,9 +176,7 @@ installdirs: +@@ -173,9 +173,7 @@ installdirs: install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir} (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@) diff --git a/baselibs.conf b/baselibs.conf index 0dc2632..1a221a2 100644 --- a/baselibs.conf +++ b/baselibs.conf @@ -1,22 +1,25 @@ -libbind9-90 -libdns100 +libbind9-140 +libdns146 libidnkit1 libidnkitlite1 libidnkitres1 -libisc95 +libirs141 +libisc142 obsoletes "bind-libs = " provides "bind-libs = " -libisccc90 -libisccfg90 -liblwres90 +libisccc140 +libisccfg140 +liblwres141 bind-devel requires -bind- - requires "libbind9-90- = " - requires "libisc95- = " - requires "libisccc90- = " - requires "libisccfg90- = " - requires "liblwres90- = " + requires "libbind9-140- = " + requires "libdns146- = " + requires "libirs141- = " + requires "libisc142- = " + requires "libisccc140- = " + requires "libisccfg140- = " + requires "liblwres141- = " idnkit-devel - requires "libdns100- = " + requires "libdns146- = " requires "libidnkit1- = " requires "libidnkitlite1- = " diff --git a/bind-9.10.1.tar.gz b/bind-9.10.1.tar.gz new file mode 100644 index 0000000..7800b95 --- /dev/null +++ b/bind-9.10.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5361eca2b8b6bc0b13904b0f964336a478dfbc165711547f6cc3f8752ac60181 +size 8353313 diff --git a/bind-9.10.1.tar.gz.asc b/bind-9.10.1.tar.gz.asc new file mode 100644 index 0000000..03acc10 --- /dev/null +++ b/bind-9.10.1.tar.gz.asc @@ -0,0 +1,11 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (GNU/Linux) + +iQEcBAABAgAGBQJUIAfBAAoJEEWseFcYnNvFmosIAMQn2vFb2j6iIqop7Fg4cJs5 +0hR1gFdcwkBZELKbLXkpL8qGOYrF9A8Wdjraf8i2iLUwZ1qsWLSL1wMokgamacRT +8VsQnfS6o1CO/uVrB7QysWmcovuAuHNj1d4v2M6CIGnbuUneQ6sQf28u6TWG6ENW +RtKUcz418WwghvQlBmoi2BVxluR+/15im87eUMsNajWRtNPLZJc2KvFnKHiZFvTU +36ffiAUC3nL/+61pHz7JvxzpJtgjyGtgSF16unPXAI1Oyg7lZOw0+cNUOnzclYy/ +UGw83PwxxtBjm9WmLPfnUqXPWKNzjCRPAiEDOvyCjEKD+HamDA7YxvV9D82aQW4= +=klq+ +-----END PGP SIGNATURE----- diff --git a/bind-9.9.5-P1.tar.gz b/bind-9.9.5-P1.tar.gz deleted file mode 100644 index 2439739..0000000 --- a/bind-9.9.5-P1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a41f7813f3a6eb0dcae961651ec93896fd82074929bc6c1d8c90b04a2417b850 -size 7730150 diff --git a/bind-9.9.5-P1.tar.gz.asc b/bind-9.9.5-P1.tar.gz.asc deleted file mode 100644 index 6166b6a..0000000 --- a/bind-9.9.5-P1.tar.gz.asc +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.12 (NetBSD) - -iQEcBAABAgAGBQJTldadAAoJEEWseFcYnNvFsLAH/iepQdJvNgfZ5inZ//Kp8QeO -5dv6f7a6UvfHZiD5wh8p9MCiIKVgxdeVV5HsSOsu8UpnzXRsmC2aH3etdxhlIsqu -QTGfJzLiIY1Y+/xnSqUXHfKdJ4aCsHQqXiGqFi8oAW26DIQgjHDRfLhYkEWBeXss -KjhCiI0FDjxvEqQ3orFWwUBV6RfHyIwTL186R/57r9xTtzJZFapvXMvV4TJjYAvU -8UqPwP36mD7sdQEjg6PCOnrDtCheHLwF1q5m3a1rsuKmV3W3a2BZvTA2mW1xdrHb -oo0Vbvt6GfzmFJHhs2G2VEj4405ALOmqLGejxs7pSbcZ1yyPlU/L/pcn+s1iB/Q= -=zuFR ------END PGP SIGNATURE----- diff --git a/bind-sdb-ldap.patch b/bind-sdb-ldap.patch index f225ca5..0e5fbe0 100644 --- a/bind-sdb-ldap.patch +++ b/bind-sdb-ldap.patch @@ -19,7 +19,7 @@ Index: bin/named/main.c =================================================================== --- bin/named/main.c.orig 2013-12-20 01:28:28.000000000 +0100 +++ bin/named/main.c 2014-01-23 18:45:19.059680008 +0100 -@@ -82,6 +82,7 @@ +@@ -85,6 +85,7 @@ * Include header files for database drivers here. */ /* #include "xxdb.h" */ @@ -27,7 +27,7 @@ Index: bin/named/main.c #ifdef CONTRIB_DLZ /* -@@ -922,6 +923,7 @@ +@@ -1016,6 +1017,7 @@ * Add calls to register sdb drivers here. */ /* xxdb_init(); */ @@ -35,7 +35,7 @@ Index: bin/named/main.c #ifdef ISC_DLZ_DLOPEN /* -@@ -958,6 +960,7 @@ +@@ -1056,6 +1058,7 @@ * Add calls to unregister sdb drivers here. */ /* xxdb_clear(); */ diff --git a/bind.changes b/bind.changes index 8c19d5f..571aab0 100644 --- a/bind.changes +++ b/bind.changes @@ -1,3 +1,187 @@ +------------------------------------------------------------------- +Thu Dec 4 18:36:41 UTC 2014 - lmuelle@suse.com + +- Add a versioned dependency when obsoleting packages. + +------------------------------------------------------------------- +Thu Dec 4 18:15:01 UTC 2014 - lmuelle@suse.com + +- Remove superfluous obsoletes *-64bit in the ifarch ppc64 case; (bnc#437293). + +------------------------------------------------------------------- +Wed Dec 3 16:58:24 UTC 2014 - lmuelle@suse.com + +- Fix gssapi_krb configure time header detection. + +------------------------------------------------------------------- +Sun Nov 30 13:52:44 UTC 2014 - lmuelle@suse.com + +- Update root zone (dated Nov 5, 2014). + +------------------------------------------------------------------- +Sat Nov 29 19:35:53 UTC 2014 - lmuelle@suse.com + +- Update to version 9.10.1 + - This release addresses the security flaws described in CVE-2014-3214 and + CVE-2014-3859. +- Update to version 9.10.0 + - DNS Response-rate limiting (DNS RRL), which blunts the impact of + reflection and amplification attacks, is always compiled in and no longer + requires a compile-time option to enable it. + - An experimental "Source Identity Token" (SIT) EDNS option is now available. + - A new zone file format, "map", stores zone data in a + format that can be mapped directly into memory, allowing + significantly faster zone loading. + - "delv" (domain entity lookup and validation) is a new tool with dig-like + semantics for looking up DNS data and performing internal DNSSEC + validation. + - Improved EDNS(0) processing for better resolver performance + and reliability over slow or lossy connections. + - Substantial improvement in response-policy zone (RPZ) performance. Up to + 32 response-policy zones can be configured with minimal performance loss. + - To improve recursive resolver performance, cache records which are still + being requested by clients can now be automatically refreshed from the + authoritative server before they expire, reducing or eliminating the time + window in which no answer is available in the cache. + - New "rpz-client-ip" triggers and drop policies allowing + response policies based on the IP address of the client. + - ACLs can now be specified based on geographic location using the MaxMind + GeoIP databases. Use "configure --with-geoip" to enable. + - Zone data can now be shared between views, allowing multiple views to serve + the same zones authoritatively without storing multiple copies in memory. + - New XML schema (version 3) for the statistics channel includes many new + statistics and uses a flattened XML tree for faster parsing. The older + schema is now deprecated. + - A new stylesheet, based on the Google Charts API, displays XML statistics + in charts and graphs on javascript-enabled browsers. + - The statistics channel can now provide data in JSON format as well as XML. + - New stats counters track TCP and UDP queries received + per zone, and EDNS options received in total. + - The internal and export versions of the BIND libraries (libisc, libdns, + etc) have been unified so that external library clients can use the same + libraries as BIND itself. + - A new compile-time option, "configure --enable-native-pkcs11", allows BIND + 9 cryptography functions to use the PKCS#11 API natively, so that BIND can + drive a cryptographic hardware service module (HSM) directly instead of + using a modified OpenSSL as an intermediary. + - The new "max-zone-ttl" option enforces maximum TTLs for zones. This can + simplify the process of rolling DNSSEC keys by guaranteeing that cached + signatures will have expired within the specified amount of time. + - "dig +subnet" sends an EDNS CLIENT-SUBNET option when querying. + - "dig +expire" sends an EDNS EXPIRE option when querying. + - New "dnssec-coverage" tool to check DNSSEC key coverage for a zone and + report if a lapse in signing coverage has been inadvertently scheduled. + - Signing algorithm flexibility and other improvements + for the "rndc" control channel. + - "named-checkzone" and "named-compilezone" can now read + journal files, allowing them to process dynamic zones. + - Multiple DLZ databases can now be configured. Individual zones can be + configured to be served from a specific DLZ database. DLZ databases now + serve zones of type "master" and "redirect". + - "rndc zonestatus" reports information about a specified zone. + - "named" now listens on IPv6 as well as IPv4 interfaces by default. + - "named" now preserves the capitalization of names + when responding to queries. + - new "dnssec-importkey" command allows the use of offline + DNSSEC keys with automatic DNSKEY management. + - New "named-rrchecker" tool to verify the syntactic + correctness of individual resource records. + - When re-signing a zone, the new "dnssec-signzone -Q" option drops + signatures from keys that are still published but are no longer active. + - "named-checkconf -px" will print the contents of configuration files with + the shared secrets obscured, making it easier to share configuration (e.g. + when submitting a bug report) without revealing private information. + - "rndc scan" causes named to re-scan network interfaces for + changes in local addresses. + - On operating systems with support for routing sockets, network interfaces + are re-scanned automatically whenever they change. + - "tsig-keygen" is now available as an alternate command + name to use for "ddns-confgen". +- Update to version 9.9.6 + New Features + - Support for CAA record types, as described in RFC 6844 "DNS + Certification Authority Authorization (CAA) Resource Record", + was added. [RT#36625] [RT #36737] + - Disallow "request-ixfr" from being specified in zone statements where it + is not valid (it is only valid for slave and redirect zones) [RT #36608] + - Support for CDS and CDNSKEY resource record types was added. For + details see the proposed Informational Internet-Draft "Automating + DNSSEC Delegation Trust Maintenance" at + http://tools.ietf.org/html/draft-ietf-dnsop-delegation-trust-maintainance-14. + [RT #36333] + - Added version printing options to various BIND utilities. [RT #26057] + [RT #10686] + - Added a "no-case-compress" ACL, which causes named to use case-insensitive + compression (disabling change #3645) for specified clients. (This is useful + when dealing with broken client implementations that use case-sensitive + name comparisons, rejecting responses that fail to match the capitalization + of the query that was sent.) [RT #35300] + Feature Changes + - Adds RPZ SOA to the additional section of responses to clearly + indicate the use of RPZ in a manner that is intended to avoid + causing issues for downstream resolvers and forwarders [RT #36507] + - rndc now gives distinct error messages when an unqualified zone + name matches multiple views vs. matching no views [RT #36691] + - Improves the accuracy of dig's reported round trip times. [RT #36611] + - When an SPF record exists in a zone but no equivalent TXT record + does, a warning will be issued. The warning for the reverse + condition is no longer issued. See the check-spf option in the + documentation for details. [RT #36210] + - "named" will now log explicitly when using rndc.key to configure + command channel. [RT #35316] + - The default setting for the -U option (setting the number of UDP + listeners per interface) has been adjusted to improve performance. + [RT #35417] + - Aging of smoothed round-trip time measurements is now limited + to no more than once per second, to improve accuracy in selecting + the best name server. [RT #32909] + - DNSSEC keys that have been marked active but have no publication + date are no longer presumed to be publishable. [RT #35063] + Bug Fixes + - The Makefile in bin/python was changed to work around a bmake + bug in FreeBSD 10 and NetBSD 6. [RT #36993] (**) + - Corrected bugs in the handling of wildcard records by the DNSSEC + validator: invalid wildcard expansions could be treated as valid + if signed, and valid wildcard expansions in NSEC3 opt-out ranges + had the AD bit set incorrectly in responses. [RT #37093] [RT #37072] + - When resigning, dnssec-signzone was removing all signatures from + delegation nodes. It now retains DS and (if applicable) NSEC + signatures. [RT #36946] + - The AD flag was being set inappopriately on RPZ responses. [RT #36833] + - Updates the URI record type to current draft standard, + draft-faltstrom-uri-08, and allows the value field to be zero + length [RT #36642] [RT #36737] + - RRSIG sets that were not loaded in a single transaction at start + up were not being correctly added to re-signing heaps. [RT #36302] + - Setting '-t aaaa' in .digrc had unintended side-effects. [RT #36452] + - A race condition could cause a crash in isc_event_free during + shutdown. [RT #36720] + - Addresses a race condition issue in dispatch. [RT #36731] + - acl elements could be miscounted, causing a crash while loading + a config [RT #36675] + - Corrects a deadlock between view.c and adb.c. [RT #36341] + - liblwres wasn't properly handling link-local addresses in + nameserver clauses in resolv.conf. [RT #36039] + - Buffers in isc_print_vsnprintf were not properly initialized + leading to potential overflows when printing out quad values. + [RT #36505] + - Don't call qsort() with a null pointer, and disable the GCC 4.9 + "delete null pointer check" optimizer option. This fixes problems + when using GNU GCC 4.9.0 where its compiler code optimizations + may cause crashes in BIND. For more information, see the operational + advisory at https://kb.isc.org/article/AA-01167/. [RT #35968] + - Fixed a bug that could cause repeated resigning of records in + dynamically signed zones. [RT #35273] + - Fixed a bug that could cause an assertion failure after forwarding + was disabled. [RT #35979] + - Fixed a bug that caused SERVFAILs when using RPZ on a system + configured as a forwarder. [RT #36060] + - Worked around a limitation in Solaris's /dev/poll implementation + that could cause named to fail to start when configured to use + more sockets than the system could accomodate. [RT #35878] +- Remove merged rpz2+rl-9.9.5.patch and obsoleted rpz2+rl-9.9.5.patch +- Update baselibs.conf (added libirs and library interface version updates). + ------------------------------------------------------------------- Fri Nov 14 09:18:26 UTC 2014 - dimstar@opensuse.org @@ -17,7 +201,7 @@ Wed Oct 1 15:26:40 UTC 2014 - jengelh@inai.de ------------------------------------------------------------------- Mon Sep 8 21:10:50 UTC 2014 - werner@suse.de -- Require systemd-rpm-macros at build +- Require systemd-rpm-macros at build ------------------------------------------------------------------- Mon Sep 8 14:00:01 UTC 2014 - werner@suse.de @@ -166,12 +350,12 @@ Sun Jun 1 13:30:10 UTC 2014 - chris@computersalat.de ------------------------------------------------------------------- Sun May 25 17:24:21 UTC 2014 - crrodriguez@opensuse.org -- Build with LFS_CFLAGS in 32 bit systems. +- Build with LFS_CFLAGS in 32 bit systems. ------------------------------------------------------------------- Thu May 8 11:23:47 CEST 2014 - ro@suse.de -- use %_rundir macro +- use %_rundir macro ------------------------------------------------------------------- Fri Mar 28 20:49:57 CET 2014 - lchiquitto@suse.de @@ -256,7 +440,7 @@ Mon Jun 24 13:17:11 UTC 2013 - meissner@suse.com - [maint] Added AAAA for D.ROOT-SERVERS.NET. - [maint] D.ROOT-SERVERS.NET is now 199.7.91.13. -- Updated to current rate limiting + rpz patch from +- Updated to current rate limiting + rpz patch from http://ss.vix.su/~vjs/rrlrpz.html - moved dnssec-* helpers to bind-utils package. bnc#813911 @@ -768,7 +952,7 @@ Thu May 5 16:59:49 CEST 2011 - ug@suse.de Thu Feb 24 11:14:09 CET 2011 - ug@suse.de - fixed security issue - VUL-0: bind: IXFR or DDNS update combined with high query rate + VUL-0: bind: IXFR or DDNS update combined with high query rate DoS vulnerability (CVE-2011-0414 bnc#674431) - version to 9.7.3 @@ -953,7 +1137,7 @@ Wed Sep 30 15:44:32 CEST 2009 - ug@suse.de ------------------------------------------------------------------- Mon Aug 10 15:30:23 CEST 2009 - ug@suse.de -- version update to 9.6.1-P1 +- version update to 9.6.1-P1 (security fix CVE-2009-0696) bnc#526185 @@ -977,7 +1161,7 @@ Thu Apr 9 11:27:57 CEST 2009 - ug@suse.de ------------------------------------------------------------------- Tue Mar 3 11:08:59 CET 2009 - ug@suse.de -- /etc/named.conf does not include /etc/named.d/forwarders.conf +- /etc/named.conf does not include /etc/named.d/forwarders.conf by default (bnc#480334) ------------------------------------------------------------------- @@ -1014,7 +1198,7 @@ Wed Nov 26 09:53:06 CET 2008 - ug@suse.de ------------------------------------------------------------------- Tue Nov 11 16:54:01 CET 2008 - ro@suse.de -- SLE-11 uses PPC64 instead of PPC, adapt baselibs.conf +- SLE-11 uses PPC64 instead of PPC, adapt baselibs.conf ------------------------------------------------------------------- Thu Oct 30 12:34:56 CET 2008 - olh@suse.de @@ -1057,7 +1241,7 @@ Tue Aug 12 16:39:27 CEST 2008 - ug@suse.de outstanding UDP queries as possible + additional security of port randomization at the same level as P1 -- also includes fixes for several bugs in the 9.5.0 base code +- also includes fixes for several bugs in the 9.5.0 base code - 9.5.0-P2 ------------------------------------------------------------------- @@ -1069,9 +1253,9 @@ Sun Jul 27 11:51:38 CEST 2008 - aj@suse.de ------------------------------------------------------------------- Wed Jul 16 12:50:46 CEST 2008 - ug@suse.de -- BIND 9.5 offers many new features, including many - behind-the-scenes improvements. For the most part, the non-visible - features help ISC's customers who have run into the upper-end of +- BIND 9.5 offers many new features, including many + behind-the-scenes improvements. For the most part, the non-visible + features help ISC's customers who have run into the upper-end of what BIND 9.4 could handle. See CHANGES for details - Statistics Counters / server @@ -1120,7 +1304,7 @@ Thu Jul 26 13:46:45 CEST 2007 - mt@suse.de ------------------------------------------------------------------- Sat May 26 23:43:35 CEST 2007 - ro@suse.de -- added ldconfig to postinstall script for bind-libs +- added ldconfig to postinstall script for bind-libs ------------------------------------------------------------------- Tue May 15 12:19:20 CEST 2007 - ug@suse.de @@ -1251,7 +1435,7 @@ Fri Jan 27 00:49:18 CET 2006 - mls@suse.de ------------------------------------------------------------------- Wed Jan 25 14:27:11 CET 2006 - ug@suse.de -- fixed #145169 +- fixed #145169 (follow symlinks during chroot jail creation) ------------------------------------------------------------------- @@ -1273,7 +1457,7 @@ Mon Nov 21 12:16:32 CET 2005 - ug@suse.de ------------------------------------------------------------------- Mon Sep 26 01:27:01 CEST 2005 - ro@suse.de -- added LDAP_DEPRECATED to CFLAGS +- added LDAP_DEPRECATED to CFLAGS ------------------------------------------------------------------- Fri Jul 22 16:50:27 CEST 2005 - lmuelle@suse.de @@ -1303,7 +1487,7 @@ Fri Mar 11 18:28:37 CET 2005 - ug@suse.de - version update from 9.3.0 to 9.3.1 - fixed bug #72153 - lwresd doesn't notice if name server is + lwresd doesn't notice if name server is unreachable and times out ------------------------------------------------------------------- @@ -1623,7 +1807,7 @@ Tue Mar 4 17:50:58 CET 2003 - lmuelle@suse.de ------------------------------------------------------------------- Sat Mar 1 17:41:47 CET 2003 - ro@suse.de -- also create named user/group in utils preinstall +- also create named user/group in utils preinstall ------------------------------------------------------------------- Thu Feb 27 23:53:01 CET 2003 - ro@suse.de @@ -1664,17 +1848,17 @@ Mon Feb 17 22:48:21 CET 2003 - lmuelle@suse.de ------------------------------------------------------------------- Wed Nov 13 01:43:18 CET 2002 - ro@suse.de -- fix build with current bison (end all rules with ";") +- fix build with current bison (end all rules with ";") ------------------------------------------------------------------- Sat Sep 7 16:31:04 CEST 2002 - kukuk@suse.de -- Fix running bind9 as user named [Bug #18417] +- Fix running bind9 as user named [Bug #18417] ------------------------------------------------------------------- Mon Aug 19 15:22:43 CEST 2002 - ro@suse.de -- added prereqs (#17807) +- added prereqs (#17807) ------------------------------------------------------------------- Mon Aug 19 12:50:37 CEST 2002 - okir@suse.de @@ -1717,7 +1901,7 @@ Mon Jun 3 10:59:07 CEST 2002 - okir@suse.de ------------------------------------------------------------------- Fri Dec 14 17:55:36 CET 2001 - ro@suse.de -- removed START_NAMED +- removed START_NAMED ------------------------------------------------------------------- Wed Sep 5 20:32:15 CEST 2001 - pthomas@suse.de @@ -1732,7 +1916,7 @@ Sun Aug 12 15:04:44 CEST 2001 - kukuk@suse.de ------------------------------------------------------------------- Wed Jul 4 09:06:38 CEST 2001 - bodammer@suse.de -- Update to bind-9.1.3 (release) +- Update to bind-9.1.3 (release) - Config-files moved away from bind-9.1.3.dif ------------------------------------------------------------------- @@ -1831,7 +2015,7 @@ Mon Feb 12 18:04:03 CET 2001 - bodammer@suse.de Thu Feb 8 12:08:50 CET 2001 - bodammer@suse.de - update to bind-9.1.1rc1 -- missing headerfile included in stdtime.c +- missing headerfile included in stdtime.c ------------------------------------------------------------------- Thu Jan 18 09:40:33 CET 2001 - bodammer@suse.de @@ -1846,7 +2030,7 @@ Tue Nov 28 19:01:37 CET 2000 - bodammer@suse.de ------------------------------------------------------------------- Thu Nov 23 23:46:02 CET 2000 - ro@suse.de -- added insserv calls +- added insserv calls ------------------------------------------------------------------- Thu Nov 23 22:40:37 CET 2000 - bodammer@suse.de @@ -1861,7 +2045,7 @@ Mon Nov 13 18:19:00 CET 2000 - bodammer@suse.de ------------------------------------------------------------------- Fri Oct 6 18:09:53 CEST 2000 - kukuk@suse.de -- change group tag +- change group tag ------------------------------------------------------------------- Mon Sep 18 11:07:47 CEST 2000 - bodammer@suse.de @@ -1893,7 +2077,7 @@ Thu Jul 13 09:53:58 CEST 2000 - bodammer@suse.de Mon Jul 3 23:10:21 CEST 2000 - bodammer@suse.de - update to bind-9.0.0b5 -- host renamed to host9 +- host renamed to host9 ------------------------------------------------------------------- Fri Jun 16 10:55:41 CEST 2000 - bodammer@suse.de diff --git a/bind.spec b/bind.spec index 93cf5d3..5a64195 100644 --- a/bind.spec +++ b/bind.spec @@ -18,8 +18,8 @@ Name: bind %define pkg_name bind -%define pkg_vers 9.9.5-P1 -%define rpm_vers 9.9.5P1 +%define pkg_vers 9.10.1 +%define rpm_vers 9.10.1 %define idn_vers 1.0 Summary: Domain Name System (DNS) Server (named) License: ISC @@ -37,7 +37,6 @@ Source9: ftp://ftp.internic.net/domain/named.root Source40: http://www.venaas.no/ldap/bind-sdb/dnszone-schema.txt Patch: configure.in.diff Patch1: Makefile.in.diff -Patch2: pid-path.diff Patch4: perl-path.diff Patch51: pie_compile.diff Patch52: named-bootconf.diff @@ -58,18 +57,13 @@ BuildRequires: update-desktop-files Provides: bind8 Provides: bind9 Provides: dns_daemon -Obsoletes: bind8 -Obsoletes: bind9 +Obsoletes: bind8 < %version +Obsoletes: bind9 < %version Requires: %{name}-chrootenv Requires: %{name}-utils PreReq: %fillup_prereq %insserv_prereq bind-utils /bin/grep /bin/sed /bin/mkdir /usr/bin/tee /bin/chmod /bin/chown /bin/mv /bin/cat /usr/bin/dirname /usr/bin/diff /usr/bin/old /usr/sbin/groupadd /usr/sbin/useradd /usr/sbin/usermod Url: http://isc.org/sw/bind/ -# Rate limiting patch by Paul Vixie et.al. for reflection DoS protection -# see http://www.redbarn.org/dns/ratelimits -#Patch200: http://ss.vix.su/~vjs/rpz2+rl-9.9.5.patch -Patch200: rpz2+rl-9.9.5.patch - Source60: dlz-schema.txt %if %ul_version >= 1 %define VENDOR UL @@ -135,23 +129,23 @@ idnkit is a toolkit for handling internationalized domain names. This subpackage contains the header files needed for building programs with it. -%package -n libbind9-90 +%package -n libbind9-140 Summary: BIND9 shared library used by BIND Group: System/Libraries Version: %rpm_vers Release: 0 -%description -n libbind9-90 +%description -n libbind9-140 This library contains a few utility functions used by the BIND server and utilities. -%package -n libdns100 +%package -n libdns146 Summary: DNS library uesd by BIND Group: System/Libraries Version: %rpm_vers Release: 0 -%description -n libdns100 +%description -n libdns146 This subpackage contains the "DNS client" module. This is a higher level API that provides an interface to name resolution, single DNS transaction with a particular server, and dynamic update. Regarding @@ -205,7 +199,33 @@ libidnkitres is a LD_PRELOAD-able library which provides a modified version of resolver functions (gethostbyname, getaddrinfo, etc.) which implement features for handling internationalized domain names. -%package -n libisc95 +%package -n libirs141 +Summary: The "IRS" (Information Retrieval System) library +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%description -n libirs141 +libirs provides an interface to parse the traditional resolv.conf file and an +"advanced" configuration file related to the DNS library for configuration +parameters that would be beyond the capability of the resolv.conf file. +Specifically, it is intended to provide DNSSEC related configuration +parameters. By default the path to this configuration file is /etc/dns.conf. + +%package -n libirs-devel +Summary: Development files for IRS +Group: Development/Libraries/C and C++ +Version: %rpm_vers +Release: 0 +Requires: libirs141 = %rpm_vers + +%description -n libirs-devel +libirs provides an interface to parse the traditional resolv.conf file and an +"advanced" configuration file related to the DNS library for configuration +parameters that would be beyond the capability of the resolv.conf file. This +subpackage contains the header files needed for building programs with it. + +%package -n libisc142 Summary: ISC shared library uesd by BIND Group: System/Libraries Version: %rpm_vers @@ -216,39 +236,39 @@ Release: 0 Obsoletes: bind-libs = %version-%release Provides: bind-libs < %version-%release -%description -n libisc95 +%description -n libisc142 This library contains miscellaneous utility function used by the BIND server and utilities. It includes functions for assertion handling, balanced binary (AVL) trees, bit masks comparison, event based programs, heap-based priority queues, memory handling, and program logging. -%package -n libisccc90 +%package -n libisccc140 Summary: Command Channel Library used by BIND Group: System/Libraries Version: %rpm_vers Release: 0 -%description -n libisccc90 +%description -n libisccc140 This library is used for communicating with BIND servers' administrative command channel (port 953 by default). -%package -n libisccfg90 +%package -n libisccfg140 Summary: Exported ISC configuration shared library Group: System/Libraries Version: %rpm_vers Release: 0 -%description -n libisccfg90 +%description -n libisccfg140 This BIND library contains the configuration file parser -%package -n liblwres90 +%package -n liblwres141 Summary: Lightweight Resolver API library Group: System/Libraries Version: %rpm_vers Release: 0 -%description -n liblwres90 +%description -n liblwres141 The BIND 9 lightweight resolver library is a name service independent stub resolver library. It provides hostname-to-address and address-to-hostname lookup services to applications by transmitting @@ -275,21 +295,17 @@ Summary: Development Libraries and Header Files of BIND Group: Development/Libraries/C and C++ Version: %rpm_vers Release: 0 -Requires: libbind9-90 = %version -Requires: libdns100 = %version -Requires: libisc95 = %version -Requires: libisccc90 = %version -Requires: libisccfg90 = %version -Requires: liblwres90 = %version +Requires: libbind9-140 = %version +Requires: libdns146 = %version +Requires: libirs141 = %version +Requires: libisc142 = %version +Requires: libisccc140 = %version +Requires: libisccfg140 = %version +Requires: liblwres141 = %version Provides: bind8-devel Provides: bind9-devel -Obsoletes: bind8-devel -Obsoletes: bind9-devel -# bug437293 -%ifarch ppc64 -Obsoletes: bind-devel-64bit -%endif -# +Obsoletes: bind8-devel < %version +Obsoletes: bind9-devel < %version %description devel This package contains the header files, libraries, and documentation @@ -339,13 +355,8 @@ Release: 0 Provides: bind9-utils Provides: bindutil Provides: dns_utils -Obsoletes: bind9-utils -Obsoletes: bindutil -# bug437293 -%ifarch ppc64 -Obsoletes: bind-utils-64bit -%endif -# +Obsoletes: bind9-utils < %version +Obsoletes: bindutil < %version %description utils This package includes the utilities host, dig, and nslookup used to @@ -358,7 +369,6 @@ Name Domain (BIND) DNS server is found in the package named bind. %setup -q -n %{pkg_name}-%{pkg_vers} -T -D -a1 %patch -p1 %patch1 -p1 -%patch2 -p0 %patch4 -p0 #%patch50 %if 0%{?suse_version} >= 1000 @@ -370,7 +380,6 @@ Name Domain (BIND) DNS server is found in the package named bind. %patch100 -p1 %endif %patch101 -p1 -%patch200 -p0 # modify settings of some files regarding to OS version and vendor function replaceStrings() { @@ -392,7 +401,8 @@ cp contrib/sdb/ldap/ldapdb.h bin/named/include/ %build %{?suse_update_config:%{suse_update_config -f}} -cat /usr/share/aclocal/libtool.m4 >> aclocal.m4 +# gssapi/gssapi_krb5.h isn't found if aclocal.m4 gets modified this way +#cat /usr/share/aclocal/libtool.m4 >> aclocal.m4 %{__libtoolize} -f %{__aclocal} %{__autoconf} @@ -423,15 +433,15 @@ CONFIGURE_OPTIONS="\ --includedir=%{_includedir}/bind \ --mandir=%{_mandir} \ --infodir=%{_infodir} \ - --disable-static \ + --disable-static \ --with-openssl \ --enable-threads \ --with-libtool \ --enable-runidn \ --with-libxml2 \ --with-dlz-mysql \ - --with-dlz-ldap \ - --enable-rrl + --with-dlz-ldap \ + --enable-rrl " cp -f -p config.guess config.sub contrib/idn/idnkit-1.0-src/ ./configure ${CONFIGURE_OPTIONS} @@ -469,7 +479,7 @@ mkdir -p \ ${RPM_BUILD_ROOT}/%{_sysconfdir}/init.d \ ${RPM_BUILD_ROOT}/%{_sysconfdir}/named.d \ ${RPM_BUILD_ROOT}/%{_sysconfdir}/openldap/schema \ - ${RPM_BUILD_ROOT}/%{_sysconfdir}/slp.reg.d \ + ${RPM_BUILD_ROOT}/%{_sysconfdir}/slp.reg.d \ ${RPM_BUILD_ROOT}/usr/{bin,%{_lib},sbin,include} \ ${RPM_BUILD_ROOT}/%{_datadir}/bind \ ${RPM_BUILD_ROOT}/%{_datadir}/susehelp/meta/Administration/System \ @@ -478,7 +488,7 @@ mkdir -p \ ${RPM_BUILD_ROOT}%{_mandir}/{man1,man3,man5,man8} \ ${RPM_BUILD_ROOT}/var/adm/fillup-templates \ ${RPM_BUILD_ROOT}/%{_rundir} \ - ${RPM_BUILD_ROOT}/%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services + ${RPM_BUILD_ROOT}/%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services %{__make} DESTDIR=${RPM_BUILD_ROOT} install pushd contrib/idn/idnkit-1.0-src %{__make} DESTDIR=${RPM_BUILD_ROOT} install @@ -693,24 +703,26 @@ fi %insserv_cleanup %service_del_postun named -%post -n libbind9-90 -p /sbin/ldconfig -%postun -n libbind9-90 -p /sbin/ldconfig -%post -n libdns100 -p /sbin/ldconfig -%postun -n libdns100 -p /sbin/ldconfig +%post -n libbind9-140 -p /sbin/ldconfig +%postun -n libbind9-140 -p /sbin/ldconfig +%post -n libdns146 -p /sbin/ldconfig +%postun -n libdns146 -p /sbin/ldconfig %post -n libidnkit1 -p /sbin/ldconfig %postun -n libidnkit1 -p /sbin/ldconfig %post -n libidnkitlite1 -p /sbin/ldconfig %postun -n libidnkitlite1 -p /sbin/ldconfig %post -n libidnkitres1 -p /sbin/ldconfig %postun -n libidnkitres1 -p /sbin/ldconfig -%post -n libisc95 -p /sbin/ldconfig -%postun -n libisc95 -p /sbin/ldconfig -%post -n libisccc90 -p /sbin/ldconfig -%postun -n libisccc90 -p /sbin/ldconfig -%post -n libisccfg90 -p /sbin/ldconfig -%postun -n libisccfg90 -p /sbin/ldconfig -%post -n liblwres90 -p /sbin/ldconfig -%postun -n liblwres90 -p /sbin/ldconfig +%post -n libirs141 -p /sbin/ldconfig +%postun -n libirs141 -p /sbin/ldconfig +%post -n libisc142 -p /sbin/ldconfig +%postun -n libisc142 -p /sbin/ldconfig +%post -n libisccc140 -p /sbin/ldconfig +%postun -n libisccc140 -p /sbin/ldconfig +%post -n libisccfg140 -p /sbin/ldconfig +%postun -n libisccfg140 -p /sbin/ldconfig +%post -n liblwres141 -p /sbin/ldconfig +%postun -n liblwres141 -p /sbin/ldconfig %pre chrootenv %{GROUPADD_NAMED} @@ -774,7 +786,9 @@ fi %{_sbindir}/named-checkconf %{_sbindir}/named-checkzone %{_sbindir}/named-compilezone +%{_sbindir}/named-rrchecker %{_mandir}/man1/bind9-config.1.gz +%{_mandir}/man1/named-rrchecker.1.gz %{_mandir}/man5/named.conf.5.gz %{_mandir}/man8/named-checkconf.8.gz %{_mandir}/man8/named-checkzone.8.gz @@ -814,13 +828,13 @@ fi %_libdir/libidn*.so %_mandir/man3/libidn*.3* -%files -n libbind9-90 +%files -n libbind9-140 %defattr(-,root,root) -%_libdir/libbind9.so.90* +%_libdir/libbind9.so.140* -%files -n libdns100 +%files -n libdns146 %defattr(-,root,root) -%_libdir/libdns.so.100* +%_libdir/libdns.so.146* %files -n libidnkit1 %defattr(-,root,root) @@ -834,21 +848,29 @@ fi %defattr(-,root,root) %_libdir/libidnkitres.so.1* -%files -n libisc95 +%files -n libirs141 %defattr(-,root,root) -%_libdir/libisc.so.95* +%_libdir/libirs.so.141* -%files -n libisccc90 +%files -n libirs-devel %defattr(-,root,root) -%_libdir/libisccc.so.90* +%_libdir/libirs.so -%files -n libisccfg90 +%files -n libisc142 %defattr(-,root,root) -%_libdir/libisccfg.so.90* +%_libdir/libisc.so.142* -%files -n liblwres90 +%files -n libisccc140 %defattr(-,root,root) -%_libdir/liblwres.so.90* +%_libdir/libisccc.so.140* + +%files -n libisccfg140 +%defattr(-,root,root) +%_libdir/libisccfg.so.140* + +%files -n liblwres141 +%defattr(-,root,root) +%_libdir/liblwres.so.141* %files chrootenv %defattr(-,root,root) @@ -903,6 +925,7 @@ fi %dir %{_sysconfdir}/openldap/schema %attr(0444,root,root) %config %{_sysconfdir}/openldap/schema/dnszone.schema %attr(0444,root,root) %config %{_sysconfdir}/openldap/schema/dlz.schema +%{_bindir}/delv %{_bindir}/dig %{_bindir}/host %{_bindir}/nslookup @@ -928,9 +951,11 @@ fi %{_sbindir}/nsec3hash %{_sbindir}/rndc %{_sbindir}/rndc-confgen +%{_sbindir}/tsig-keygen %dir %doc %{_defaultdocdir}/bind %{_defaultdocdir}/bind/README.%{VENDOR} %{_mandir}/man1/arpaname.1.gz +%{_mandir}/man1/delv.1.gz %{_mandir}/man1/dig.1.gz %{_mandir}/man1/host.1.gz %{_mandir}/man1/isc-config.sh.1.gz @@ -943,6 +968,7 @@ fi %{_mandir}/man8/dnssec-coverage.8.gz %endif %{_mandir}/man8/dnssec-dsfromkey.8.gz +%{_mandir}/man8/dnssec-importkey.8.gz %{_mandir}/man8/dnssec-keyfromlabel.8.gz %{_mandir}/man8/dnssec-keygen.8.gz %{_mandir}/man8/dnssec-revoke.8.gz @@ -955,5 +981,6 @@ fi %{_mandir}/man8/nsec3hash.8.gz %{_mandir}/man8/rndc.8.gz %{_mandir}/man8/rndc-confgen.8.gz +%{_mandir}/man8/tsig-keygen.8.gz %changelog diff --git a/configure.in.diff b/configure.in.diff index baedcd2..a73cfab 100644 --- a/configure.in.diff +++ b/configure.in.diff @@ -2,9 +2,9 @@ Index: bind-9.9.4-P2/configure.in =================================================================== --- bind-9.9.4-P2.orig/configure.in 2013-12-20 01:28:28.000000000 +0100 +++ bind-9.9.4-P2/configure.in 2014-01-21 17:55:51.063395215 +0100 -@@ -3172,7 +3172,7 @@ +@@ -3839,7 +3839,7 @@ AC_SUBST(DOXYGEN) # empty). The variable VARIABLE will be substituted into output files. - # + # -AC_DEFUN(NOM_PATH_FILE, [ +AC_DEFUN([NOM_PATH_FILE], [ diff --git a/named-bootconf.diff b/named-bootconf.diff index e958144..fbb2ad9 100644 --- a/named-bootconf.diff +++ b/named-bootconf.diff @@ -1,7 +1,7 @@ Index: contrib/named-bootconf/named-bootconf.sh =================================================================== ---- contrib/named-bootconf/named-bootconf.sh.orig -+++ contrib/named-bootconf/named-bootconf.sh +--- contrib/scripts/named-bootconf.sh.orig ++++ contrib/scripts/named-bootconf.sh @@ -47,7 +47,8 @@ # POSSIBILITY OF SUCH DAMAGE. diff --git a/named.root b/named.root index 2fba31d..a060308 100644 --- a/named.root +++ b/named.root @@ -9,30 +9,32 @@ ; on server FTP.INTERNIC.NET ; -OR- RS.INTERNIC.NET ; -; last update: Jan 3, 2013 -; related version of root zone: 2013010300 +; last update: November 05, 2014 +; related version of root zone: 2014110501 ; ; formerly NS.INTERNIC.NET ; -. 3600000 IN NS A.ROOT-SERVERS.NET. +. 3600000 NS A.ROOT-SERVERS.NET. A.ROOT-SERVERS.NET. 3600000 A 198.41.0.4 -A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:BA3E::2:30 +A.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:ba3e::2:30 ; ; FORMERLY NS1.ISI.EDU ; . 3600000 NS B.ROOT-SERVERS.NET. B.ROOT-SERVERS.NET. 3600000 A 192.228.79.201 +B.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:84::b ; ; FORMERLY C.PSI.NET ; . 3600000 NS C.ROOT-SERVERS.NET. C.ROOT-SERVERS.NET. 3600000 A 192.33.4.12 +C.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2::c ; ; FORMERLY TERP.UMD.EDU ; . 3600000 NS D.ROOT-SERVERS.NET. D.ROOT-SERVERS.NET. 3600000 A 199.7.91.13 -D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2D::D +D.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2d::d ; ; FORMERLY NS.NASA.GOV ; @@ -43,7 +45,7 @@ E.ROOT-SERVERS.NET. 3600000 A 192.203.230.10 ; . 3600000 NS F.ROOT-SERVERS.NET. F.ROOT-SERVERS.NET. 3600000 A 192.5.5.241 -F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2F::F +F.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:2f::f ; ; FORMERLY NS.NIC.DDN.MIL ; @@ -54,25 +56,25 @@ G.ROOT-SERVERS.NET. 3600000 A 192.112.36.4 ; . 3600000 NS H.ROOT-SERVERS.NET. H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53 -H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803F:235 +H.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:1::803f:235 ; ; FORMERLY NIC.NORDU.NET ; . 3600000 NS I.ROOT-SERVERS.NET. I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17 -I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FE::53 +I.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fe::53 ; ; OPERATED BY VERISIGN, INC. ; . 3600000 NS J.ROOT-SERVERS.NET. J.ROOT-SERVERS.NET. 3600000 A 192.58.128.30 -J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:C27::2:30 +J.ROOT-SERVERS.NET. 3600000 AAAA 2001:503:c27::2:30 ; ; OPERATED BY RIPE NCC ; . 3600000 NS K.ROOT-SERVERS.NET. K.ROOT-SERVERS.NET. 3600000 A 193.0.14.129 -K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7FD::1 +K.ROOT-SERVERS.NET. 3600000 AAAA 2001:7fd::1 ; ; OPERATED BY ICANN ; @@ -84,5 +86,5 @@ L.ROOT-SERVERS.NET. 3600000 AAAA 2001:500:3::42 ; . 3600000 NS M.ROOT-SERVERS.NET. M.ROOT-SERVERS.NET. 3600000 A 202.12.27.33 -M.ROOT-SERVERS.NET. 3600000 AAAA 2001:DC3::35 -; End of File +M.ROOT-SERVERS.NET. 3600000 AAAA 2001:dc3::35 +; End of file diff --git a/pid-path.diff b/pid-path.diff deleted file mode 100644 index 4d55ad3..0000000 --- a/pid-path.diff +++ /dev/null @@ -1,29 +0,0 @@ -Index: bin/named/include/named/globals.h -=================================================================== ---- bin/named/include/named/globals.h.orig 2013-07-17 00:13:06.000000000 +0200 -+++ bin/named/include/named/globals.h 2013-08-05 14:14:28.152275375 +0200 -@@ -140,9 +140,9 @@ - "lwresd.pid"); - #else - EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR -- "/run/named.pid"); -+ "/run/named/named.pid"); - EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR -- "/run/lwresd.pid"); -+ "/run/named/lwresd.pid"); - #endif - - EXTERN const char * ns_g_username INIT(NULL); -Index: contrib/nanny/nanny.pl -=================================================================== ---- contrib/nanny/nanny.pl.orig 2013-07-17 00:13:06.000000000 +0200 -+++ contrib/nanny/nanny.pl 2013-08-05 14:14:28.153275387 +0200 -@@ -19,7 +19,7 @@ - - # A simple nanny to make sure named stays running. - --$pid_file_location = '/var/run/named.pid'; -+$pid_file_location = '/var/run/named/named.pid'; - $nameserver_location = 'localhost'; - $dig_program = 'dig'; - $named_program = 'named'; diff --git a/pie_compile.diff b/pie_compile.diff index 854a844..2b87888 100644 --- a/pie_compile.diff +++ b/pie_compile.diff @@ -49,7 +49,7 @@ Index: bin/dig/Makefile.in =================================================================== --- bin/dig/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 +++ bin/dig/Makefile.in 2013-08-06 12:08:19.492457714 +0200 -@@ -69,8 +69,12 @@ +@@ -69,8 +69,12 @@ HTMLPAGES = dig.html host.html nslookup. MANOBJS = ${MANPAGES} ${HTMLPAGES} @@ -61,12 +61,12 @@ Index: bin/dig/Makefile.in + dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS} export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \ - ${FINALBUILDCMD} + export LIBS0="${DNSLIBS}"; \ Index: bin/dnssec/Makefile.in =================================================================== --- bin/dnssec/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 +++ bin/dnssec/Makefile.in 2013-08-06 12:08:19.493457729 +0200 -@@ -64,8 +64,12 @@ +@@ -65,8 +65,12 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @@ -96,7 +96,7 @@ Index: bin/named/Makefile.in =================================================================== --- bin/named/Makefile.in.orig 2013-08-06 12:08:17.653432490 +0200 +++ bin/named/Makefile.in 2013-08-06 12:08:19.493457729 +0200 -@@ -115,8 +115,12 @@ +@@ -119,8 +119,12 @@ MANOBJS = ${MANPAGES} ${HTMLPAGES} @@ -158,8 +158,8 @@ Index: bin/tools/Makefile.in =================================================================== --- bin/tools/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 +++ bin/tools/Makefile.in 2013-08-06 12:08:19.493457729 +0200 -@@ -53,8 +53,12 @@ - genrandom.html isc-hmac-fixup.html +@@ -54,8 +54,12 @@ HTMLPAGES = arpaname.html named-journalp + nsec3hash.html genrandom.html isc-hmac-fixup.html MANOBJS = ${MANPAGES} ${HTMLPAGES} +EXT_CFLAGS = -fPIE -static @@ -169,8 +169,8 @@ Index: bin/tools/Makefile.in +LDFLAGS += -pie + arpaname@EXEEXT@: arpaname.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} - ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ arpaname.@O@ \ - ${ISCLIBS} ${LIBS} + ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \ + -o $@ arpaname.@O@ ${ISCLIBS} ${LIBS} Index: contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in =================================================================== --- contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 @@ -188,8 +188,8 @@ Index: contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in OBJS = idnconv.o util.o selectiveencode.o Index: contrib/zkt/Makefile.in =================================================================== ---- contrib/zkt/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 -+++ contrib/zkt/Makefile.in 2013-08-06 12:08:19.494457743 +0200 +--- contrib/zkt-1.1.2/Makefile.in.orig 2013-07-17 00:13:06.000000000 +0200 ++++ contrib/zkt-1.1.2/Makefile.in 2013-08-06 12:08:19.494457743 +0200 @@ -13,11 +13,11 @@ OPTIM = # -O3 -DNDEBUG diff --git a/rpz2+rl-9.9.5.patch b/rpz2+rl-9.9.5.patch deleted file mode 100644 index c6f3fa7..0000000 --- a/rpz2+rl-9.9.5.patch +++ /dev/null @@ -1,7601 +0,0 @@ -diff -r -u bin/named/query.c-orig bin/named/query.c ---- bin/named/query.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/named/query.c 2004-01-01 00:00:00.000000000 +0000 -@@ -879,11 +879,11 @@ - static void - rpz_log_rewrite(ns_client_t *client, isc_boolean_t disabled, - dns_rpz_policy_t policy, dns_rpz_type_t type, -- dns_zone_t *zone, dns_name_t *rpz_qname) -+ dns_zone_t *p_zone, dns_name_t *p_name) - { - isc_stats_t *zonestats; - char qname_buf[DNS_NAME_FORMATSIZE]; -- char rpz_qname_buf[DNS_NAME_FORMATSIZE]; -+ char p_name_buf[DNS_NAME_FORMATSIZE]; - - /* - * Count enabled rewrites in the global counter. -@@ -893,8 +893,8 @@ - isc_stats_increment(ns_g_server->nsstats, - dns_nsstatscounter_rpz_rewrites); - } -- if (zone != NULL) { -- zonestats = dns_zone_getrequeststats(zone); -+ if (p_zone != NULL) { -+ zonestats = dns_zone_getrequeststats(p_zone); - if (zonestats != NULL) - isc_stats_increment(zonestats, - dns_nsstatscounter_rpz_rewrites); -@@ -904,68 +904,73 @@ - return; - - dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf)); -- dns_name_format(rpz_qname, rpz_qname_buf, sizeof(rpz_qname_buf)); -+ dns_name_format(p_name, p_name_buf, sizeof(p_name_buf)); - - ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY, - DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s", - disabled ? "disabled " : "", - dns_rpz_type2str(type), dns_rpz_policy2str(policy), -- qname_buf, rpz_qname_buf); -+ qname_buf, p_name_buf); - } - - static void --rpz_log_fail(ns_client_t *client, int level, -- dns_rpz_type_t rpz_type, dns_name_t *name, -- const char *str, isc_result_t result) -+rpz_log_fail(ns_client_t *client, int level, dns_name_t *p_name, -+ dns_rpz_type_t rpz_type, const char *str, isc_result_t result) - { -- char namebuf1[DNS_NAME_FORMATSIZE]; -- char namebuf2[DNS_NAME_FORMATSIZE]; -+ char qnamebuf[DNS_NAME_FORMATSIZE]; -+ char p_namebuf[DNS_NAME_FORMATSIZE]; -+ const char *failed; - - if (!isc_log_wouldlog(ns_g_lctx, level)) - return; - - /* -- * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". -+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed" for problems. - */ -- dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1)); -- dns_name_format(name, namebuf2, sizeof(namebuf2)); -+ if (level <= DNS_RPZ_DEBUG_LEVEL1) -+ failed = "failed: "; -+ else -+ failed = ": "; -+ dns_name_format(client->query.qname, qnamebuf, sizeof(qnamebuf)); -+ dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); - ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS, - NS_LOGMODULE_QUERY, level, -- "rpz %s rewrite %s via %s %sfailed: %s", -+ "rpz %s rewrite %s via %s%s%s%s", - dns_rpz_type2str(rpz_type), -- namebuf1, namebuf2, str, isc_result_totext(result)); -+ qnamebuf, p_namebuf, -+ str, failed, isc_result_totext(result)); - } - - /* - * Get a policy rewrite zone database. - */ - static isc_result_t --rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, dns_name_t *rpz_qname, -+rpz_getdb(ns_client_t *client, dns_name_t *p_name, dns_rpz_type_t rpz_type, - dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp) - { -- char namebuf1[DNS_NAME_FORMATSIZE]; -- char namebuf2[DNS_NAME_FORMATSIZE]; -+ char qnamebuf[DNS_NAME_FORMATSIZE]; -+ char p_namebuf[DNS_NAME_FORMATSIZE]; - dns_dbversion_t *rpz_version = NULL; - isc_result_t result; - -- result = query_getzonedb(client, rpz_qname, dns_rdatatype_any, -+ result = query_getzonedb(client, p_name, dns_rdatatype_any, - DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version); - if (result == ISC_R_SUCCESS) { - if (isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) { -- dns_name_format(client->query.qname, namebuf1, -- sizeof(namebuf1)); -- dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2)); -+ dns_name_format(client->query.qname, qnamebuf, -+ sizeof(qnamebuf)); -+ dns_name_format(p_name, p_namebuf, sizeof(p_namebuf)); - ns_client_log(client, DNS_LOGCATEGORY_RPZ, - NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2, - "try rpz %s rewrite %s via %s", - dns_rpz_type2str(rpz_type), -- namebuf1, namebuf2); -+ qnamebuf, p_namebuf); - } - *versionp = rpz_version; - return (ISC_R_SUCCESS); - } -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname, -- "query_getzonedb() ", result); -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, -+ " query_getzonedb()", result); - return (result); - } - -@@ -3913,7 +3918,7 @@ - dns_rdataset_disassociate(*rdatasetp); - } - --static void -+static inline void - rpz_match_clear(dns_rpz_st_t *st) - { - rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset); -@@ -3921,16 +3926,16 @@ - } - - static inline isc_result_t --rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp, -- dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp) -+rpz_ready(ns_client_t *client, dns_rdataset_t **rdatasetp) - { - REQUIRE(rdatasetp != NULL); - -- rpz_clean(zonep, dbp, nodep, rdatasetp); - if (*rdatasetp == NULL) { - *rdatasetp = query_newrdataset(client); - if (*rdatasetp == NULL) - return (DNS_R_SERVFAIL); -+ } else if (dns_rdataset_isassociated(*rdatasetp)) { -+ dns_rdataset_disassociate(*rdatasetp); - } - return (ISC_R_SUCCESS); - } -@@ -3959,13 +3964,83 @@ - st->m.policy = DNS_RPZ_POLICY_MISS; - } - -+static dns_rpz_zbits_t -+rpz_get_zbits(ns_client_t *client, -+ dns_rdatatype_t ip_type, dns_rpz_type_t rpz_type) -+{ -+ dns_rpz_zones_t *rpzs; -+ dns_rpz_st_t *st; -+ dns_rpz_zbits_t zbits; -+ -+ rpzs = client->view->rpzs; -+ -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ zbits = rpzs->have.client_ip; -+ break; -+ case DNS_RPZ_TYPE_QNAME: -+ zbits = rpzs->have.qname; -+ break; -+ case DNS_RPZ_TYPE_IP: -+ if (ip_type == dns_rdatatype_a) { -+ zbits = rpzs->have.ipv4; -+ } else if (ip_type == dns_rdatatype_aaaa) { -+ zbits = rpzs->have.ipv6; -+ } else { -+ zbits = rpzs->have.ip; -+ } -+ break; -+ case DNS_RPZ_TYPE_NSDNAME: -+ zbits = rpzs->have.nsdname; -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ if (ip_type == dns_rdatatype_a) { -+ zbits = rpzs->have.nsipv4; -+ } else if (ip_type == dns_rdatatype_aaaa) { -+ zbits = rpzs->have.nsipv6; -+ } else { -+ zbits = rpzs->have.nsip; -+ } -+ break; -+ default: -+ INSIST(0); -+ break; -+ } -+ -+ st = client->query.rpz_st; -+ -+ /* -+ * Choose -+ * the earliest configured policy zone (rpz->num) -+ * QNAME over IP over NSDNAME over NSIP (rpz_type) -+ * the smallest name, -+ * the longest IP address prefix, -+ * the lexically smallest address. -+ */ -+ if (st->m.policy != DNS_RPZ_POLICY_MISS) { -+ if (st->m.type >= rpz_type) { -+ zbits &= DNS_RPZ_ZMASK(st->m.rpz->num); -+ } else{ -+ zbits &= DNS_RPZ_ZMASK(st->m.rpz->num) >> 1; -+ } -+ } -+ -+ /* -+ * If the client wants recursion, allow only compatible policies. -+ */ -+ if (!RECURSIONOK(client)) -+ zbits &= rpzs->p.no_rd_ok; -+ -+ return (zbits); -+} -+ - /* -- * Get NS, A, or AAAA rrset for response policy zone checks. -+ * Get an NS, A, or AAAA rrset related to the response for the client -+ * to check the contents of that rrset for hits by eligible policy zones. - */ - static isc_result_t --rpz_rrset_find(ns_client_t *client, dns_rpz_type_t rpz_type, -- dns_name_t *name, dns_rdatatype_t type, -- dns_db_t **dbp, dns_dbversion_t *version, -+rpz_rrset_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type, -+ dns_rpz_type_t rpz_type, dns_db_t **dbp, dns_dbversion_t *version, - dns_rdataset_t **rdatasetp, isc_boolean_t resuming) - { - dns_rpz_st_t *st; -@@ -3977,15 +4052,13 @@ - dns_clientinfomethods_t cm; - dns_clientinfo_t ci; - -- dns_clientinfomethods_init(&cm, ns_client_sourceip); -- dns_clientinfo_init(&ci, client); -- - st = client->query.rpz_st; - if ((st->state & DNS_RPZ_RECURSING) != 0) { - INSIST(st->r.r_type == type); - INSIST(dns_name_equal(name, st->r_name)); - INSIST(*rdatasetp == NULL || - !dns_rdataset_isassociated(*rdatasetp)); -+ INSIST(*dbp == NULL); - st->state &= ~DNS_RPZ_RECURSING; - *dbp = st->r.db; - st->r.db = NULL; -@@ -3995,16 +4068,15 @@ - st->r.r_rdataset = NULL; - result = st->r.r_result; - if (result == DNS_R_DELEGATION) { -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, -- rpz_type, name, -- "rpz_rrset_find(1) ", result); -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, -+ rpz_type, " rpz_rrset_find(1)", result); - st->m.policy = DNS_RPZ_POLICY_ERROR; - result = DNS_R_SERVFAIL; - } - return (result); - } - -- result = rpz_ready(client, NULL, NULL, NULL, rdatasetp); -+ result = rpz_ready(client, rdatasetp); - if (result != ISC_R_SUCCESS) { - st->m.policy = DNS_RPZ_POLICY_ERROR; - return (result); -@@ -4019,9 +4091,8 @@ - result = query_getdb(client, name, type, 0, &zone, dbp, - &version, &is_zone); - if (result != ISC_R_SUCCESS) { -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, -- rpz_type, name, -- "rpz_rrset_find(2) ", result); -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, -+ rpz_type, " rpz_rrset_find(2)", result); - st->m.policy = DNS_RPZ_POLICY_ERROR; - if (zone != NULL) - dns_zone_detach(&zone); -@@ -4034,6 +4105,8 @@ - node = NULL; - dns_fixedname_init(&fixed); - found = dns_fixedname_name(&fixed); -+ dns_clientinfomethods_init(&cm, ns_client_sourceip); -+ dns_clientinfo_init(&ci, client); - result = dns_db_findext(*dbp, name, version, type, DNS_DBFIND_GLUEOK, - client->now, &node, found, - &cm, &ci, *rdatasetp, NULL); -@@ -4072,177 +4145,97 @@ - } - - /* -- * Check the IP address in an A or AAAA rdataset against -- * the IP or NSIP response policy rules of a view. -+ * Compute a policy owner name, p_name, in a policy zone given the needed -+ * policy type and the trigger name. - */ - static isc_result_t --rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset, -- dns_rpz_type_t rpz_type) -+rpz_get_p_name(ns_client_t *client, dns_name_t *p_name, -+ dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -+ dns_name_t *trig_name) - { -- dns_rpz_st_t *st; -- dns_dbversion_t *version; -- dns_zone_t *zone; -- dns_db_t *db; -- dns_rpz_zone_t *rpz; -+ dns_offsets_t prefix_offsets; -+ dns_name_t prefix, *suffix; -+ unsigned int first, labels; - isc_result_t result; - -- st = client->query.rpz_st; -- if (st->m.rdataset == NULL) { -- st->m.rdataset = query_newrdataset(client); -- if (st->m.rdataset == NULL) -- return (DNS_R_SERVFAIL); -- } -- zone = NULL; -- db = NULL; -- for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); -- rpz != NULL; -- rpz = ISC_LIST_NEXT(rpz, link)) { -- if (!RECURSIONOK(client) && rpz->recursive_only) -- continue; -- -- /* -- * Do not check policy zones that cannot replace a policy -- * already known to match. -- */ -- if (st->m.policy != DNS_RPZ_POLICY_MISS) { -- if (st->m.rpz->num < rpz->num) -- break; -- if (st->m.rpz->num == rpz->num && -- st->m.type < rpz_type) -- continue; -- } -- -- /* -- * Find the database for this policy zone to get its radix tree. -- */ -- version = NULL; -- result = rpz_getdb(client, rpz_type, &rpz->origin, -- &zone, &db, &version); -- if (result != ISC_R_SUCCESS) { -- rpz_clean(&zone, &db, NULL, NULL); -- continue; -- } -- /* -- * Look for a better (e.g. longer prefix) hit for an IP address -- * in this rdataset in this radix tree than than the previous -- * hit, if any. Note the domain name and quality of the -- * best hit. -- */ -- dns_db_rpz_findips(rpz, rpz_type, zone, db, version, -- rdataset, st, client->query.rpz_st->qname); -- rpz_clean(&zone, &db, NULL, NULL); -- } -- return (ISC_R_SUCCESS); --} -- --/* -- * Look for an A or AAAA rdataset -- * and check for IP or NSIP rewrite policy rules. -- */ --static isc_result_t --rpz_rewrite_rrset(ns_client_t *client, dns_rpz_type_t rpz_type, -- dns_rdatatype_t type, dns_name_t *name, -- dns_db_t **dbp, dns_dbversion_t *version, -- dns_rdataset_t **rdatasetp, isc_boolean_t resuming) --{ -- isc_result_t result; -- -- result = rpz_rrset_find(client, rpz_type, name, type, dbp, version, -- rdatasetp, resuming); -- switch (result) { -- case ISC_R_SUCCESS: -- case DNS_R_GLUE: -- case DNS_R_ZONECUT: -- result = rpz_rewrite_ip(client, *rdatasetp, rpz_type); -+ /* -+ * The policy owner name consists of a suffix depending on the type -+ * and policy zone and a prefix that is the longest possible string -+ * from the trigger name that keesp the resulting policy owner name -+ * from being too long. -+ */ -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ suffix = &rpz->client_ip; - break; -- case DNS_R_EMPTYNAME: -- case DNS_R_EMPTYWILD: -- case DNS_R_NXDOMAIN: -- case DNS_R_NCACHENXDOMAIN: -- case DNS_R_NXRRSET: -- case DNS_R_NCACHENXRRSET: -- case ISC_R_NOTFOUND: -- result = ISC_R_SUCCESS; -+ case DNS_RPZ_TYPE_QNAME: -+ suffix = &rpz->origin; - break; -- case DNS_R_DELEGATION: -- case DNS_R_DUPLICATE: -- case DNS_R_DROP: -+ case DNS_RPZ_TYPE_IP: -+ suffix = &rpz->ip; - break; -- case DNS_R_CNAME: -- case DNS_R_DNAME: -- rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, rpz_type, -- name, "NS address rewrite rrset ", result); -- result = ISC_R_SUCCESS; -+ case DNS_RPZ_TYPE_NSDNAME: -+ suffix = &rpz->nsdname; - break; -- default: -- if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { -- client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, -- name, "NS address rewrite rrset ", result); -- } -+ case DNS_RPZ_TYPE_NSIP: -+ suffix = &rpz->nsip; - break; -+ default: -+ INSIST(0); - } -- return (result); --} -- --/* -- * Look for both A and AAAA rdatasets -- * and check for IP or NSIP rewrite policy rules. -- * Look only for addresses that will be in the ANSWER section -- * when checking for IP rules. -- */ --static isc_result_t --rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type, -- dns_name_t *name, dns_rdatatype_t type, -- dns_rdataset_t **rdatasetp, isc_boolean_t resuming) --{ -- dns_rpz_st_t *st; -- dns_dbversion_t *version; -- dns_db_t *ipdb; -- isc_result_t result; - -- st = client->query.rpz_st; -- version = NULL; -- ipdb = NULL; -- if ((st->state & DNS_RPZ_DONE_IPv4) == 0 && -- ((rpz_type == DNS_RPZ_TYPE_NSIP) ? -- (st->state & DNS_RPZ_HAVE_NSIPv4) : -- (st->state & DNS_RPZ_HAVE_IP)) != 0 && -- (type == dns_rdatatype_any || type == dns_rdatatype_a)) { -- result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_a, -- name, &ipdb, version, rdatasetp, -- resuming); -+ /* -+ * Start with relative version of the full trigger name, -+ * and trim enough allow the addition of the suffix. -+ */ -+ dns_name_init(&prefix, prefix_offsets); -+ labels = dns_name_countlabels(trig_name); -+ first = 0; -+ for (;;) { -+ dns_name_getlabelsequence(trig_name, first, labels-first-1, -+ &prefix); -+ result = dns_name_concatenate(&prefix, suffix, p_name, NULL); - if (result == ISC_R_SUCCESS) -- st->state |= DNS_RPZ_DONE_IPv4; -- } else { -- result = ISC_R_SUCCESS; -- } -- if (result == ISC_R_SUCCESS && -- ((rpz_type == DNS_RPZ_TYPE_NSIP) ? -- (st->state & DNS_RPZ_HAVE_NSIPv6) : -- (st->state & DNS_RPZ_HAVE_IP)) != 0 && -- (type == dns_rdatatype_any || type == dns_rdatatype_aaaa)) { -- result = rpz_rewrite_rrset(client, rpz_type, dns_rdatatype_aaaa, -- name, &ipdb, version, rdatasetp, -- resuming); -+ return (ISC_R_SUCCESS); -+ INSIST(result == DNS_R_NAMETOOLONG); -+ /* -+ * Trim the trigger name until the combination is not too long. -+ */ -+ if (labels-first < 2) { -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, suffix, -+ rpz_type, " concatentate()", result); -+ return (ISC_R_FAILURE); -+ } -+ /* -+ * Complain once about trimming the trigger name. -+ */ -+ if (first == 0) { -+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, suffix, -+ rpz_type, " concatentate()", result); -+ } -+ ++first; - } -- if (ipdb != NULL) -- dns_db_detach(&ipdb); -- return (result); - } - - /* -- * Get the rrset from a response policy zone. -+ * Look in policy zone rpz for a policy of rpz_type by p_name. -+ * The self-name (usually the client qname or an NS name) is compared with -+ * the target of a CNAME policy for the old style passthru encoding. -+ * If found, the policy is recorded in *zonep, *dbp, *versionp, *nodep, -+ * *rdatasetp, and *policyp. -+ * The target DNS type, qtype, chooses the best rdataset for *rdatasetp. -+ * The caller must decide if the found policy is most suitable, including -+ * better than a previously found policy. -+ * If it is best, the caller records it in client->query.rpz_st->m. - */ - static isc_result_t --rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef, -- dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -- dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, -- dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, -- dns_rpz_policy_t *policyp) -+rpz_find_p(ns_client_t *client, dns_name_t *self_name, dns_rdatatype_t qtype, -+ dns_name_t *p_name, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -+ dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp, -+ dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, -+ dns_rpz_policy_t *policyp) - { -- dns_rpz_policy_t policy; -- dns_fixedname_t fixed; -+ dns_fixedname_t foundf; - dns_name_t *found; - isc_result_t result; - dns_clientinfomethods_t cm; -@@ -4250,31 +4243,28 @@ - - REQUIRE(nodep != NULL); - -- dns_clientinfomethods_init(&cm, ns_client_sourceip); -- dns_clientinfo_init(&ci, client); -- -- result = rpz_ready(client, zonep, dbp, nodep, rdatasetp); -- if (result != ISC_R_SUCCESS) { -- *policyp = DNS_RPZ_POLICY_ERROR; -- return (result); -- } -- - /* -- * Try to get either a CNAME or the type of record demanded by the -+ * Try to find either a CNAME or the type of record demanded by the - * request from the policy zone. - */ -+ rpz_clean(zonep, dbp, nodep, rdatasetp); -+ result = rpz_ready(client, rdatasetp); -+ if (result != ISC_R_SUCCESS) -+ return (DNS_R_SERVFAIL); - *versionp = NULL; -- result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, versionp); -- if (result != ISC_R_SUCCESS) { -- *policyp = DNS_RPZ_POLICY_MISS; -+ result = rpz_getdb(client, p_name, rpz_type, zonep, dbp, versionp); -+ if (result != ISC_R_SUCCESS) - return (DNS_R_NXDOMAIN); -- } -- -- dns_fixedname_init(&fixed); -- found = dns_fixedname_name(&fixed); -- result = dns_db_findext(*dbp, qnamef, *versionp, dns_rdatatype_any, 0, -+ dns_fixedname_init(&foundf); -+ found = dns_fixedname_name(&foundf); -+ dns_clientinfomethods_init(&cm, ns_client_sourceip); -+ dns_clientinfo_init(&ci, client); -+ result = dns_db_findext(*dbp, p_name, *versionp, dns_rdatatype_any, 0, - client->now, nodep, found, &cm, &ci, - *rdatasetp, NULL); -+ /* -+ * Choose the best rdataset if we found something. -+ */ - if (result == ISC_R_SUCCESS) { - dns_rdatasetiter_t *rdsiter; - -@@ -4282,10 +4272,8 @@ - result = dns_db_allrdatasets(*dbp, *nodep, *versionp, 0, - &rdsiter); - if (result != ISC_R_SUCCESS) { -- dns_db_detachnode(*dbp, nodep); -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, -- qnamef, "allrdatasets() ", result); -- *policyp = DNS_RPZ_POLICY_ERROR; -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, -+ rpz_type, " allrdatasets()", result); - return (DNS_R_SERVFAIL); - } - for (result = dns_rdatasetiter_first(rdsiter); -@@ -4301,9 +4289,8 @@ - if (result != ISC_R_SUCCESS) { - if (result != ISC_R_NOMORE) { - rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, -- rpz_type, qnamef, "rdatasetiter ", -- result); -- *policyp = DNS_RPZ_POLICY_ERROR; -+ p_name, rpz_type, -+ " rdatasetiter", result); - return (DNS_R_SERVFAIL); - } - /* -@@ -4318,7 +4305,7 @@ - qtype == dns_rdatatype_sig) - result = DNS_R_NXRRSET; - else -- result = dns_db_findext(*dbp, qnamef, *versionp, -+ result = dns_db_findext(*dbp, p_name, *versionp, - qtype, 0, client->now, - nodep, found, &cm, &ci, - *rdatasetp, NULL); -@@ -4327,162 +4314,476 @@ - switch (result) { - case ISC_R_SUCCESS: - if ((*rdatasetp)->type != dns_rdatatype_cname) { -- policy = DNS_RPZ_POLICY_RECORD; -+ *policyp = DNS_RPZ_POLICY_RECORD; - } else { -- policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname); -- if ((policy == DNS_RPZ_POLICY_RECORD || -- policy == DNS_RPZ_POLICY_WILDCNAME) && -+ *policyp = dns_rpz_decode_cname(rpz, *rdatasetp, -+ self_name); -+ if ((*policyp == DNS_RPZ_POLICY_RECORD || -+ *policyp == DNS_RPZ_POLICY_WILDCNAME) && - qtype != dns_rdatatype_cname && - qtype != dns_rdatatype_any) -- result = DNS_R_CNAME; -+ return (DNS_R_CNAME); - } -- break; -+ return (ISC_R_SUCCESS); - case DNS_R_NXRRSET: -- policy = DNS_RPZ_POLICY_NODATA; -- break; -+ *policyp = DNS_RPZ_POLICY_NODATA; -+ return (result); - case DNS_R_DNAME: - /* - * DNAME policy RRs have very few if any uses that are not -- * better served with simple wildcards. Making the work would -+ * better served with simple wildcards. Making them work would - * require complications to get the number of labels matched - * in the name or the found name to the main DNS_R_DNAME case -- * in query_find(). -- */ -- dns_rdataset_disassociate(*rdatasetp); -- dns_db_detachnode(*dbp, nodep); -- /* -- * Fall through to treat it as a miss. -+ * in query_find(). The domain also does not appear in the -+ * summary database at the right level, so this happens only -+ * with a single policy zone when we have no summary database. -+ * Treat it as a miss. - */ - case DNS_R_NXDOMAIN: - case DNS_R_EMPTYNAME: -- /* -- * If we don't get a qname hit, -- * see if it is worth looking for other types. -- */ -- (void)dns_db_rpz_enabled(*dbp, client->query.rpz_st); -- dns_db_detach(dbp); -- dns_zone_detach(zonep); -- result = DNS_R_NXDOMAIN; -- policy = DNS_RPZ_POLICY_MISS; -- break; -+ return (DNS_R_NXDOMAIN); - default: -- dns_db_detach(dbp); -- dns_zone_detach(zonep); -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef, -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, p_name, rpz_type, - "", result); - return (DNS_R_SERVFAIL); - } -+} - -- *policyp = policy; -- return (result); -+static void -+rpz_save_p(dns_rpz_st_t *st, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -+ dns_rpz_policy_t policy, dns_name_t *p_name, dns_rpz_prefix_t prefix, -+ isc_result_t result, dns_zone_t **zonep, dns_db_t **dbp, -+ dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp, -+ dns_dbversion_t *version) -+{ -+ dns_rdataset_t *trdataset; -+ -+ rpz_match_clear(st); -+ st->m.rpz = rpz; -+ st->m.type = rpz_type; -+ st->m.policy = policy; -+ dns_name_copy(p_name, st->p_name, NULL); -+ st->m.prefix = prefix; -+ st->m.result = result; -+ st->m.zone = *zonep; -+ *zonep = NULL; -+ st->m.db = *dbp; -+ *dbp = NULL; -+ st->m.node = *nodep; -+ *nodep = NULL; -+ if (*rdatasetp != NULL && dns_rdataset_isassociated(*rdatasetp)) { -+ /* -+ * Save the replacement rdataset from the policy -+ * and make the previous replacement rdataset scratch. -+ */ -+ trdataset = st->m.rdataset; -+ st->m.rdataset = *rdatasetp; -+ *rdatasetp = trdataset; -+ st->m.ttl = ISC_MIN(st->m.rdataset->ttl, rpz->max_policy_ttl); -+ } else { -+ st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, rpz->max_policy_ttl); -+ } -+ st->m.version = version; - } - - /* -- * Build and look for a QNAME or NSDNAME owner name in a response policy zone. -+ * Check this address in every eligible policy zone. - */ - static isc_result_t --rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname, -- dns_rpz_type_t rpz_type, dns_rdataset_t **rdatasetp) -+rpz_rewrite_ip(ns_client_t *client, const isc_netaddr_t *netaddr, -+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t zbits, dns_rdataset_t **p_rdatasetp) - { -+ dns_rpz_zones_t *rpzs; - dns_rpz_st_t *st; - dns_rpz_zone_t *rpz; -- dns_fixedname_t prefixf, rpz_qnamef; -- dns_name_t *prefix, *suffix, *rpz_qname; -- dns_zone_t *zone; -- dns_db_t *db; -- dns_dbversion_t *version; -- dns_dbnode_t *node; -+ dns_rpz_prefix_t prefix; -+ dns_rpz_num_t rpz_num; -+ dns_fixedname_t ip_namef, p_namef; -+ dns_name_t *ip_name, *p_name; -+ dns_zone_t *p_zone; -+ dns_db_t *p_db; -+ dns_dbversion_t *p_version; -+ dns_dbnode_t *p_node; - dns_rpz_policy_t policy; -- unsigned int labels; - isc_result_t result; - -- st = client->query.rpz_st; -- zone = NULL; -- db = NULL; -- node = NULL; -+ dns_fixedname_init(&ip_namef); -+ ip_name = dns_fixedname_name(&ip_namef); - -- for (rpz = ISC_LIST_HEAD(client->view->rpz_zones); -- rpz != NULL; -- rpz = ISC_LIST_NEXT(rpz, link)) { -- if (!RECURSIONOK(client) && rpz->recursive_only) -- continue; -+ p_zone = NULL; -+ p_db = NULL; -+ p_node = NULL; -+ -+ rpzs = client->view->rpzs; -+ st = client->query.rpz_st; -+ while (zbits != 0) { -+ rpz_num = dns_rpz_find_ip(rpzs, rpz_type, zbits, netaddr, -+ ip_name, &prefix); -+ if (rpz_num == DNS_RPZ_INVALID_NUM) -+ break; -+ zbits &= (DNS_RPZ_ZMASK(rpz_num) >> 1); - - /* -- * Do not check policy zones that cannot replace a policy -- * already known to match. -+ * Do not try applying policy zones that cannot replace a -+ * previously found policy zone. -+ * Stop looking if the next best choice cannot -+ * replace what we already have. - */ -+ rpz = rpzs->zones[rpz_num]; - if (st->m.policy != DNS_RPZ_POLICY_MISS) { - if (st->m.rpz->num < rpz->num) - break; - if (st->m.rpz->num == rpz->num && -- st->m.type < rpz_type) -- continue; -+ (st->m.type < rpz_type || -+ st->m.prefix > prefix)) -+ break; - } -+ - /* -- * Construct the policy's owner name. -+ * Get the policy for a prefix at least as long -+ * as the prefix of the entry we had before. - */ -- dns_fixedname_init(&prefixf); -- prefix = dns_fixedname_name(&prefixf); -- dns_name_split(qname, 1, prefix, NULL); -- if (rpz_type == DNS_RPZ_TYPE_NSDNAME) -- suffix = &rpz->nsdname; -- else -- suffix = &rpz->origin; -- dns_fixedname_init(&rpz_qnamef); -- rpz_qname = dns_fixedname_name(&rpz_qnamef); -- for (;;) { -- result = dns_name_concatenate(prefix, suffix, -- rpz_qname, NULL); -- if (result == ISC_R_SUCCESS) -- break; -- INSIST(result == DNS_R_NAMETOOLONG); -+ dns_fixedname_init(&p_namef); -+ p_name = dns_fixedname_name(&p_namef); -+ result = rpz_get_p_name(client, p_name, rpz, rpz_type, ip_name); -+ if (result != ISC_R_SUCCESS) -+ continue; -+ result = rpz_find_p(client, ip_name, qtype, -+ p_name, rpz, rpz_type, -+ &p_zone, &p_db, &p_version, &p_node, -+ p_rdatasetp, &policy); -+ switch (result) { -+ case DNS_R_NXDOMAIN: - /* -- * Trim the name until it is not too long. -+ * Continue after a policy record that is missing -+ * contrary to the summary data. The summary -+ * data can out of date during races with and among -+ * policy zone updates. - */ -- labels = dns_name_countlabels(prefix); -- if (labels < 2) { -- rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, -- rpz_type, suffix, -- "concatentate() ", result); -- return (ISC_R_SUCCESS); -- } -- if (labels+1 == dns_name_countlabels(qname)) { -- rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, -- rpz_type, suffix, -- "concatentate() ", result); -+ continue; -+ case DNS_R_SERVFAIL: -+ rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); -+ st->m.policy = DNS_RPZ_POLICY_ERROR; -+ return (DNS_R_SERVFAIL); -+ default: -+ /* -+ * Forget this policy if it is not preferable -+ * to the previously found policy. -+ * If this policy is not good, then stop looking -+ * because none of the later policy zones would work. -+ * -+ * With more than one applicable policy, prefer -+ * the earliest configured policy, -+ * client-IP over QNAME over IP over NSDNAME over NSIP, -+ * the longest prefix -+ * the lexically smallest address. -+ * dns_rpz_find_ip() ensures st->m.rpz->num >= rpz->num. -+ * We can compare new and current p_name because -+ * both are of the same type and in the same zone. -+ * The tests above eliminate other reasons to -+ * reject this policy. If this policy can't work, -+ * then neither can later zones. -+ */ -+ if (st->m.policy != DNS_RPZ_POLICY_MISS && -+ rpz->num == st->m.rpz->num && -+ (st->m.type == rpz_type && -+ st->m.prefix == prefix && -+ 0 > dns_name_rdatacompare(st->p_name, p_name))) -+ break; -+ -+ /* -+ * Stop checking after saving an enabled hit in this -+ * policy zone. The radix tree in the policy zone -+ * ensures that we found the longest match. -+ */ -+ if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { -+ rpz_save_p(st, rpz, rpz_type, -+ policy, p_name, prefix, result, -+ &p_zone, &p_db, &p_node, -+ p_rdatasetp, p_version); -+ break; - } -- dns_name_split(prefix, labels - 1, NULL, prefix); -+ -+ /* -+ * Log DNS_RPZ_POLICY_DISABLED zones -+ * and try the next eligible policy zone. -+ */ -+ rpz_log_rewrite(client, ISC_TRUE, policy, rpz_type, -+ p_zone, p_name); -+ } -+ } -+ -+ rpz_clean(&p_zone, &p_db, &p_node, p_rdatasetp); -+ return (ISC_R_SUCCESS); -+} -+ -+/* -+ * Check the IP addresses in the A or AAAA rrsets for name against -+ * all eligible rpz_type (IP or NSIP) response policy rewrite rules. -+ */ -+static isc_result_t -+rpz_rewrite_ip_rrset(ns_client_t *client, -+ dns_name_t *name, dns_rdatatype_t qtype, -+ dns_rpz_type_t rpz_type, dns_rdatatype_t ip_type, -+ dns_db_t **ip_dbp, dns_dbversion_t *ip_version, -+ dns_rdataset_t **ip_rdatasetp, -+ dns_rdataset_t **p_rdatasetp, isc_boolean_t resuming) -+{ -+ dns_rpz_zbits_t zbits; -+ isc_netaddr_t netaddr; -+ struct in_addr ina; -+ struct in6_addr in6a; -+ isc_result_t result; -+ -+ zbits = rpz_get_zbits(client, ip_type, rpz_type); -+ if (zbits == 0) -+ return (ISC_R_SUCCESS); -+ -+ /* -+ * Get the A or AAAA rdataset. -+ */ -+ result = rpz_rrset_find(client, name, ip_type, rpz_type, ip_dbp, -+ ip_version, ip_rdatasetp, resuming); -+ switch (result) { -+ case ISC_R_SUCCESS: -+ case DNS_R_GLUE: -+ case DNS_R_ZONECUT: -+ break; -+ case DNS_R_EMPTYNAME: -+ case DNS_R_EMPTYWILD: -+ case DNS_R_NXDOMAIN: -+ case DNS_R_NCACHENXDOMAIN: -+ case DNS_R_NXRRSET: -+ case DNS_R_NCACHENXRRSET: -+ case ISC_R_NOTFOUND: -+ return (ISC_R_SUCCESS); -+ case DNS_R_DELEGATION: -+ case DNS_R_DUPLICATE: -+ case DNS_R_DROP: -+ return (result); -+ case DNS_R_CNAME: -+ case DNS_R_DNAME: -+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, name, rpz_type, -+ " NS address rewrite rrset", result); -+ return (ISC_R_SUCCESS); -+ default: -+ if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { -+ client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR; -+ rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, name, -+ rpz_type, " NS address rewrite rrset", -+ result); -+ } -+ return (DNS_R_SERVFAIL); -+ } -+ -+ /* -+ * Check all of the IP addresses in the rdataset. -+ */ -+ for (result = dns_rdataset_first(*ip_rdatasetp); -+ result == ISC_R_SUCCESS; -+ result = dns_rdataset_next(*ip_rdatasetp)) { -+ -+ dns_rdata_t rdata = DNS_RDATA_INIT; -+ dns_rdataset_current(*ip_rdatasetp, &rdata); -+ switch (rdata.type) { -+ case dns_rdatatype_a: -+ INSIST(rdata.length == 4); -+ memcpy(&ina.s_addr, rdata.data, 4); -+ isc_netaddr_fromin(&netaddr, &ina); -+ break; -+ case dns_rdatatype_aaaa: -+ INSIST(rdata.length == 16); -+ memcpy(in6a.s6_addr, rdata.data, 16); -+ isc_netaddr_fromin6(&netaddr, &in6a); -+ break; -+ default: -+ continue; -+ } -+ -+ result = rpz_rewrite_ip(client, &netaddr, qtype, rpz_type, -+ zbits, p_rdatasetp); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ } -+ -+ return (ISC_R_SUCCESS); -+} -+ -+/* -+ * Look for IP addresses in A and AAAA rdatasets -+ * that trigger all eligible IP or NSIP policy rules. -+ */ -+static isc_result_t -+rpz_rewrite_ip_rrsets(ns_client_t *client, dns_name_t *name, -+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, -+ dns_rdataset_t **ip_rdatasetp, isc_boolean_t resuming) -+{ -+ dns_rpz_st_t *st; -+ dns_dbversion_t *ip_version; -+ dns_db_t *ip_db; -+ dns_rdataset_t *p_rdataset; -+ isc_result_t result; -+ -+ st = client->query.rpz_st; -+ ip_version = NULL; -+ ip_db = NULL; -+ p_rdataset = NULL; -+ if ((st->state & DNS_RPZ_DONE_IPv4) == 0 && -+ (qtype == dns_rdatatype_a || -+ qtype == dns_rdatatype_any || -+ rpz_type == DNS_RPZ_TYPE_NSIP)) { -+ /* -+ * Rewrite based on an IPv4 address that will appear -+ * in the ANSWER section or if we are checking IP addresses. -+ */ -+ result = rpz_rewrite_ip_rrset(client, name, qtype, -+ rpz_type, dns_rdatatype_a, -+ &ip_db, ip_version, ip_rdatasetp, -+ &p_rdataset, resuming); -+ if (result == ISC_R_SUCCESS) -+ st->state |= DNS_RPZ_DONE_IPv4; -+ } else { -+ result = ISC_R_SUCCESS; -+ } -+ if (result == ISC_R_SUCCESS && -+ (qtype == dns_rdatatype_aaaa || -+ qtype == dns_rdatatype_any || -+ rpz_type == DNS_RPZ_TYPE_NSIP)) { -+ /* -+ * Rewrite based on IPv6 addresses that will appear -+ * in the ANSWER section or if we are checking IP addresses. -+ */ -+ result = rpz_rewrite_ip_rrset(client, name, qtype, -+ rpz_type, dns_rdatatype_aaaa, -+ &ip_db, ip_version, ip_rdatasetp, -+ &p_rdataset, resuming); -+ } -+ if (ip_db != NULL) -+ dns_db_detach(&ip_db); -+ query_putrdataset(client, &p_rdataset); -+ return (result); -+} -+ -+/* -+ * Try to rewrite a request for a qtype rdataset based on the trigger name -+ * trig_name and rpz_type (DNS_RPZ_TYPE_QNAME or DNS_RPZ_TYPE_NSDNAME). -+ * Record the results including the replacement rdataset if any -+ * in client->query.rpz_st. -+ * *rdatasetp is a scratch rdataset. -+ */ -+static isc_result_t -+rpz_rewrite_name(ns_client_t *client, dns_name_t *trig_name, -+ dns_rdatatype_t qtype, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t allowed_zbits, dns_rdataset_t **rdatasetp) -+{ -+ dns_rpz_zone_t *rpz; -+ dns_rpz_st_t *st; -+ dns_fixedname_t p_namef; -+ dns_name_t *p_name; -+ dns_rpz_zbits_t zbits; -+ dns_rpz_num_t rpz_num; -+ dns_zone_t *p_zone; -+ dns_db_t *p_db; -+ dns_dbversion_t *p_version; -+ dns_dbnode_t *p_node; -+ dns_rpz_policy_t policy; -+ isc_result_t result; -+ -+ zbits = rpz_get_zbits(client, qtype, rpz_type); -+ zbits &= allowed_zbits; -+ if (zbits == 0) -+ return (ISC_R_SUCCESS); -+ -+ /* -+ * If there is only one eligible policy zone, just check it. -+ * If more than one, then use the summary database to find -+ * the bit mask of policy zones with policies for this trigger name. -+ * x&-x is the least significant bit set in x -+ */ -+ if (zbits != (zbits & (~zbits + 1))) { -+ zbits = dns_rpz_find_name(client->view->rpzs, -+ rpz_type, zbits, trig_name); -+ if (zbits == 0) -+ return (ISC_R_SUCCESS); -+ } -+ -+ dns_fixedname_init(&p_namef); -+ p_name = dns_fixedname_name(&p_namef); -+ -+ p_zone = NULL; -+ p_db = NULL; -+ p_node = NULL; -+ -+ st = client->query.rpz_st; -+ -+ /* -+ * Check the trigger name in every policy zone that the summary data -+ * says has a hit for the trigger name. -+ * Most of the time there are no eligible zones and the summary data -+ * keeps us from getting this far. -+ * We check the most eligible zone first and so usually check only -+ * one policy zone. -+ */ -+ for (rpz_num = 0; -+ zbits != 0; -+ ++rpz_num, zbits >>= 1) { -+ if ((zbits & 1) == 0) { -+ INSIST(rpz_num <= client->view->rpzs->p.num_zones); -+ continue; - } - - /* -- * See if the policy record exists and get its policy. -+ * Do not check policy zones that cannot replace a previously -+ * found policy. - */ -- result = rpz_find(client, qtype, rpz_qname, qname, rpz, -- rpz_type, &zone, &db, &version, &node, -- rdatasetp, &policy); -+ rpz = client->view->rpzs->zones[rpz_num]; -+ if (st->m.policy != DNS_RPZ_POLICY_MISS) { -+ if (st->m.rpz->num < rpz->num) -+ break; -+ if (st->m.rpz->num == rpz->num && -+ st->m.type < rpz_type) -+ break; -+ } -+ -+ /* -+ * Get the next policy zone's record for this trigger name. -+ */ -+ result = rpz_get_p_name(client, p_name, rpz, rpz_type, -+ trig_name); -+ if (result != ISC_R_SUCCESS) -+ continue; -+ result = rpz_find_p(client, trig_name, qtype, p_name, -+ rpz, rpz_type, -+ &p_zone, &p_db, &p_version, &p_node, -+ rdatasetp, &policy); - switch (result) { - case DNS_R_NXDOMAIN: -- break; -+ /* -+ * Continue after a missing policy record -+ * contrary to the summary data. The summary -+ * data can out of date during races with and among -+ * policy zone updates. -+ */ -+ continue; - case DNS_R_SERVFAIL: -- rpz_clean(&zone, &db, &node, rdatasetp); -+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); - st->m.policy = DNS_RPZ_POLICY_ERROR; - return (DNS_R_SERVFAIL); - default: - /* -- * We are dealing with names here. - * With more than one applicable policy, prefer - * the earliest configured policy, -- * QNAME over IP over NSDNAME over NSIP, -+ * client-IP over QNAME over IP over NSDNAME over NSIP, - * and the smallest name. -- * Because of the testing above, -- * we known st->m.rpz->num >= rpz->num and either -+ * We known st->m.rpz->num >= rpz->num and either - * st->m.rpz->num > rpz->num or st->m.type >= rpz_type - */ - if (st->m.policy != DNS_RPZ_POLICY_MISS && - rpz->num == st->m.rpz->num && - (st->m.type < rpz_type || - (st->m.type == rpz_type && -- 0 >= dns_name_compare(rpz_qname, st->qname)))) -+ 0 >= dns_name_compare(p_name, st->p_name)))) - continue; - #if 0 - /* -@@ -4505,11 +4806,12 @@ - * names in TLDs that start with "rpz-" should - * ICANN ever allow such TLDs. - */ -- labels = dns_name_countlabels(qname); -+ unsigned int labels; -+ labels = dns_name_countlabels(trig_name); - if (labels >= 2) { - dns_label_t label; - -- dns_name_getlabel(qname, labels-2, &label); -+ dns_name_getlabel(trig_name, labels-2, &label); - if (label.length >= sizeof(DNS_RPZ_PREFIX)-1 && - strncasecmp((const char *)label.base+1, - DNS_RPZ_PREFIX, -@@ -4517,46 +4819,29 @@ - continue; - } - #endif -+ if (rpz->policy != DNS_RPZ_POLICY_DISABLED) { -+ rpz_save_p(st, rpz, rpz_type, -+ policy, p_name, 0, result, -+ &p_zone, &p_db, &p_node, -+ rdatasetp, p_version); -+ /* -+ * After a hit, higher numbered policy zones -+ * are irrelevant -+ */ -+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); -+ return (ISC_R_SUCCESS); -+ } - /* -- * Merely log DNS_RPZ_POLICY_DISABLED hits. -+ * Log DNS_RPZ_POLICY_DISABLED zones -+ * and try the next eligible policy zone. - */ -- if (rpz->policy == DNS_RPZ_POLICY_DISABLED) { -- rpz_log_rewrite(client, ISC_TRUE, policy, -- rpz_type, zone, rpz_qname); -- continue; -- } -- -- rpz_match_clear(st); -- st->m.rpz = rpz; -- st->m.type = rpz_type; -- st->m.prefix = 0; -- st->m.policy = policy; -- st->m.result = result; -- dns_name_copy(rpz_qname, st->qname, NULL); -- if (*rdatasetp != NULL && -- dns_rdataset_isassociated(*rdatasetp)) { -- dns_rdataset_t *trdataset; -- -- trdataset = st->m.rdataset; -- st->m.rdataset = *rdatasetp; -- *rdatasetp = trdataset; -- st->m.ttl = ISC_MIN(st->m.rdataset->ttl, -- rpz->max_policy_ttl); -- } else { -- st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT, -- rpz->max_policy_ttl); -- } -- st->m.node = node; -- node = NULL; -- st->m.db = db; -- db = NULL; -- st->m.version = version; -- st->m.zone = zone; -- zone = NULL; -+ rpz_log_rewrite(client, ISC_TRUE, policy, rpz_type, -+ p_zone, p_name); -+ break; - } - } - -- rpz_clean(&zone, &db, &node, rdatasetp); -+ rpz_clean(&p_zone, &p_db, &p_node, rdatasetp); - return (ISC_R_SUCCESS); - } - -@@ -4569,7 +4854,7 @@ - st = client->query.rpz_st; - - if (str != NULL) -- rpz_log_fail(client, level, DNS_RPZ_TYPE_NSIP, nsname, -+ rpz_log_fail(client, level, nsname, DNS_RPZ_TYPE_NSIP, - str, result); - if (st->r.ns_rdataset != NULL && - dns_rdataset_isassociated(st->r.ns_rdataset)) -@@ -4589,7 +4874,8 @@ - dns_rdataset_t *rdataset; - dns_fixedname_t nsnamef; - dns_name_t *nsname; -- isc_boolean_t ck_ip; -+ int qresult_type; -+ dns_rpz_zbits_t zbits; - isc_result_t result; - - st = client->query.rpz_st; -@@ -4604,10 +4890,10 @@ - st->m.ttl = ~0; - memset(&st->r, 0, sizeof(st->r)); - memset(&st->q, 0, sizeof(st->q)); -- dns_fixedname_init(&st->_qnamef); -+ dns_fixedname_init(&st->_p_namef); - dns_fixedname_init(&st->_r_namef); - dns_fixedname_init(&st->_fnamef); -- st->qname = dns_fixedname_name(&st->_qnamef); -+ st->p_name = dns_fixedname_name(&st->_p_namef); - st->r_name = dns_fixedname_name(&st->_r_namef); - st->fname = dns_fixedname_name(&st->_fnamef); - client->query.rpz_st = st; -@@ -4620,7 +4906,7 @@ - case ISC_R_SUCCESS: - case DNS_R_GLUE: - case DNS_R_ZONECUT: -- ck_ip = ISC_TRUE; -+ qresult_type = 0; - break; - case DNS_R_EMPTYNAME: - case DNS_R_NXRRSET: -@@ -4630,73 +4916,155 @@ - case DNS_R_NCACHENXRRSET: - case DNS_R_CNAME: - case DNS_R_DNAME: -- ck_ip = ISC_FALSE; -+ qresult_type = 1; - break; - case DNS_R_DELEGATION: - case ISC_R_NOTFOUND: -- return (ISC_R_SUCCESS); -+ /* -+ * If recursion is on, do only tentative rewriting. -+ * If recursion is off, this the normal and only time we -+ * can rewrite. -+ */ -+ if (RECURSIONOK(client)) -+ qresult_type = 2; -+ else -+ qresult_type = 1; -+ break; - case ISC_R_FAILURE: - case ISC_R_TIMEDOUT: - case DNS_R_BROKENCHAIN: -- rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME, -- client->query.qname, -- "stop on qresult in rpz_rewrite() ", -- qresult); -+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, client->query.qname, -+ DNS_RPZ_TYPE_QNAME, -+ " stop on qresult in rpz_rewrite()", qresult); - return (ISC_R_SUCCESS); - default: -- rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME, -- client->query.qname, -- "stop on unrecognized qresult in rpz_rewrite() ", -+ rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, client->query.qname, -+ DNS_RPZ_TYPE_QNAME, -+ " stop on unrecognized qresult in rpz_rewrite()", - qresult); - return (ISC_R_SUCCESS); - } - - rdataset = NULL; -- if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { -+ -+ if ((st->state & (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) != -+ (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME)) { -+ isc_netaddr_t netaddr; -+ dns_rpz_zbits_t allowed; -+ -+ if (qresult_type == 2) { -+ /* -+ * This request needs recursion that has not been done. -+ * Get bits for the policy zones that do not need -+ * to wait for the results of recursion. -+ */ -+ allowed = client->view->rpzs->have.qname_skip_recurse; -+ if (allowed == 0) -+ return (ISC_R_SUCCESS); -+ } else { -+ allowed = DNS_RPZ_ALL_ZBITS; -+ } -+ - /* -- * Check rules for the query name if this is the first time -- * for the current qname, i.e. we've not been recursing. -- * There is a first time for each name in a CNAME chain. -+ * Check once for triggers for the client IP address. - */ -- result = rpz_rewrite_name(client, qtype, client->query.qname, -- DNS_RPZ_TYPE_QNAME, &rdataset); -- if (result != ISC_R_SUCCESS) -- goto cleanup; -+ if ((st->state & DNS_RPZ_DONE_CLIENT_IP) == 0) { -+ zbits = rpz_get_zbits(client, dns_rdatatype_none, -+ DNS_RPZ_TYPE_CLIENT_IP); -+ zbits &= allowed; -+ if (zbits != 0) { -+ isc_netaddr_fromsockaddr(&netaddr, -+ &client->peeraddr); -+ result = rpz_rewrite_ip(client, &netaddr, qtype, -+ DNS_RPZ_TYPE_CLIENT_IP, -+ zbits, &rdataset); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ } -+ } -+ -+ /* -+ * Check triggers for the query name if this is the first time -+ * for the current qname. -+ * There is a first time for each name in a CNAME chain -+ */ -+ if ((st->state & DNS_RPZ_DONE_QNAME) == 0) { -+ result = rpz_rewrite_name(client, client->query.qname, -+ qtype, DNS_RPZ_TYPE_QNAME, -+ allowed, &rdataset); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+ -+ /* -+ * Check IPv4 addresses in A RRs next. -+ * Reset to the start of the NS names. -+ */ -+ st->r.label = dns_name_countlabels(client->query.qname); -+ st->state &= ~(DNS_RPZ_DONE_QNAME_IP | -+ DNS_RPZ_DONE_IPv4); - -- st->r.label = dns_name_countlabels(client->query.qname); -+ } - -- st->state &= ~(DNS_RPZ_DONE_QNAME_IP | DNS_RPZ_DONE_IPv4); -- st->state |= DNS_RPZ_DONE_QNAME; -+ /* -+ * Quit if this was an attempt to find a qname or -+ * client-IP trigger before recursion. -+ * We will be back if no pre-recursion triggers hit. -+ * For example, consider 2 policy zones, both with qname and -+ * IP address triggers. If the qname misses the 1st zone, -+ * then we cannot know whether a hit for the qname in the -+ * 2nd zone matters until after recursing to get the A RRs and -+ * testing them in the first zone. -+ * Do not bother saving the work from this attempt, -+ * because recusion is so slow. -+ */ -+ if (qresult_type == 2) -+ goto cleanup; -+ -+ /* -+ * DNS_RPZ_DONE_QNAME but not DNS_RPZ_DONE_CLIENT_IP -+ * is reset at the end of dealing with each CNAME. -+ */ -+ st->state |= (DNS_RPZ_DONE_CLIENT_IP | DNS_RPZ_DONE_QNAME); - } - - /* -- * Check known IP addresses for the query name. -+ * Check known IP addresses for the query name if the database -+ * lookup resulted in some addresses (qresult_type == 0) -+ * and if we have not already checked them. - * Any recursion required for the query has already happened. - * Do not check addresses that will not be in the ANSWER section. - */ -- if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && -- (st->state & DNS_RPZ_HAVE_IP) != 0 && ck_ip) { -- result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_IP, -- client->query.qname, qtype, -- &rdataset, resuming); -+ if ((st->state & DNS_RPZ_DONE_QNAME_IP) == 0 && qresult_type == 0 && -+ rpz_get_zbits(client, qtype, DNS_RPZ_TYPE_IP) != 0) { -+ result = rpz_rewrite_ip_rrsets(client, -+ client->query.qname, qtype, -+ DNS_RPZ_TYPE_IP, -+ &rdataset, resuming); - if (result != ISC_R_SUCCESS) - goto cleanup; -- st->state &= ~DNS_RPZ_DONE_IPv4; -+ /* -+ * We are finished checking the IP addresses for the qname. -+ * Start with IPv4 if we will check NS IP addesses. -+ */ - st->state |= DNS_RPZ_DONE_QNAME_IP; -+ st->state &= ~DNS_RPZ_DONE_IPv4; - } - - /* -- * Stop looking for rules if there are none of the other kinds. -+ * Stop looking for rules if there are none of the other kinds -+ * that could override what we already have. - */ -- if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 | -- DNS_RPZ_HAVE_NSDNAME)) == 0) { -+ if (rpz_get_zbits(client, dns_rdatatype_any, -+ DNS_RPZ_TYPE_NSDNAME) == 0 && -+ rpz_get_zbits(client, dns_rdatatype_any, -+ DNS_RPZ_TYPE_NSIP) == 0) { - result = ISC_R_SUCCESS; - goto cleanup; - } - - dns_fixedname_init(&nsnamef); - dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef)); -- while (st->r.label > client->view->rpz_min_ns_labels) { -+ while (st->r.label > client->view->rpzs->p.min_ns_labels) { - /* - * Get NS rrset for each domain in the current qname. - */ -@@ -4710,8 +5078,8 @@ - if (st->r.ns_rdataset == NULL || - !dns_rdataset_isassociated(st->r.ns_rdataset)) { - dns_db_t *db = NULL; -- result = rpz_rrset_find(client, DNS_RPZ_TYPE_NSDNAME, -- nsname, dns_rdatatype_ns, -+ result = rpz_rrset_find(client, nsname, dns_rdatatype_ns, -+ DNS_RPZ_TYPE_NSDNAME, - &db, NULL, &st->r.ns_rdataset, - resuming); - if (db != NULL) -@@ -4745,12 +5113,12 @@ - case ISC_R_FAILURE: - rpz_rewrite_ns_skip(client, nsname, result, - DNS_RPZ_DEBUG_LEVEL3, -- "NS db_find() "); -+ " NS db_find()"); - continue; - default: - rpz_rewrite_ns_skip(client, nsname, result, - DNS_RPZ_INFO_LEVEL, -- "unrecognized NS db_find() "); -+ " unrecognized NS db_find()"); - continue; - } - } -@@ -4766,8 +5134,8 @@ - dns_rdata_reset(&nsrdata); - if (result != ISC_R_SUCCESS) { - rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, -- DNS_RPZ_TYPE_NSIP, nsname, -- "rdata_tostruct() ", result); -+ nsname, DNS_RPZ_TYPE_NSIP, -+ " rdata_tostruct()", result); - st->m.policy = DNS_RPZ_POLICY_ERROR; - goto cleanup; - } -@@ -4783,11 +5151,11 @@ - * Check this NS name if we did not handle it - * during a previous recursion. - */ -- if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0 && -- (st->state & DNS_RPZ_HAVE_NSDNAME) != 0) { -- result = rpz_rewrite_name(client, qtype, -- &ns.name, -+ if ((st->state & DNS_RPZ_DONE_NSDNAME) == 0) { -+ result = rpz_rewrite_name(client, &ns.name, -+ qtype, - DNS_RPZ_TYPE_NSDNAME, -+ DNS_RPZ_ALL_ZBITS, - &rdataset); - if (result != ISC_R_SUCCESS) { - dns_rdata_freestruct(&ns); -@@ -4798,9 +5166,9 @@ - /* - * Check all IP addresses for this NS name. - */ -- result = rpz_rewrite_rrsets(client, DNS_RPZ_TYPE_NSIP, -- &ns.name, dns_rdatatype_any, -- &rdataset, resuming); -+ result = rpz_rewrite_ip_rrsets(client, &ns.name, qtype, -+ DNS_RPZ_TYPE_NSIP, -+ &rdataset, resuming); - dns_rdata_freestruct(&ns); - if (result != ISC_R_SUCCESS) - goto cleanup; -@@ -4810,10 +5178,16 @@ - } while (result == ISC_R_SUCCESS); - dns_rdataset_disassociate(st->r.ns_rdataset); - st->r.label--; -+ -+ if (rpz_get_zbits(client, dns_rdatatype_any, -+ DNS_RPZ_TYPE_NSDNAME) == 0 && -+ rpz_get_zbits(client, dns_rdatatype_any, -+ DNS_RPZ_TYPE_NSIP) == 0) -+ break; - } - - /* -- * Use the best, if any, hit. -+ * Use the best hit, if any. - */ - result = ISC_R_SUCCESS; - -@@ -4828,7 +5202,7 @@ - if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU && - result != DNS_R_DELEGATION) - rpz_log_rewrite(client, ISC_FALSE, st->m.policy, -- st->m.type, st->m.zone, st->qname); -+ st->m.type, st->m.zone, st->p_name); - rpz_match_clear(st); - } - if (st->m.policy == DNS_RPZ_POLICY_ERROR) { -@@ -4847,19 +5221,25 @@ - * by the client in DNSSEC or a lack of signatures. - */ - static isc_boolean_t --rpz_ck_dnssec(ns_client_t *client, isc_result_t result, -+rpz_ck_dnssec(ns_client_t *client, isc_result_t qresult, - dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) - { - dns_fixedname_t fixed; - dns_name_t *found; - dns_rdataset_t trdataset; - dns_rdatatype_t type; -+ isc_result_t result; - -- if (client->view->rpz_break_dnssec) -+ if (client->view->rpzs->p.break_dnssec || !WANTDNSSEC(client)) - return (ISC_TRUE); -+ - /* -- * sigrdataset == NULL if and only !WANTDNSSEC(client) -+ * We do not know if there are signatures if we have not recursed -+ * for them. - */ -+ if (qresult == DNS_R_DELEGATION || qresult == ISC_R_NOTFOUND) -+ return (ISC_FALSE); -+ - if (sigrdataset == NULL) - return (ISC_TRUE); - if (dns_rdataset_isassociated(sigrdataset)) -@@ -4939,7 +5319,7 @@ - if (result != ISC_R_SUCCESS) - return (result); - rpz_log_rewrite(client, ISC_FALSE, st->m.policy, -- st->m.type, st->m.zone, st->qname); -+ st->m.type, st->m.zone, st->p_name); - ns_client_qnamereplace(client, fname); - /* - * Turn off DNSSEC because the results of a -@@ -5998,13 +6378,15 @@ - } - #endif /* USE_RRL */ - -- if (!ISC_LIST_EMPTY(client->view->rpz_zones) && -- (RECURSIONOK(client) || !client->view->rpz_recursive_only) && -+ if (client->view->rpzs != NULL && -+ client->view->rpzs->p.num_zones != 0 && -+ (RECURSIONOK(client) || client->view->rpzs->p.no_rd_ok != 0) && - rpz_ck_dnssec(client, result, rdataset, sigrdataset) && - !RECURSING(client) && - (client->query.rpz_st == NULL || - (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) && -- !dns_name_equal(client->query.qname, dns_rootname)) { -+ !dns_name_equal(client->query.qname, dns_rootname)) -+ { - isc_result_t rresult; - - rresult = rpz_rewrite(client, qtype, result, resuming); -@@ -6042,12 +6424,17 @@ - rpz_st->state |= DNS_RPZ_REWRITTEN; - if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS && - rpz_st->m.policy != DNS_RPZ_POLICY_PASSTHRU && -+ (rpz_st->m.policy != DNS_RPZ_POLICY_TCP_ONLY || -+ (client->attributes & NS_CLIENTATTR_TCP) == 0) && - rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) { -- if (rpz_st->m.type == DNS_RPZ_TYPE_QNAME) { -- result = dns_name_copy(client->query.qname, -- fname, NULL); -- RUNTIME_CHECK(result == ISC_R_SUCCESS); -- } -+ /* We got a hit and are going to answer with our -+ * fiction. Ensure that we answer with the name -+ * we looked up even if we were stopped short -+ * in recursion or for a deferral. -+ */ -+ rresult = dns_name_copy(client->query.qname, -+ fname, NULL); -+ RUNTIME_CHECK(rresult == ISC_R_SUCCESS); - rpz_clean(&zone, &db, &node, NULL); - if (rpz_st->m.rdataset != NULL) { - query_putrdataset(client, &rdataset); -@@ -6067,6 +6454,27 @@ - rpz_st->m.zone = NULL; - - switch (rpz_st->m.policy) { -+ case DNS_RPZ_POLICY_TCP_ONLY: -+ client->message->flags |= DNS_MESSAGEFLAG_TC; -+ if (result == DNS_R_NXDOMAIN || -+ result == DNS_R_NCACHENXDOMAIN) -+ client->message->rcode = -+ dns_rcode_nxdomain; -+ else -+ result = ISC_R_SUCCESS; -+ rpz_log_rewrite(client, ISC_FALSE, -+ rpz_st->m.policy, -+ rpz_st->m.type, zone, -+ rpz_st->p_name); -+ goto cleanup; -+ case DNS_RPZ_POLICY_DROP: -+ result = ISC_R_SUCCESS; -+ QUERY_ERROR(DNS_R_DROP); -+ rpz_log_rewrite(client, ISC_FALSE, -+ rpz_st->m.policy, -+ rpz_st->m.type, zone, -+ rpz_st->p_name); -+ goto cleanup; - case DNS_RPZ_POLICY_NXDOMAIN: - result = DNS_R_NXDOMAIN; - break; -@@ -6079,8 +6487,8 @@ - result != DNS_R_CNAME) { - /* - * We will add all of the rdatasets of -- * the node by iterating, setting the -- * TTL then. -+ * the node by iterating later, -+ * and set the TTL then. - */ - if (dns_rdataset_isassociated(rdataset)) - dns_rdataset_disassociate(rdataset); -@@ -6135,7 +6543,7 @@ - rpz_st->q.is_zone = is_zone; - is_zone = ISC_TRUE; - rpz_log_rewrite(client, ISC_FALSE, rpz_st->m.policy, -- rpz_st->m.type, zone, rpz_st->qname); -+ rpz_st->m.type, zone, rpz_st->p_name); - } - } - -diff -r -u bin/named/server.c-orig bin/named/server.c ---- bin/named/server.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/named/server.c 2004-01-01 00:00:00.000000000 +0000 -@@ -375,7 +375,8 @@ - static isc_result_t - configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, - const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, -- cfg_aclconfctx_t *aclconf, isc_boolean_t added); -+ cfg_aclconfctx_t *aclconf, isc_boolean_t added, -+ isc_boolean_t old_rpz_ok); - - static isc_result_t - add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx); -@@ -1556,17 +1557,24 @@ - } - - static isc_result_t --configure_rpz(dns_view_t *view, const cfg_listelt_t *element, -- isc_boolean_t recursive_only_def, dns_ttl_t ttl_def) -+configure_rpz_zone(dns_view_t *view, const cfg_listelt_t *element, -+ isc_boolean_t recursive_only_def, dns_ttl_t ttl_def, -+ const dns_rpz_zone_t *old, isc_boolean_t *old_rpz_okp) - { - const cfg_obj_t *rpz_obj, *obj; - const char *str; -- dns_rpz_zone_t *old, *new; -+ dns_rpz_zone_t *new; - isc_result_t result; -+ dns_rpz_num_t rpz_num; -+ -+ REQUIRE(old != NULL || !*old_rpz_okp); - - rpz_obj = cfg_listelt_value(element); - -- new = isc_mem_get(view->mctx, sizeof(*new)); -+ if (view->rpzs->p.num_zones >= DNS_RPZ_MAX_ZONES) -+ return (ISC_R_NOMEMORY); -+ -+ new = isc_mem_get(view->rpzs->mctx, sizeof(*new)); - if (new == NULL) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "no memory for response policy zones"); -@@ -1574,20 +1582,29 @@ - } - - memset(new, 0, sizeof(*new)); -+ result = isc_refcount_init(&new->refs, 1); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(view->rpzs->mctx, new, sizeof(*new)); -+ return (result); -+ } - dns_name_init(&new->origin, NULL); -+ dns_name_init(&new->client_ip, NULL); -+ dns_name_init(&new->ip, NULL); - dns_name_init(&new->nsdname, NULL); -+ dns_name_init(&new->nsip, NULL); - dns_name_init(&new->passthru, NULL); -+ dns_name_init(&new->drop, NULL); -+ dns_name_init(&new->tcp_only, NULL); - dns_name_init(&new->cname, NULL); -- ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link); -+ new->num = view->rpzs->p.num_zones++; -+ view->rpzs->zones[new->num] = new; - - obj = cfg_tuple_get(rpz_obj, "recursive-only"); -- if (cfg_obj_isvoid(obj)) { -- new->recursive_only = recursive_only_def; -+ if (cfg_obj_isvoid(obj) ? recursive_only_def : cfg_obj_asboolean(obj)) { -+ view->rpzs->p.no_rd_ok &= ~DNS_RPZ_ZBIT(new->num); - } else { -- new->recursive_only = cfg_obj_asboolean(obj); -+ view->rpzs->p.no_rd_ok |= DNS_RPZ_ZBIT(new->num); - } -- if (!new->recursive_only) -- view->rpz_recursive_only = ISC_FALSE; - - obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); - if (cfg_obj_isuint32(obj)) { -@@ -1595,6 +1612,8 @@ - } else { - new->max_policy_ttl = ttl_def; - } -+ if (*old_rpz_okp && new->max_policy_ttl != old->max_policy_ttl) -+ *old_rpz_okp = ISC_FALSE; - - str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "zone name")); - result = configure_rpz_name(view, rpz_obj, &new->origin, str, "zone"); -@@ -1605,25 +1624,50 @@ - "invalid zone name '%s'", str); - return (DNS_R_EMPTYLABEL); - } -- for (old = ISC_LIST_HEAD(view->rpz_zones); -- old != new; -- old = ISC_LIST_NEXT(old, link)) { -- ++new->num; -- if (dns_name_equal(&old->origin, &new->origin)) { -+ for (rpz_num = 0; rpz_num < view->rpzs->p.num_zones-1; ++rpz_num) { -+ if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, -+ &new->origin)) { - cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, - "duplicate '%s'", str); - result = DNS_R_DUPLICATE; - return (result); - } - } -+ if (*old_rpz_okp && !dns_name_equal(&old->origin, &new->origin)) -+ *old_rpz_okp = ISC_FALSE; -+ -+ result = configure_rpz_name2(view, rpz_obj, &new->client_ip, -+ DNS_RPZ_CLIENT_IP_ZONE, &new->origin); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ result = configure_rpz_name2(view, rpz_obj, &new->ip, -+ DNS_RPZ_IP_ZONE, &new->origin); -+ if (result != ISC_R_SUCCESS) -+ return (result); - - result = configure_rpz_name2(view, rpz_obj, &new->nsdname, - DNS_RPZ_NSDNAME_ZONE, &new->origin); - if (result != ISC_R_SUCCESS) - return (result); - -+ result = configure_rpz_name2(view, rpz_obj, &new->nsip, -+ DNS_RPZ_NSIP_ZONE, &new->origin); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ - result = configure_rpz_name(view, rpz_obj, &new->passthru, -- DNS_RPZ_PASSTHRU_ZONE, "zone"); -+ DNS_RPZ_PASSTHRU_NAME, "name"); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ result = configure_rpz_name(view, rpz_obj, &new->drop, -+ DNS_RPZ_DROP_NAME, "name"); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ -+ result = configure_rpz_name(view, rpz_obj, &new->tcp_only, -+ DNS_RPZ_TCP_ONLY_NAME, "name"); - if (result != ISC_R_SUCCESS) - return (result); - -@@ -1642,6 +1686,116 @@ - return (result); - } - } -+ if (*old_rpz_okp && (new->policy != old->policy || -+ !dns_name_equal(&old->cname, &new->cname))) -+ *old_rpz_okp = ISC_FALSE; -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+configure_rpz(dns_view_t *view, const cfg_obj_t *rpz_obj, -+ isc_boolean_t *old_rpz_okp) -+{ -+ const cfg_listelt_t *zone_element; -+ const cfg_obj_t *sub_obj; -+ isc_boolean_t recursive_only_def; -+ dns_ttl_t ttl_def; -+ dns_rpz_zones_t *new; -+ const dns_rpz_zones_t *old; -+ dns_view_t *pview; -+ const dns_rpz_zone_t *old_zone; -+ isc_result_t result; -+ int i; -+ -+ *old_rpz_okp = ISC_FALSE; -+ -+ zone_element = cfg_list_first(cfg_tuple_get(rpz_obj, "zone list")); -+ if (zone_element == NULL) -+ return (ISC_R_SUCCESS); -+ -+ result = dns_rpz_new_zones(&view->rpzs, view->mctx); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ new = view->rpzs; -+ -+ sub_obj = cfg_tuple_get(rpz_obj, "recursive-only"); -+ if (!cfg_obj_isvoid(sub_obj) && -+ !cfg_obj_asboolean(sub_obj)) -+ recursive_only_def = ISC_FALSE; -+ else -+ recursive_only_def = ISC_TRUE; -+ -+ sub_obj = cfg_tuple_get(rpz_obj, "break-dnssec"); -+ if (!cfg_obj_isvoid(sub_obj) && -+ cfg_obj_asboolean(sub_obj)) -+ new->p.break_dnssec = ISC_TRUE; -+ else -+ new->p.break_dnssec = ISC_FALSE; -+ -+ sub_obj = cfg_tuple_get(rpz_obj, "max-policy-ttl"); -+ if (cfg_obj_isuint32(sub_obj)) -+ ttl_def = cfg_obj_asuint32(sub_obj); -+ else -+ ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; -+ -+ sub_obj = cfg_tuple_get(rpz_obj, "min-ns-dots"); -+ if (cfg_obj_isuint32(sub_obj)) -+ new->p.min_ns_labels = cfg_obj_asuint32(sub_obj) + 1; -+ else -+ new->p.min_ns_labels = 2; -+ -+ sub_obj = cfg_tuple_get(rpz_obj, "qname-wait-recurse"); -+ if (cfg_obj_isvoid(sub_obj) || cfg_obj_asboolean(sub_obj)) -+ new->p.qname_wait_recurse = ISC_TRUE; -+ else -+ new->p.qname_wait_recurse = ISC_FALSE; -+ -+ pview = NULL; -+ result = dns_viewlist_find(&ns_g_server->viewlist, -+ view->name, view->rdclass, &pview); -+ if (result == ISC_R_SUCCESS) { -+ old = pview->rpzs; -+ } else { -+ old = NULL; -+ } -+ if (old == NULL) -+ *old_rpz_okp = ISC_FALSE; -+ else -+ *old_rpz_okp = ISC_TRUE; -+ -+ for (i = 0; -+ zone_element != NULL; -+ ++i, zone_element = cfg_list_next(zone_element)) { -+ if (*old_rpz_okp && i < old->p.num_zones) { -+ old_zone = old->zones[i]; -+ } else { -+ *old_rpz_okp = ISC_FALSE; -+ old_zone = NULL; -+ } -+ result = configure_rpz_zone(view, zone_element, -+ recursive_only_def, ttl_def, -+ old_zone, old_rpz_okp); -+ if (result != ISC_R_SUCCESS) { -+ if (pview != NULL) -+ dns_view_detach(&pview); -+ return (result); -+ } -+ } -+ -+ /* -+ * If this is a reloading and the parameters and list of policy -+ * zones are unchanged, then use the same policy data. -+ * Data for individual zones that must be reloaded will be merged. -+ */ -+ if (old != NULL && memcmp(&old->p, &new->p, sizeof(new->p)) != 0) -+ *old_rpz_okp = ISC_FALSE; -+ if (*old_rpz_okp) { -+ dns_rpz_detach_rpzs(&view->rpzs); -+ dns_rpz_attach_rpzs(pview->rpzs, &view->rpzs); -+ } -+ if (pview != NULL) -+ dns_view_detach(&pview); - - return (ISC_R_SUCCESS); - } -@@ -2109,7 +2263,7 @@ - dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL; - unsigned int query_timeout, ndisp; - struct cfg_context *nzctx; -- dns_rpz_zone_t *rpz; -+ isc_boolean_t old_rpz_ok = ISC_FALSE; - - REQUIRE(DNS_VIEW_VALID(view)); - -@@ -2207,44 +2361,7 @@ - obj = NULL; - if (view->rdclass == dns_rdataclass_in && need_hints && - ns_config_get(maps, "response-policy", &obj) == ISC_R_SUCCESS) { -- const cfg_obj_t *rpz_obj; -- isc_boolean_t recursive_only_def; -- dns_ttl_t ttl_def; -- -- rpz_obj = cfg_tuple_get(obj, "recursive-only"); -- if (!cfg_obj_isvoid(rpz_obj) && -- !cfg_obj_asboolean(rpz_obj)) -- recursive_only_def = ISC_FALSE; -- else -- recursive_only_def = ISC_TRUE; -- -- rpz_obj = cfg_tuple_get(obj, "break-dnssec"); -- if (!cfg_obj_isvoid(rpz_obj) && -- cfg_obj_asboolean(rpz_obj)) -- view->rpz_break_dnssec = ISC_TRUE; -- else -- view->rpz_break_dnssec = ISC_FALSE; -- -- rpz_obj = cfg_tuple_get(obj, "max-policy-ttl"); -- if (cfg_obj_isuint32(rpz_obj)) -- ttl_def = cfg_obj_asuint32(rpz_obj); -- else -- ttl_def = DNS_RPZ_MAX_TTL_DEFAULT; -- -- rpz_obj = cfg_tuple_get(obj, "min-ns-dots"); -- if (cfg_obj_isuint32(rpz_obj)) -- view->rpz_min_ns_labels = cfg_obj_asuint32(rpz_obj) + 1; -- else -- view->rpz_min_ns_labels = 2; -- -- element = cfg_list_first(cfg_tuple_get(obj, "zone list")); -- while (element != NULL) { -- result = configure_rpz(view, element, -- recursive_only_def, ttl_def); -- if (result != ISC_R_SUCCESS) -- goto cleanup; -- element = cfg_list_next(element); -- } -+ CHECK(configure_rpz(view, obj, &old_rpz_ok)); - } - - /* -@@ -2265,22 +2382,29 @@ - { - const cfg_obj_t *zconfig = cfg_listelt_value(element); - CHECK(configure_zone(config, zconfig, vconfig, mctx, view, -- actx, ISC_FALSE)); -+ actx, ISC_FALSE, old_rpz_ok)); - } - -- for (rpz = ISC_LIST_HEAD(view->rpz_zones); -- rpz != NULL; -- rpz = ISC_LIST_NEXT(rpz, link)) -- { -- if (!rpz->defined) { -- char namebuf[DNS_NAME_FORMATSIZE]; -+ /* -+ * Check that a master or slave zone was found for each -+ * zone named in the response policy statement. -+ */ -+ if (view->rpzs != NULL) { -+ dns_rpz_num_t n; - -- dns_name_format(&rpz->origin, namebuf, sizeof(namebuf)); -- cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, -- "'%s' is not a master or slave zone", -- namebuf); -- result = ISC_R_NOTFOUND; -- goto cleanup; -+ for (n = 0; n < view->rpzs->p.num_zones; ++n) -+ { -+ if ((view->rpzs->defined & DNS_RPZ_ZBIT(n)) == 0) { -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ -+ dns_name_format(&view->rpzs->zones[n]->origin, -+ namebuf, sizeof(namebuf)); -+ cfg_obj_log(obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL, -+ "'%s' is not a master or slave zone", -+ namebuf); -+ result = ISC_R_NOTFOUND; -+ goto cleanup; -+ } - } - } - -@@ -2306,7 +2430,7 @@ - const cfg_obj_t *zconfig = cfg_listelt_value(element); - CHECK(configure_zone(config, zconfig, vconfig, - mctx, view, actx, -- ISC_TRUE)); -+ ISC_TRUE, ISC_FALSE)); - } - } - -@@ -3750,7 +3874,8 @@ - static isc_result_t - configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig, - const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view, -- cfg_aclconfctx_t *aclconf, isc_boolean_t added) -+ cfg_aclconfctx_t *aclconf, isc_boolean_t added, -+ isc_boolean_t old_rpz_ok) - { - dns_view_t *pview = NULL; /* Production view */ - dns_zone_t *zone = NULL; /* New or reused zone */ -@@ -3771,8 +3896,7 @@ - const char *zname; - dns_rdataclass_t zclass; - const char *ztypestr; -- isc_boolean_t is_rpz; -- dns_rpz_zone_t *rpz; -+ dns_rpz_num_t rpz_num; - - options = NULL; - (void)cfg_map_get(config, "options", &options); -@@ -3934,18 +4058,15 @@ - INSIST(dupzone == NULL); - - /* -- * Note whether this is a response policy zone. -+ * Note whether this is a response policy zone and which one if so. - */ -- is_rpz = ISC_FALSE; -- for (rpz = ISC_LIST_HEAD(view->rpz_zones); -- rpz != NULL; -- rpz = ISC_LIST_NEXT(rpz, link)) -- { -- if (dns_name_equal(&rpz->origin, origin)) { -- is_rpz = ISC_TRUE; -- rpz->defined = ISC_TRUE; -+ for (rpz_num = 0; ; ++rpz_num) { -+ if (view->rpzs == NULL || rpz_num >= view->rpzs->p.num_zones) { -+ rpz_num = DNS_RPZ_INVALID_NUM; - break; - } -+ if (dns_name_equal(&view->rpzs->zones[rpz_num]->origin, origin)) -+ break; - } - - /* -@@ -3956,7 +4077,9 @@ - * - The zone is compatible with the config - * options (e.g., an existing master zone cannot - * be reused if the options specify a slave zone) -- * - The zone was and is or was not and is not a policy zone -+ * - The zone was not and is still not a response policy zone -+ * or the zone is a policy zone with an unchanged number -+ * and we are using the old policy zone summary data. - */ - result = dns_viewlist_find(&ns_g_server->viewlist, view->name, - view->rdclass, &pview); -@@ -3970,7 +4093,8 @@ - if (zone != NULL && !ns_zone_reusable(zone, zconfig)) - dns_zone_detach(&zone); - -- if (zone != NULL && is_rpz != dns_zone_get_rpz(zone)) -+ if (zone != NULL && (rpz_num != dns_zone_get_rpz_num(zone) || -+ (rpz_num != DNS_RPZ_INVALID_NUM && !old_rpz_ok))) - dns_zone_detach(&zone); - - if (zone != NULL) { -@@ -3995,8 +4119,8 @@ - dns_zone_setstats(zone, ns_g_server->zonestats); - } - -- if (is_rpz) { -- result = dns_zone_rpz_enable(zone); -+ if (rpz_num != DNS_RPZ_INVALID_NUM) { -+ result = dns_zone_rpz_enable(zone, view->rpzs, rpz_num); - if (result != ISC_R_SUCCESS) { - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_ERROR, -@@ -8286,7 +8410,8 @@ - RUNTIME_CHECK(result == ISC_R_SUCCESS); - dns_view_thaw(view); - result = configure_zone(cfg->config, parms, vconfig, -- server->mctx, view, cfg->actx, ISC_FALSE); -+ server->mctx, view, cfg->actx, ISC_FALSE, -+ ISC_FALSE); - dns_view_freeze(view); - isc_task_endexclusive(server->task); - if (result != ISC_R_SUCCESS) -diff -r -u bin/tests/system/rpz/Makefile-orig bin/tests/system/rpz/Makefile ---- bin/tests/system/rpz/Makefile-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/Makefile 2004-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,478 @@ -+# Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id$ -+ -+ -+srcdir = . -+ -+top_srcdir = ../../../.. -+ -+VERSION=9.10.0pre-alpha -+ -+# Copyright (C) 2004, 2005, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") -+# Copyright (C) 1999-2001 Internet Software Consortium. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id: includes.in,v 1.21 2007/06/19 23:47:24 tbox Exp $ -+ -+# Search for machine-generated header files in the build tree, -+# and for normal headers in the source tree (${top_srcdir}). -+# We only need to look in OS-specific subdirectories for the -+# latter case, because there are no machine-generated OS-specific -+# headers. -+ -+ISC_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/isc/include \ -+ -I${top_srcdir}/lib/isc \ -+ -I${top_srcdir}/lib/isc/include \ -+ -I${top_srcdir}/lib/isc/unix/include \ -+ -I${top_srcdir}/lib/isc/pthreads/include \ -+ -I${top_srcdir}/lib/isc/x86_32/include -+ -+ISCCC_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/isccc/include \ -+ -I${top_srcdir}/lib/isccc/include -+ -+ISCCFG_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/isccfg/include \ -+ -I${top_srcdir}/lib/isccfg/include -+ -+DNS_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/dns/include \ -+ -I${top_srcdir}/lib/dns/include -+ -+LWRES_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/lwres/include \ -+ -I${top_srcdir}/lib/lwres/unix/include \ -+ -I${top_srcdir}/lib/lwres/include -+ -+BIND9_INCLUDES = -I/usr/home/vjs/isc/work/rpz3/lib/bind9/include \ -+ -I${top_srcdir}/lib/bind9/include -+ -+TEST_INCLUDES = \ -+ -I${top_srcdir}/lib/tests/include -+ -+CINCLUDES = -+ -+CDEFINES = -+CWARNINGS = -+ -+DNSLIBS = -+ISCLIBS = . -+ -+DNSDEPLIBS = -+ISCDEPLIBS = -+ -+DEPLIBS = -+ -+LIBS = -L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm -+ -+TARGETS = rpz -+ -+RPZOBJS = rpz.o -+ -+SRCS = rpz.c -+ -+# Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") -+# Copyright (C) 1998-2003 Internet Software Consortium. -+# -+# Permission to use, copy, modify, and/or distribute this software for any -+# purpose with or without fee is hereby granted, provided that the above -+# copyright notice and this permission notice appear in all copies. -+# -+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+# PERFORMANCE OF THIS SOFTWARE. -+ -+# $Id$ -+ -+### -+### Common Makefile rules for BIND 9. -+### -+ -+### -+### Paths -+### -+### Note: paths that vary by Makefile MUST NOT be listed -+### here, or they won't get expanded correctly. -+ -+prefix = /usr -+exec_prefix = ${prefix} -+bindir = ${exec_prefix}/bin -+sbindir = ${exec_prefix}/sbin -+includedir = ${prefix}/include -+libdir = ${exec_prefix}/lib -+sysconfdir = /etc/namedb -+localstatedir = ${prefix}/var -+mandir = ${datarootdir}/man -+datarootdir = ${prefix}/share -+ -+DESTDIR = -+ -+ -+ -+top_builddir = /usr/home/vjs/isc/work/rpz3 -+ -+### -+### All -+### -+### Makefile may define: -+### TARGETS -+ -+all: subdirs ${TARGETS} testdirs -+ -+### -+### Subdirectories -+### -+### Makefile may define: -+### SUBDIRS -+ -+ALL_SUBDIRS = ${SUBDIRS} nulldir -+ALL_TESTDIRS = ${TESTDIRS} nulldir -+ -+# -+# We use a single-colon rule so that additional dependencies of -+# subdirectories can be specified after the inclusion of this file. -+# The "depend" and "testdirs" targets are treated the same way. -+# -+subdirs: -+ @for i in ${ALL_SUBDIRS}; do \ -+ if [ "$$i" != "nulldir" -a -d $$i ]; then \ -+ echo "making all in `pwd`/$$i"; \ -+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" all) || exit 1; \ -+ fi; \ -+ done -+ -+# -+# Tests are built after the targets instead of before -+# -+testdirs: -+ @for i in ${ALL_TESTDIRS}; do \ -+ if [ "$$i" != "nulldir" -a -d $$i ]; then \ -+ echo "making all in `pwd`/$$i"; \ -+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" all) || exit 1; \ -+ fi; \ -+ done -+ -+install:: all -+ -+install clean distclean maintainer-clean doc docclean man manclean:: -+ @for i in ${ALL_SUBDIRS} ${ALL_TESTDIRS}; do \ -+ if [ "$$i" != "nulldir" -a -d $$i ]; then \ -+ echo "making $@ in `pwd`/$$i"; \ -+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@) || exit 1; \ -+ fi; \ -+ done -+ -+### -+### C Programs -+### -+### Makefile must define -+### CC -+### Makefile may define -+### CFLAGS -+### LDFLAGS -+### CINCLUDES -+### CDEFINES -+### CWARNINGS -+### User may define externally -+### EXT_CFLAGS -+ -+CC = gcc -pthread -+CFLAGS = -g -I/usr/local/include/libxml2 -I/usr/local/include -+LDFLAGS = -+STD_CINCLUDES = -+STD_CDEFINES = -D_THREAD_SAFE -+STD_CWARNINGS = -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wformat -Wpointer-arith -fno-strict-aliasing -+ -+BUILD_CC = gcc -pthread -+BUILD_CFLAGS = -g -I/usr/local/include/libxml2 -I/usr/local/include -+BUILD_CPPFLAGS = -+BUILD_LDFLAGS = -+BUILD_LIBS = -L/usr/local/lib -lxml2 -lz -L/usr/local/lib -liconv -lm -+ -+.SUFFIXES: -+.SUFFIXES: .c .o -+ -+ALWAYS_INCLUDES = -I${top_builddir} -+ALWAYS_DEFINES = -D_REENTRANT -+ALWAYS_WARNINGS = -+ -+ALL_CPPFLAGS = \ -+ ${ALWAYS_INCLUDES} ${CINCLUDES} ${STD_CINCLUDES} \ -+ ${ALWAYS_DEFINES} ${CDEFINES} ${STD_CDEFINES} -+ -+ALL_CFLAGS = ${EXT_CFLAGS} ${ALL_CPPFLAGS} ${CFLAGS} \ -+ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} -+ -+.c.o: -+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c $< -+ -+SHELL = /bin/sh -+LIBTOOL = -+LIBTOOL_MODE_COMPILE = ${LIBTOOL} -+LIBTOOL_MODE_INSTALL = ${LIBTOOL} -+LIBTOOL_MODE_LINK = ${LIBTOOL} -+PURIFY = -+ -+MKDEP = ${SHELL} ${top_builddir}/make/mkdep -+ -+### -+### This is a template compound command to build an executable binary with -+### an internal symbol table. -+### This process is tricky. We first link all objects including a tentative -+### empty symbol table, then get a tentative list of symbols from the resulting -+### binary ($@tmp0). Next, we re-link all objects, but this time with the -+### symbol table just created ($tmp@1). The set of symbols should be the same, -+### but the corresponding addresses would be changed due to the difference on -+### the size of symbol tables. So we create the symbol table and re-create the -+### objects once again. Finally, we check the symbol table embedded in the -+### final binaryis consistent with the binary itself; otherwise the process is -+### terminated. -+### -+### To minimize the overhead of creating symbol tables, the autoconf switch -+### --enable-symtable takes an argument so that the symbol table can be created -+### on a per application basis: unless the argument is set to "all", the symbol -+### table is created only when a shell (environment) variable "MAKE_SYMTABLE" is -+### set to a non-null value in the rule to build the executable binary. -+### -+### Each Makefile.in that uses this macro is expected to define "LIBS" and -+### "NOSYMLIBS"; the former includes libisc with an empty symbol table, and -+### the latter includes libisc without the definition of a symbol table. -+### The rule to make the executable binary will look like this -+### binary: ${OBJS} -+### #export MAKE_SYMTABLE="yes"; \ <- enable if symtable is always needed -+### export BASEOBJS="${OBJS}"; \ -+### ${FINALBUILDCMD} -+### -+### Normally, ${LIBS} includes all necessary libraries to build the binary; -+### there are some exceptions however, where the rule lists some of the -+### necessary libraries explicitly in addition to (or instead of) ${LIBS}, -+### like this: -+### binary: ${OBJS} -+### cc -o $@ ${OBJS} ${OTHERLIB1} ${OTHERLIB2} ${lIBS} -+### in order to modify such a rule to use this compound command, a separate -+### variable "LIBS0" should be deinfed for the explicitly listed libraries, -+### while making sure ${LIBS} still includes libisc. So the above rule would -+### be modified as follows: -+### binary: ${OBJS} -+### export BASEOBJS="${OBJS}"; \ -+### export LIBS0="${OTHERLIB1} ${OTHERLIB2}"; \ -+### ${FINALBUILDCMD} -+### See bin/check/Makefile.in for a complete example of the use of LIBS0. -+### -+FINALBUILDCMD = if [ X"${MKSYMTBL_PROGRAM}" = X -o X"$${MAKE_SYMTABLE:-${ALWAYS_MAKE_SYMTABLE}}" = X ] ; then \ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@ $${BASEOBJS} $${LIBS0} ${LIBS}; \ -+ else \ -+ rm -f $@tmp0; \ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@tmp0 $${BASEOBJS} $${LIBS0} ${LIBS} || exit 1; \ -+ rm -f $@-symtbl.c $@-symtbl.o; \ -+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ -+ -o $@-symtbl.c $@tmp0 || exit 1; \ -+ $(MAKE) $@-symtbl.o || exit 1; \ -+ rm -f $@tmp1; \ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@tmp1 $${BASEOBJS} $@-symtbl.o $${LIBS0} ${NOSYMLIBS} || exit 1; \ -+ rm -f $@-symtbl.c $@-symtbl.o; \ -+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ -+ -o $@-symtbl.c $@tmp1 || exit 1; \ -+ $(MAKE) $@-symtbl.o || exit 1; \ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} ${LDFLAGS} \ -+ -o $@tmp2 $${BASEOBJS} $@-symtbl.o $${LIBS0} ${NOSYMLIBS}; \ -+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ -+ -o $@-symtbl2.c $@tmp2; \ -+ count=0; \ -+ until diff $@-symtbl.c $@-symtbl2.c > /dev/null ; \ -+ do \ -+ count=`expr $$count + 1` ; \ -+ test $$count = 42 && exit 1 ; \ -+ rm -f $@-symtbl.c $@-symtbl.o; \ -+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ -+ -o $@-symtbl.c $@tmp2 || exit 1; \ -+ $(MAKE) $@-symtbl.o || exit 1; \ -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${ALL_CFLAGS} \ -+ ${LDFLAGS} -o $@tmp2 $${BASEOBJS} $@-symtbl.o \ -+ $${LIBS0} ${NOSYMLIBS}; \ -+ ${MKSYMTBL_PROGRAM} ${top_srcdir}/util/mksymtbl.pl \ -+ -o $@-symtbl2.c $@tmp2; \ -+ done ; \ -+ mv $@tmp2 $@; \ -+ rm -f $@tmp0 $@tmp1 $@tmp2 $@-symtbl2.c; \ -+ fi -+ -+cleandir: distclean -+superclean: maintainer-clean -+ -+clean distclean maintainer-clean:: -+ rm -f *.o *.o *.lo *.la core *.core *-symtbl.c *tmp0 *tmp1 *tmp2 -+ rm -rf .depend .libs -+ -+distclean maintainer-clean:: -+ rm -f Makefile -+ -+depend: -+ @for i in ${ALL_SUBDIRS}; do \ -+ if [ "$$i" != "nulldir" -a -d $$i ]; then \ -+ echo "making depend in `pwd`/$$i"; \ -+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@) || exit 1; \ -+ fi; \ -+ done -+ @if [ X"${srcdir}" != X. ] ; then \ -+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \ -+ echo ${MKDEP} -vpath ${srcdir} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${MKDEP} -vpath ${srcdir} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ echo ${MKDEP} -vpath ${srcdir} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${MKDEP} -vpath ${srcdir} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${DEPENDEXTRA} \ -+ elif [ X"${SRCS}" != X ] ; then \ -+ echo ${MKDEP} -vpath ${srcdir} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${MKDEP} -vpath ${srcdir} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${DEPENDEXTRA} \ -+ elif [ X"${PSRCS}" != X ] ; then \ -+ echo ${MKDEP} -vpath ${srcdir} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${MKDEP} -vpath ${srcdir} -p ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${DEPENDEXTRA} \ -+ fi \ -+ else \ -+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \ -+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${MKDEP} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${DEPENDEXTRA} \ -+ elif [ X"${SRCS}" != X ] ; then \ -+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \ -+ ${DEPENDEXTRA} \ -+ elif [ X"${PSRCS}" != X ] ; then \ -+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${MKDEP} -p ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \ -+ ${DEPENDEXTRA} \ -+ fi \ -+ fi -+ -+FORCE: -+ -+### -+### Libraries -+### -+ -+AR = /usr/local/bin/ar -+ARFLAGS = cruv -+RANLIB = ranlib -+ -+### -+### Installation -+### -+ -+INSTALL = /usr/bin/install -c -+INSTALL_PROGRAM = ${INSTALL} -+LINK_PROGRAM = ln -s -+INSTALL_SCRIPT = ${INSTALL} -+INSTALL_DATA = ${INSTALL} -m 644 -+ -+### -+### Programs used when generating documentation. It's ok for these -+### not to exist when not generating documentation. -+### -+ -+XSLTPROC = xsltproc --novalid --xinclude --nonet -+PERL = /usr/local/bin/perl5 -+LATEX = latex -+PDFLATEX = pdflatex -+W3M = w3m -+ -+### -+### Script language program used to create internal symbol tables -+### -+MKSYMTBL_PROGRAM = /usr/local/bin/perl5 -+ -+### -+### Switch to create internal symbol table selectively -+### -+ALWAYS_MAKE_SYMTABLE = -+ -+### -+### DocBook -> HTML -+### DocBook -> man page -+### -+ -+.SUFFIXES: .docbook .html .1 .2 .3 .4 .5 .6 .7 .8 -+ -+.docbook.html: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-docbook-html.xsl $< -+ -+.docbook.1: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.2: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.3: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.4: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.5: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.6: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.7: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+.docbook.8: -+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $< -+ -+### -+### Python executable -+### -+.SUFFIXES: .py -+.py: -+ cp -f $< $@ -+ chmod +x $@ -+ -+ -+all: rpz -+ -+rpz: ${RPZOBJS} -+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${RPZOBJS} ${LIBS} -+ -+clean distclean:: -+ rm -f ${TARGETS} -+ -+# DO NOT DELETE THIS LINE -- mkdep uses it. -+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. -+ -+rpz.o: rpz.c /usr/home/vjs/isc/work/rpz3/config.h /usr/include/stdlib.h \ -+ /usr/include/sys/cdefs.h /usr/include/sys/_null.h \ -+ /usr/include/sys/_types.h /usr/include/machine/_types.h \ -+ /usr/include/stdio.h /usr/include/string.h /usr/include/strings.h -+ -+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY -diff -r -u bin/tests/system/rpz/clean.sh-orig bin/tests/system/rpz/clean.sh ---- bin/tests/system/rpz/clean.sh-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/clean.sh 2004-01-01 00:00:00.000000000 +0000 -@@ -19,7 +19,7 @@ - # Clean up after rpz tests. - - rm -f proto.* dsset-* random.data trusted.conf dig.out* nsupdate.tmp ns*/*tmp --rm -f ns*/*.key ns*/*.private ns2/tld2s.db ns2/bl.tld2.db -+rm -f ns*/*.key ns*/*.private ns2/tld2s.db - rm -f ns3/bl*.db ns*/*switch ns5/requests ns5/example.db ns5/bl.db ns5/*.perf - rm -f */named.memstats */named.run */named.stats */session.key - rm -f */*.jnl */*.core */*.pid -diff -r -u bin/tests/system/rpz/ns1/root.db-orig bin/tests/system/rpz/ns1/root.db ---- bin/tests/system/rpz/ns1/root.db-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns1/root.db 2004-01-01 00:00:00.000000000 +0000 -@@ -38,3 +38,6 @@ - ; performance test - tld5. NS ns.tld5. - ns.tld5. A 10.53.0.5 -+ -+; generate SERVFAIL -+servfail NS ns.tld2. -diff -r -u bin/tests/system/rpz/ns2/bl.tld2.db-orig bin/tests/system/rpz/ns2/bl.tld2.db ---- bin/tests/system/rpz/ns2/bl.tld2.db-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns2/bl.tld2.db 2004-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,27 @@ -+; Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+; $Id$ -+ -+ -+ -+; master for slave RPZ zone -+ -+$TTL 3600 -+@ SOA rpz.tld2. hostmaster.ns.tld2. ( 1 3600 1200 604800 60 ) -+ NS ns -+ns A 10.53.0.2 -+ A 10.53.0.3 -+ -+32.1.7.168.192.rpz-ip CNAME . -diff -r -u bin/tests/system/rpz/ns2/named.conf-orig bin/tests/system/rpz/ns2/named.conf ---- bin/tests/system/rpz/ns2/named.conf-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns2/named.conf 2004-01-01 00:00:00.000000000 +0000 -@@ -32,14 +32,6 @@ - notify no; - }; - --key rndc_key { -- secret "1234abcd8765"; -- algorithm hmac-sha256; --}; --controls { -- inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; }; --}; -- - include "../trusted.conf"; - zone "." { type hint; file "hints"; }; - -@@ -53,4 +45,4 @@ - - zone "tld2s." {type master; file "tld2s.db";}; - --zone "bl.tld2." {type master; file "bl.tld2.db"; notify yes; notify-delay 1;}; -+zone "bl.tld2." {type master; file "bl.tld2.db";}; -diff -r -u bin/tests/system/rpz/ns2/tld2.db-orig bin/tests/system/rpz/ns2/tld2.db ---- bin/tests/system/rpz/ns2/tld2.db-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns2/tld2.db 2004-01-01 00:00:00.000000000 +0000 -@@ -111,6 +111,9 @@ - A 192.168.5.2 - TXT "a5-1-2 tld2 text" - -+a5-2 A 192.168.5.2 -+ TXT "a5-2 tld2 text" -+ - a5-3 A 192.168.5.3 - TXT "a5-3 tld2 text" - -diff -r -u bin/tests/system/rpz/ns3/base.db-orig bin/tests/system/rpz/ns3/base.db ---- bin/tests/system/rpz/ns3/base.db-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns3/base.db 2004-01-01 00:00:00.000000000 +0000 -@@ -21,30 +21,7 @@ - ; Its contents are also changed with nsupdate - - --$TTL 120 -+$TTL 300 - @ SOA blx. hostmaster.ns.blx. ( 1 3600 1200 604800 60 ) -- NS ns --ns A 10.53.0.3 -+ NS ns.tld3. - --; Poke the radix tree a little. --128.1111.2222.3333.4444.5555.6666.7777.8888.rpz-ip CNAME . --128.1111.2222.3333.4444.5555.6666.zz.rpz-ip CNAME . --128.1111.2222.3333.4444.5555.zz.8888.rpz-ip CNAME . --128.1111.2222.3333.4444.zz.8888.rpz-ip CNAME . --128.zz.3333.4444.0.0.8888.rpz-ip CNAME . --128.zz.3333.4444.0.7777.8888.rpz-ip CNAME . --128.zz.3333.4444.0.8777.8888.rpz-ip CNAME . --127.zz.3333.4444.0.8777.8888.rpz-ip CNAME . -- -- --; regression testing for some old crashes --redirect A 127.0.0.1 --*.redirect A 127.0.0.1 --*.credirect CNAME google.com. -- -- --; names in the RPZ TLDs that some say should not be rewritten. --; This is not a bug, because any data leaked by writing 24.4.3.2.10.rpz-ip --; (or whatever) is available by publishing "foo A 10.2.3.4" and then --; resolving foo. --32.3.2.1.127.rpz-ip CNAME walled.invalid. -diff -r -u bin/tests/system/rpz/ns3/named.conf-orig bin/tests/system/rpz/ns3/named.conf ---- bin/tests/system/rpz/ns3/named.conf-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns3/named.conf 2004-01-01 00:00:00.000000000 +0000 -@@ -46,20 +46,24 @@ - zone "bl-cname" policy cname txt-only.tld2.; - zone "bl-wildcname" policy cname *.tld4.; - zone "bl-garden" policy cname a12.tld2.; -+ zone "bl-drop" policy drop; -+ zone "bl-tcp-only" policy tcp-only; - zone "bl.tld2"; -- } min-ns-dots 0; -+ } -+ min-ns-dots 0 -+ qname-wait-recurse yes -+ ; - }; - - key rndc_key { - secret "1234abcd8765"; -- algorithm hmac-md5; -+ algorithm hmac-sha256; - }; - controls { - inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; }; - }; - - --// include "../trusted.conf"; - zone "." { type hint; file "hints"; }; - - zone "bl." {type master; file "bl.db"; -@@ -84,9 +88,13 @@ - allow-update {any;};}; - zone "bl-garden." {type master; file "bl-garden.db"; - allow-update {any;};}; -+zone "bl-drop." {type master; file "bl-drop.db"; -+ allow-update {any;};}; -+zone "bl-tcp-only." {type master; file "bl-tcp-only.db"; -+ allow-update {any;};}; - - zone "bl.tld2." {type slave; file "bl.tld2.db"; masters {10.53.0.2;}; -- request-ixfr no; masterfile-format text;}; -+ masterfile-format text;}; - - zone "crash1.tld2" {type master; file "crash1";}; - zone "crash2.tld3." {type master; file "crash2";}; -diff -r -u bin/tests/system/rpz/ns5/named.args-orig bin/tests/system/rpz/ns5/named.args ---- bin/tests/system/rpz/ns5/named.args-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns5/named.args 2004-01-01 00:00:00.000000000 +0000 -@@ -1,3 +1,3 @@ - # run the performace test close to real life - ---c named.conf -g -+-c named.conf -gd3 -diff -r -u bin/tests/system/rpz/ns5/named.conf-orig bin/tests/system/rpz/ns5/named.conf ---- bin/tests/system/rpz/ns5/named.conf-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns5/named.conf 2004-01-01 00:00:00.000000000 +0000 -@@ -40,7 +40,7 @@ - - key rndc_key { - secret "1234abcd8765"; -- algorithm hmac-md5; -+ algorithm hmac-sha256; - }; - controls { - inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; -@@ -56,3 +56,20 @@ - zone "bl0." {type master; file "bl.db"; }; - zone "bl1." {type master; file "bl.db"; }; - zone "bl2." {type master; file "bl.db"; }; -+zone "bl3." {type master; file "bl.db"; }; -+zone "bl4." {type master; file "bl.db"; }; -+zone "bl5." {type master; file "bl.db"; }; -+zone "bl6." {type master; file "bl.db"; }; -+zone "bl7." {type master; file "bl.db"; }; -+zone "bl8." {type master; file "bl.db"; }; -+zone "bl9." {type master; file "bl.db"; }; -+zone "bl10." {type master; file "bl.db"; }; -+zone "bl11." {type master; file "bl.db"; }; -+zone "bl12." {type master; file "bl.db"; }; -+zone "bl13." {type master; file "bl.db"; }; -+zone "bl14." {type master; file "bl.db"; }; -+zone "bl15." {type master; file "bl.db"; }; -+zone "bl16." {type master; file "bl.db"; }; -+zone "bl17." {type master; file "bl.db"; }; -+zone "bl18." {type master; file "bl.db"; }; -+zone "bl19." {type master; file "bl.db"; }; -diff -r -u bin/tests/system/rpz/ns5/tld5.db-orig bin/tests/system/rpz/ns5/tld5.db ---- bin/tests/system/rpz/ns5/tld5.db-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/ns5/tld5.db 2004-01-01 00:00:00.000000000 +0000 -@@ -22,42 +22,10 @@ - NS ns1 - NS ns2 - NS ns3 -- NS ns4 -- NS ns5 -- NS ns6 -- NS ns7 -- NS ns8 -- NS ns9 -- NS ns10 -- NS ns11 -- NS ns12 -- NS ns13 -- NS ns14 -- NS ns15 -- NS ns16 -- NS ns17 -- NS ns18 -- NS ns19 - ns A 10.53.0.5 - ns1 A 10.53.0.5 - ns2 A 10.53.0.5 - ns3 A 10.53.0.5 --ns4 A 10.53.0.5 --ns5 A 10.53.0.5 --ns6 A 10.53.0.5 --ns7 A 10.53.0.5 --ns8 A 10.53.0.5 --ns9 A 10.53.0.5 --ns10 A 10.53.0.5 --ns11 A 10.53.0.5 --ns12 A 10.53.0.5 --ns13 A 10.53.0.5 --ns14 A 10.53.0.5 --ns15 A 10.53.0.5 --ns16 A 10.53.0.5 --ns17 A 10.53.0.5 --ns18 A 10.53.0.5 --ns19 A 10.53.0.5 - - - $ORIGIN example.tld5. -diff -r -u bin/tests/system/rpz/setup.sh-orig bin/tests/system/rpz/setup.sh ---- bin/tests/system/rpz/setup.sh-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/setup.sh 2004-01-01 00:00:00.000000000 +0000 -@@ -26,11 +26,13 @@ - - sh clean.sh - --# set up test policy zones. bl-2 is used to check competing zones. --# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden} --# are used to check policy overrides in named.conf. --# NO-OP is an obsolete synonym for PASSHTRU --for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden; do -+# set up test policy zones. -+# bl is the main test zone -+# bl-2 is used to check competing zones. -+# bl-{given,disabled,passthru,no-data,nxdomain,cname,wildcard,garden, -+# drop,tcp-only} are used to check policy overrides in named.conf. -+# NO-OP is an obsolete synonym for PASSHTRU -+for NM in '' -2 -given -disabled -passthru -no-op -nodata -nxdomain -cname -wildcname -garden -drop -tcp-only; do - sed -e "/SOA/s/blx/bl$NM/g" ns3/base.db >ns3/bl$NM.db - done - -@@ -48,18 +50,22 @@ - signzone ns2 tld2s. base-tld2s.db tld2s.db - - --# Performance checks. -+# Performance and a few other checks. - cat <ns5/rpz-switch - response-policy { -- zone "bl0"; zone "bl1"; zone "bl2"; -+ zone "bl0"; zone "bl1"; zone "bl2"; zone "bl3"; zone "bl4"; -+ zone "bl5"; zone "bl6"; zone "bl7"; zone "bl8"; zone "bl9"; -+ zone "bl10"; zone "bl11"; zone "bl12"; zone "bl13"; zone "bl14"; -+ zone "bl15"; zone "bl16"; zone "bl17"; zone "bl18"; zone "bl19"; - } recursive-only no -- max-policy-ttl 90 -- # min-ns-dots 0 -- break-dnssec yes; -+ max-policy-ttl 90 -+ break-dnssec yes -+ qname-wait-recurse no -+ ; - EOF - - cat <ns5/example.db --\$TTL 120 -+\$TTL 300 - @ SOA . hostmaster.ns.example.tld5. ( 1 3600 1200 604800 60 ) - NS ns - NS ns1 -@@ -68,15 +74,16 @@ - EOF - - cat <ns5/bl.db --\$TTL 120 -+\$TTL 300 - @ SOA . hostmaster.ns.blperf. ( 1 3600 1200 604800 60 ) -- NS ns --ns A 10.53.0.5 -+ NS ns.tld5. - --; used only in failure for "recursive-only no" in #8 test5 --a3-5.tld2 CNAME *. -+; for "qname-wait-recurse no" in #35 test1 -+x.servfail A 35.35.35.35 -+; for "recursive-only no" in #8 test5 -+a3-5.tld2 CNAME . - ; for "break-dnssec" in #9 & #10 test5 --a3-5.tld2s CNAME *. -+a3-5.tld2s CNAME . - ; for "max-policy-ttl 90" in #17 test5 - a3-17.tld2 500 A 17.17.17.17 - -@@ -85,8 +92,7 @@ - EOF - - if test -n "$QPERF"; then -- # do not build the full zones if we will not use them to avoid the long -- # time otherwise required to shut down the server -+ # Do not build the full zones if we will not use them. - $PERL -e 'for ($val = 1; $val <= 65535; ++$val) { - printf("host-%05d\tA 192.168.%d.%d\n", $val, $val/256, $val%256); - }' >>ns5/example.db -@@ -110,5 +116,3 @@ - printf("host-%05d.example.tld5 A\n", $val); - $val = ($val * 9 + 32771) % 65536; - }' >ns5/requests -- --cp ns2/bl.tld2.db.in ns2/bl.tld2.db -diff -r -u bin/tests/system/rpz/test1-orig bin/tests/system/rpz/test1 ---- bin/tests/system/rpz/test1-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/test1 2004-01-01 00:00:00.000000000 +0000 -@@ -24,13 +24,13 @@ - ; QNAME tests - - ; NXDOMAIN --; 2, 20, 25 -+; 2, 25 - update add a0-1.tld2.bl. 300 CNAME . - ; NODATA --; 3, 21 -+; 3 - update add a3-1.tld2.bl. 300 CNAME *. - ; and no assert-botch --; 4, 5, 22, 23 -+; 4, 5 - update add a3-2.tld2.bl. 300 DNAME example.com. - ; - ; NXDOMAIN for a4-2-cname.tld2 via its target a4-2.tld2. -@@ -77,6 +77,14 @@ - ; 19 - update add a4-6.tld2.bl. 300 CNAME . - update add a4-6-cname.tld2.bl. 300 A 127.0.0.17 -+; no change instead of NXDOMAIN because +norecurse -+; 20 -+update add a5-2.tld2.bl. 300 CNAME . -+; no change instead of NODATA because +norecurse -+; 21 -+update add a5-3.tld2.bl. 300 CNAME *. -+; 22, 23 -+update add a5-4.tld2.bl. 300 DNAME example.com. - ; - ; assert in rbtdb.c - ; 24 -@@ -84,4 +92,10 @@ - ; DO=1 without signatures, DO=0 with signatures are rewritten - ; 26 - 27 - update add a0-1.tld2s.bl. 300 CNAME . -+; 32 -+update add a3-8.tld2.bl. 300 CNAME rpz-drop. -+; 33 -+update add a3-9.tld2.bl. 300 CNAME rpz-tcp-only. -+; 34 qname-wait-recurse yes -+update add x.servfail.bl. 300 A 127.0.0.34 - send -diff -r -u bin/tests/system/rpz/test2-orig bin/tests/system/rpz/test2 ---- bin/tests/system/rpz/test2-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/test2 2004-01-01 00:00:00.000000000 +0000 -@@ -58,7 +58,7 @@ - send - - ; prefer QNAME to IP for a5-4.tld2 --; 13 -+; 13, 14 - update add 32.4.5.168.192.rpz-ip.bl 300 CNAME a12.tld2. - update add a5-4.tld2.bl 300 CNAME a14.tld4. - ; -@@ -72,3 +72,8 @@ - send - update add c2.crash2.tld3.bl-2 300 A 127.0.0.16 - send -+ -+; client-IP address trigger -+; 17 -+update add 32.1.0.53.10.rpz-client-ip.bl 300 A 127.0.0.17 -+send -diff -r -u bin/tests/system/rpz/test5-orig bin/tests/system/rpz/test5 ---- bin/tests/system/rpz/test5-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/test5 2004-01-01 00:00:00.000000000 +0000 -@@ -35,10 +35,8 @@ - ; 4 - update add a3-4.tld2.bl-disabled. 300 A 127.0.0.4 - send --; 5 - 8 -+; 5 - 7 - update add a3-5.tld2.bl-nodata. 300 A 127.0.0.5 --; 9 - 10 --update add a3-5.tld2s.bl-nodata. 300 A 127.0.0.9 - send - ; 11 - update add a3-6.tld2.bl-nxdomain. 300 A 127.0.0.11 -@@ -57,3 +55,9 @@ - ; 16 - update add a3-16.tld2.bl. 300 A 127.0.0.16 - send -+; 18 -+update add a3-18.tld2.bl-drop. 300 A 127.0.0.18 -+send -+; 19 -+update add a3-19.tld2.bl-tcp-only. 300 A 127.0.0.19 -+send -diff -r -u bin/tests/system/rpz/test6-orig bin/tests/system/rpz/test6 ---- bin/tests/system/rpz/test6-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/test6 2004-01-01 00:00:00.000000000 +0000 -@@ -0,0 +1,40 @@ -+; Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC") -+; -+; Permission to use, copy, modify, and/or distribute this software for any -+; purpose with or without fee is hereby granted, provided that the above -+; copyright notice and this permission notice appear in all copies. -+; -+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -+; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -+; PERFORMANCE OF THIS SOFTWARE. -+ -+ -+ -+; Use comment lines instead of blank lines to combine update requests into -+; single requests -+; Separate update requests for distinct TLDs with blank lines or 'send' -+; End the file with a blank line or 'send' -+ -+server 10.53.0.3 5300 -+ -+; Poke the radix tree a little. -+update add 128.1111.2222.3333.4444.5555.6666.7777.8888.rpz-ip.bl. 300 CNAME . -+update add 128.1111.2222.3333.4444.5555.6666.zz.rpz-ip.bl. 300 CNAME . -+update add 128.1111.2222.3333.4444.5555.zz.8888.rpz-ip.bl. 300 CNAME . -+update add 128.1111.2222.3333.4444.zz.8888.rpz-ip.bl. 300 CNAME . -+update add 128.zz.3333.4444.0.0.8888.rpz-ip.bl. 300 CNAME . -+update add 128.zz.3333.4444.0.7777.8888.rpz-ip.bl. 300 CNAME . -+update add 128.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME . -+update add 127.zz.3333.4444.0.8777.8888.rpz-ip.bl. 300 CNAME . -+; -+; -+; regression testing for some old crashes -+update add redirect.bl. 300 A 127.0.0.1 -+update add *.redirect.bl. 300 A 127.0.0.1 -+update add *.credirect.bl. 300 CNAME google.com. -+; -+send -diff -r -u bin/tests/system/rpz/tests.sh-orig bin/tests/system/rpz/tests.sh ---- bin/tests/system/rpz/tests.sh-orig 2004-01-01 00:00:00.000000000 +0000 -+++ bin/tests/system/rpz/tests.sh 2004-01-01 00:00:00.000000000 +0000 -@@ -21,15 +21,15 @@ - . $SYSTEMTESTTOP/conf.sh - - ns=10.53.0 --ns1=$ns.1 # root, defining the others --ns2=$ns.2 # server whose answers are rewritten --ns3=$ns.3 # resolve that does the rewriting --ns4=$ns.4 # another server that is rewritten --ns5=$ns.5 # check performance with this server -+ns1=$ns.1 # root, defining the others -+ns2=$ns.2 # authoritative server whose records are rewritten -+ns3=$ns.3 # main rewriting resolver -+ns4=$ns.4 # another authoritative server that is rewritten -+ns5=$ns.5 # another rewriting resolver - - HAVE_CORE= - SAVE_RESULTS= --NS3_STATS=47 -+ - - USAGE="$0: [-x]" - while getopts "x" c; do -@@ -57,13 +57,16 @@ - RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s" - - digcmd () { -+ if test "$1" = TCP; then -+ shift -+ fi - # Default to +noauth and @$ns3 - # Also default to -bX where X is the @value so that OS X will choose -- # the right IP source address. -- digcmd_args=`echo "+noadd +time=1 +tries=1 -p 5300 $*" | \ -- sed -e "/@/!s/.*/& @$ns3/" \ -- -e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \ -- -e '/+n?o?auth/!s/.*/+noauth &/'` -+ # the right IP source address. -+ digcmd_args=`echo "+noadd +time=1 +tries=1 -p 5300 $*" | \ -+ sed -e "/@/!s/.*/& @$ns3/" \ -+ -e '/-b/!s/@\([^ ]*\)/@\1 -b\1/' \ -+ -e '/+n?o?auth/!s/.*/+noauth &/'` - #echo I:dig $digcmd_args 1>&2 - $DIG $digcmd_args - } -@@ -89,10 +92,13 @@ - # (re)load the reponse policy zones with the rules in the file $TEST_FILE - load_db () { - if test -n "$TEST_FILE"; then -- $NSUPDATE -v $TEST_FILE || { -+ if $NSUPDATE -v $TEST_FILE; then : -+ $RNDCCMD $ns3 sync -+ else - echo "I:failed to update policy zone with $TEST_FILE" -+ $RNDCCMD $ns3 sync - exit 1 -- } -+ fi - fi - } - -@@ -135,16 +141,20 @@ - return 1 - } - --# check that statistics for $1 in $2 = $3 - ckstats () { -- rm -f $2/named.stats -- $RNDCCMD $1 stats -- CNT=`sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \ -- $2/named.stats` -- CNT=`expr 0$CNT + 0` -- if test "$CNT" -ne $3; then -- setret "I:wrong $2 statistics of $CNT instead of $3" -+ HOST=$1 -+ LABEL="$2" -+ NSDIR="$3" -+ EXPECTED="$4" -+ $RNDCCMD $HOST stats -+ NEW_CNT=0`sed -n -e 's/[ ]*\([0-9]*\).response policy.*/\1/p' \ -+ $NSDIR/named.stats | tail -1` -+ eval "OLD_CNT=0\$${NSDIR}_CNT" -+ GOT=`expr $NEW_CNT - $OLD_CNT` -+ if test "$GOT" -ne "$EXPECTED"; then -+ setret "I:wrong $LABEL $NSDIR statistics of $GOT instead of $EXPECTED" - fi -+ eval "${NSDIR}_CNT=$NEW_CNT" - } - - # $1=message $2=optional test file name -@@ -181,6 +191,12 @@ - ckresult () { - #ckalive "$1" "I:server crashed by 'dig $1'" || return 1 - if $PERL $SYSTEMTESTTOP/digcomp.pl $DIGNM $2 >/dev/null; then -+ NEED_TCP=`echo "$1" | sed -n -e 's/[Tt][Cc][Pp].*/TCP/p'` -+ RESULT_TCP=`sed -n -e 's/.*Truncated, retrying in TCP.*/TCP/p' $DIGNM` -+ if test "$NEED_TCP" != "$RESULT_TCP"; then -+ setret "I:'dig $1' wrong; no or unexpected truncation in $DIGNM" -+ return 1 -+ fi - clean_result ${DIGNM}* - return 0 - fi -@@ -237,12 +253,14 @@ - clean_result ${DIGNM}* - } - --# check that a response is not rewritten --# $1=target domain $2=optional query type -+# Check that a response is not rewritten -+# Use $ns1 instead of the authority for most test domains, $ns2 to prevent -+# spurious differences for `dig +norecurse` -+# $1=optional "TCP" remaining args for dig - nochange () { - make_dignm - digcmd $* >$DIGNM -- digcmd $* @$ns2 >${DIGNM}_OK -+ digcmd $* @$ns1 >${DIGNM}_OK - ckresult "$*" ${DIGNM}_OK && clean_result ${DIGNM}_OK - } - -@@ -254,6 +272,20 @@ - ckresult "$*" ${DIGNM}_OK - } - -+# check dropped response -+DROPPED='^;; connection timed out; no servers could be reached' -+drop () { -+ make_dignm -+ digcmd $* >$DIGNM -+ if grep "$DROPPED" $DIGNM >/dev/null; then -+ clean_result ${DIGNM}* -+ return 0 -+ fi -+ setret "I:'dig $1' wrong; response in $DIGNM" -+ return 1 -+} -+ -+ - # make prototype files to check against rewritten results - digcmd nonexistent @$ns2 >proto.nxdomain - digcmd txt-only.tld2 @$ns2 >proto.nodata -@@ -281,19 +313,27 @@ - addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME - addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain - addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain --nochange a0-1.tld2 +norecurse # 20 check that RD=1 is required --nochange a3-1.tld2 +norecurse # 21 --nochange a3-2.tld2 +norecurse # 22 --nochange sub.a3-2.tld2 +norecurse # 23 -+nochange a5-2.tld2 +norecurse # 20 check that RD=1 is required -+nochange a5-3.tld2 +norecurse # 21 -+nochange a5-4.tld2 +norecurse # 22 -+nochange sub.a5-4.tld2 +norecurse # 23 - nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c - nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures --nxdomain a0-1.tld2s # 26 simple DO=0 with signatures -+nxdomain a0-1.tld2s +nodnssec # 26 simple DO=0 with signatures - nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures - nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain - nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain --nochange a0-1.tld2s srv +auth +dnssec # 30 no write for +DNSSEC and no record --nxdomain a0-1.tld2s srv # 31 -+nochange a0-1.tld2s srv +auth +dnssec # 30 no write for DNSSEC and no record -+nxdomain a0-1.tld2s srv +nodnssec # 31 -+drop a3-8.tld2 any # 32 drop -+nochange tcp a3-9.tld2 # 33 tcp-only -+here x.servfail <<'EOF' # 34 qname-wait-recurse yes -+ ;; status: SERVFAIL, x -+EOF -+addr 35.35.35.35 "x.servfail @$ns5" # 35 qname-wait-recurse no - end_group -+ckstats $ns3 test1 ns3 22 -+ckstats $ns5 test1 ns5 1 - - start_group "IP rewrites" test2 - nodata a3-1.tld2 # 1 NODATA -@@ -308,35 +348,14 @@ - nochange a4-1-aaaa.tld2 -taaaa # 10 - addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address - addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone --addr 14.14.14.14 a5-4.tld2 # 13 prefer QNAME to IP --nochange a5-4.tld2 +norecurse # 14 check that RD=1 is required -+nochange a5-4.tld2 +norecurse # 13 check that RD=1 is required for #14 -+addr 14.14.14.14 a5-4.tld2 # 14 prefer QNAME to IP - nochange a4-4.tld2 # 15 PASSTHRU - nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c --ckstats $ns3 ns3 29 --nxdomain a7-1.tld2 # 17 slave policy zone (RT34450) --cp ns2/blv2.tld2.db.in ns2/bl.tld2.db --$RNDCCMD 10.53.0.2 reload bl.tld2 --goodsoa="rpz.tld2. hostmaster.ns.tld2. 2 3600 1200 604800 60" --for i in 0 1 2 3 4 5 6 7 8 9 10 --do -- soa=`$DIG -p 5300 +short soa bl.tld2 @10.53.0.3 -b10.53.0.3` -- test "$soa" = "$goodsoa" && break -- sleep 1 --done --nochange a7-1.tld2 # 18 PASSTHRU --sleep 1 # ensure that a clock tick has occured so that the reload takes effect --cp ns2/blv3.tld2.db.in ns2/bl.tld2.db --goodsoa="rpz.tld2. hostmaster.ns.tld2. 3 3600 1200 604800 60" --$RNDCCMD 10.53.0.2 reload bl.tld2 --for i in 0 1 2 3 4 5 6 7 8 9 10 --do -- soa=`$DIG -p 5300 +short soa bl.tld2 @10.53.0.3 -b10.53.0.3` -- test "$soa" = "$goodsoa" && break -- sleep 1 --done --nxdomain a7-1.tld2 # 19 slave policy zone (RT34450) --ckstats $ns3 ns3 31 -+addr 127.0.0.17 "a4-4.tld2 -b $ns1" # 17 client-IP address trigger -+nxdomain a7-1.tld2 # 18 slave policy zone (RT34450) - end_group -+ckstats $ns3 test2 ns3 11 - - # check that IP addresses for previous group were deleted from the radix tree - start_group "radix tree deletions" -@@ -352,6 +371,7 @@ - nochange a4-1-aaaa.tld2 -tAAAA - nochange a5-1-2.tld2 - end_group -+ckstats $ns3 'radix tree deletions' ns3 0 - - if ./rpz nsdname; then - # these tests assume "min-ns-dots 0" -@@ -369,7 +389,7 @@ - addr 127.0.0.2 a3-1.subsub.sub3.tld2 - nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash - end_group -- NS3_STATS=`expr $NS3_STATS + 7` -+ ckstats $ns3 test3 ns3 7 - else - echo "I:NSDNAME not checked; named configured with --disable-rpz-nsdname" - fi -@@ -383,15 +403,15 @@ - nochange a3-1.tld4 # 4 different NS IP address - end_group - --# start_group "walled garden NSIP rewrites" test4a --# addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2 --# addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2 --# here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2 --# ;; status: NOERROR, x --# a3-1.tld2. x IN TXT "NSIP walled garden" --#EOF --# end_group -- NS3_STATS=`expr $NS3_STATS + 1` -+ start_group "walled garden NSIP rewrites" test4a -+ addr 41.41.41.41 a3-1.tld2 # 1 walled garden for all of tld2 -+ addr 2041::41 'a3-1.tld2 AAAA' # 2 walled garden for all of tld2 -+ here a3-1.tld2 TXT <<'EOF' # 3 text message for all of tld2 -+ ;; status: NOERROR, x -+ a3-1.tld2. x IN TXT "NSIP walled garden" -+EOF -+ end_group -+ ckstats $ns3 test4 ns3 4 - else - echo "I:NSIP not checked; named configured with --disable-rpz-nsip" - fi -@@ -403,12 +423,12 @@ - nochange a3-2.tld2 # 2 bl-passthru - nochange a3-3.tld2 # 3 bl-no-op obsolete for passthru - nochange a3-4.tld2 # 4 bl-disabled --nodata a3-5.tld2 # 5 bl-nodata --nodata a3-5.tld2 +norecurse # 6 bl-nodata recursive-only no --nodata a3-5.tld2 # 7 bl-nodata --nodata a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata recursive-only no --nodata a3-5.tld2s @$ns5 # 9 bl-nodata --nodata a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata break-dnssec -+nodata a3-5.tld2 # 5 bl-nodata zone recursive-only no -+nodata a3-5.tld2 +norecurse # 6 bl-nodata zone recursive-only no -+nodata a3-5.tld2 # 7 bl-nodata not needed -+nxdomain a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata global recursive-only no -+nxdomain a3-5.tld2s @$ns5 # 9 bl-nodata global break-dnssec -+nxdomain a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata global break-dnssec - nxdomain a3-6.tld2 # 11 bl-nxdomain - here a3-7.tld2 -tany <<'EOF' - ;; status: NOERROR, x -@@ -420,10 +440,15 @@ - addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2 - addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100 - addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90 -+drop a3-18.tld2 any # 18 bl-drop -+nxdomain TCP a3-19.tld2 # 19 bl-tcp-only - end_group -+ckstats $ns3 test5 ns3 12 -+ckstats $ns5 test5 ns5 4 -+ - - # check that miscellaneous bugs are still absent --start_group "crashes" -+start_group "crashes" test6 - for Q in RRSIG SIG ANY 'ANY +dnssec'; do - nocrash a3-1.tld2 -t$Q - nocrash a3-2.tld2 -t$Q -@@ -437,6 +462,8 @@ - # resolving foo. - # nxdomain 32.3.2.1.127.rpz-ip - end_group -+ckstats $ns3 bugs ns3 8 -+ - - - # superficial test for major performance bugs -@@ -449,6 +476,7 @@ - $QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p 5300 >/dev/null - comment "before real test $1" - PFILE="ns5/$2.perf" -+ $RNDCCMD $ns5 notrace - $QPERF -c -1 -l30 -d ns5/requests -s $ns5 -p 5300 >$PFILE - comment "after test $1" - X=`sed -n -e 's/.*Returned *\([^ ]*:\) *\([0-9]*\) .*/\1\2/p' $PFILE \ -@@ -463,17 +491,17 @@ - } - - # get qps with rpz -- perf 'with rpz' rpz 'NOERROR:2900 NXDOMAIN:100 ' -+ perf 'with RPZ' rpz 'NOERROR:2900 NXDOMAIN:100 ' - RPZ=`trim rpz` - - # turn off rpz and measure qps again -- echo "# rpz off" >ns5/rpz-switch -+ echo "# RPZ off" >ns5/rpz-switch - RNDCCMD_OUT=`$RNDCCMD $ns5 reload` -- perf 'without rpz' norpz 'NOERROR:3000 ' -+ perf 'without RPZ' norpz 'NOERROR:3000 ' - NORPZ=`trim norpz` - - PERCENT=`expr \( "$RPZ" \* 100 + \( $NORPZ / 2 \) \) / $NORPZ` -- echo "I:$RPZ qps with rpz is $PERCENT% of $NORPZ qps without rpz" -+ echo "I:$RPZ qps with RPZ is $PERCENT% of $NORPZ qps without RPZ" - - MIN_PERCENT=30 - if test "$PERCENT" -lt $MIN_PERCENT; then -@@ -484,13 +512,12 @@ - setret "I:$RPZ qps with RPZ or $PERCENT% of $NORPZ qps without RPZ is too high" - fi - -- ckstats $ns5 ns5 203 -+ ckstats $ns5 performance ns5 200 - - else - echo "I:performance not checked; queryperf not available" - fi - --ckstats $ns3 ns3 57 - - # restart the main test RPZ server to see if that creates a core file - if test -z "$HAVE_CORE"; then -diff -r -u doc/arm/Bv9ARM-book.xml-orig doc/arm/Bv9ARM-book.xml ---- doc/arm/Bv9ARM-book.xml-orig 2004-01-01 00:00:00.000000000 +0000 -+++ doc/arm/Bv9ARM-book.xml 2004-01-01 00:00:00.000000000 +0000 -@@ -4873,7 +4873,7 @@ - min-table-size number ; - } ; - response-policy { zone_name -- policy given | disabled | passthru | nxdomain | nodata | cname domain -+ policy given | disabled | passthru | drop | nxdomain | nodata | cname domain - recursive-only yes_or_no max-policy-ttl number ; - } recursive-only yes_or_no max-policy-ttl number - break-dnssec yes_or_no min-ns-dots number ; -@@ -9167,77 +9167,122 @@ - Response policy zones are named in the - response-policy option for the view or among the - global options if there is no response-policy option for the view. -- RPZs are ordinary DNS zones containing RRsets -+ Response policy zones are ordinary DNS zones containing RRsets - that can be queried normally if allowed. - It is usually best to restrict those queries with something like - allow-query { localhost; };. - - - -- Four policy triggers are encoded in RPZ records, QNAME, IP, NSIP, -- and NSDNAME. -- QNAME RPZ records triggered by query names of requests and targets -- of CNAME records resolved to generate the response. -- The owner name of a QNAME RPZ record is the query name relativized -- to the RPZ. -- -+ Five policy triggers can be encoded in RPZ records. -+ -+ -+ RPZ-CLIENT-IP -+ -+ -+ IP records are triggered by the IP address of the -+ DNS client. -+ Client IP address triggers are encoded in records that have -+ owner names that are subdomains of -+ rpz-client-ip relativized to the -+ policy zone origin name -+ and encode an address or address block. -+ IPv4 addresses are represented as -+ prefixlength.B4.B3.B2.B1.rpz-ip. -+ The IPv4 prefix length must be between 1 and 32. -+ All four bytes, B4, B3, B2, and B1, must be present. -+ B4 is the decimal value of the least significant byte of the -+ IPv4 address as in IN-ADDR.ARPA. -+ - -- -- The second kind of RPZ trigger is an IP address in an A and AAAA -- record in the ANSWER section of a response. -- IP address triggers are encoded in records that have owner names -- that are subdomains of rpz-ip relativized -- to the RPZ origin name and encode an IP address or address block. -- IPv4 trigger addresses are represented as -- prefixlength.B4.B3.B2.B1.rpz-ip. -- The prefix length must be between 1 and 32. -- All four bytes, B4, B3, B2, and B1, must be present. -- B4 is the decimal value of the least significant byte of the -- IPv4 address as in IN-ADDR.ARPA. -- IPv6 addresses are encoded in a format similar to the standard -- IPv6 text representation, -- prefixlength.W8.W7.W6.W5.W4.W3.W2.W1.rpz-ip. -- Each of W8,...,W1 is a one to four digit hexadecimal number -- representing 16 bits of the IPv6 address as in the standard text -- representation of IPv6 addresses, but reversed as in IN-ADDR.ARPA. -- All 8 words must be present except when consecutive -- zero words are replaced with .zz. -- analogous to double colons (::) in standard IPv6 text encodings. -- The prefix length must be between 1 and 128. -- -+ -+ IPv6 addresses are encoded in a format similar -+ to the standard IPv6 text representation, -+ prefixlength.W8.W7.W6.W5.W4.W3.W2.W1.rpz-ip. -+ Each of W8,...,W1 is a one to four digit hexadecimal number -+ representing 16 bits of the IPv6 address as in the standard -+ text representation of IPv6 addresses, -+ but reversed as in IN-ADDR.ARPA. -+ All 8 words must be present except when one set of consecutive -+ zero words is replaced with .zz. -+ analogous to double colons (::) in standard IPv6 text -+ encodings. -+ The IPv6 prefix length must be between 64 and 128. -+ -+ -+ - -- -- NSDNAME triggers match names of authoritative servers -- for the query name, a parent of the query name, a CNAME for -- query name, or a parent of a CNAME. -- They are encoded as subdomains of -- rpz-nsdomain relativized -- to the RPZ origin name. -- NSIP triggers match IP addresses in A and -- AAAA RRsets for domains that can be checked against NSDNAME -- policy records. -- NSIP triggers are encoded like IP triggers except as subdomains of -- rpz-nsip. -- NSDNAME and NSIP triggers are checked only for names with at -- least min-ns-dots dots. -- The default value of min-ns-dots is 1 to -- exclude top level domains. -- -+ -+ QNAME -+ -+ -+ QNAME policy records are triggered by query names of -+ requests and targets of CNAME records resolved to generate -+ the response. -+ The owner name of a QNAME policy record is -+ the query name relativized to the policy zone. -+ -+ -+ -+ -+ -+ RPZ-IP -+ -+ -+ IP triggers are IP addresses in an -+ A or AAAA record in the ANSWER section of a response. -+ They are encoded like client-IP triggers except as -+ subdomains of rpz-ip. -+ -+ -+ -+ -+ -+ RPZ-NSDNAME -+ -+ -+ NSDNAME triggers match names of authoritative servers -+ for the query name, a parent of the query name, a CNAME for -+ query name, or a parent of a CNAME. -+ They are encoded as subdomains of -+ rpz-nsdname relativized -+ to the RPZ origin name. -+ NSIP triggers match IP addresses in A and -+ AAAA RRsets for domains that can be checked against NSDNAME -+ policy records. -+ -+ -+ -+ -+ -+ RPZ-NSIP -+ -+ -+ NSIP triggers are encoded like IP triggers except as -+ subdomains of rpz-nsip. -+ NSDNAME and NSIP triggers are checked only for names with at -+ least min-ns-dots dots. -+ The default value of min-ns-dots is 1 to -+ exclude top level domains. -+ -+ -+ -+ - - -- The query response is checked against all RPZs, so -- two or more policy records can be triggered by a response. -- Because DNS responses can be rewritten according to at most one -+ The query response is checked against all response policy zones, -+ so two or more policy records can be triggered by a response. -+ Because DNS responses are rewritten according to at most one - policy record, a single record encoding an action (other than - DISABLED actions) must be chosen. -- Triggers or the records that encode them are chosen in -- the following order: -+ Triggers or the records that encode them are chosen for the -+ rewriting in the following order: - - Choose the triggered record in the zone that appears -- first in the response-policy option. -+ first in the response-policy option. - -- Prefer QNAME to IP to NSDNAME to NSIP triggers -- in a single zone. -+ Prefer CLIENT-IP to QNAME to IP to NSDNAME to NSIP -+ triggers in a single zone. - - Among NSDNAME triggers, prefer the - trigger that matches the smallest name under the DNSSEC ordering. -@@ -9256,83 +9301,168 @@ - When the processing of a response is restarted to resolve - DNAME or CNAME records and a policy record set has - not been triggered, -- all RPZs are again consulted for the DNAME or CNAME names -- and addresses. -+ all response policy zones are again consulted for the -+ DNAME or CNAME names and addresses. - - - -- RPZ record sets are sets of any types of DNS record except -- DNAME or DNSSEC that encode actions or responses to queries. -- -- The NXDOMAIN response is encoded -- by a CNAME whose target is the root domain (.) -- -- A CNAME whose target is the wildcard top-level -- domain (*.) specifies the NODATA action, -- which rewrites the response to NODATA or ANCOUNT=1. -- -- The Local Data action is -- represented by a set ordinary DNS records that are used -- to answer queries. Queries for record types not the -- set are answered with NODATA. -- -- A special form of local data is a CNAME whose target is a -- wildcard such as *.example.com. -- It is used as if were an ordinary CNAME after the astrisk (*) -- has been replaced with the query name. -- The purpose for this special form is query logging in the -- walled garden's authority DNS server. -- -- The PASSTHRU policy is specified -- by a CNAME whose target is rpz-passthru. -- It causes the response to not be rewritten -- and is most often used to "poke holes" in policies for -- CIDR blocks. -- (A CNAME whose target is the variable part of its owner name -- is an obsolete specification of the PASSTHRU policy.) -- -- -+ RPZ record sets are any types of DNS record except -+ DNAME or DNSSEC that encode actions or responses to -+ individual queries. -+ Any of the policies can be used with any of the triggers. -+ For example, while the TCP-only policy is -+ commonly used with client-IP triggers, -+ it cn be used with any type of trigger to force the use of -+ TCP for responses with owner names in a zone. -+ -+ -+ PASSTHRU -+ -+ -+ The whitelist policy is specified -+ by a CNAME whose target is rpz-passthru. -+ It causes the response to not be rewritten -+ and is most often used to "poke holes" in policies for -+ CIDR blocks. -+ -+ -+ -+ -+ -+ DROP -+ -+ -+ The blacklist policy is specified -+ by a CNAME whose target is rpz-drop. -+ It causes the response to be discarded. -+ Nothing is sent to the DNS client. -+ -+ -+ -+ -+ -+ TCP-Only -+ -+ -+ The "slip" policy is specified -+ by a CNAME whose target is rpz-tcp-only. -+ It changes UDP responses to short, truncated DNS responses -+ that require the DNS client to try again with TCP. -+ It is used to mitigate distributed DNS reflection attacks. -+ -+ -+ -+ -+ -+ NXDOMAIN -+ -+ -+ The domain undefined response is encoded -+ by a CNAME whose target is the root domain (.) -+ -+ -+ -+ -+ -+ NODATA -+ -+ -+ The empty set of resource records is specified by -+ CNAME whose target is the wildcard top-level -+ domain (*.). -+ It rewrites the response to NODATA or ANCOUNT=1. -+ -+ -+ -+ -+ -+ Local Data -+ -+ -+ A set of ordinary DNS records can be used to answer queries. -+ Queries for record types not the set are answered with -+ NODATA. -+ -+ -+ -+ A special form of local data is a CNAME whose target is a -+ wildcard such as *.example.com. -+ It is used as if were an ordinary CNAME after the astrisk (*) -+ has been replaced with the query name. -+ The purpose for this special form is query logging in the -+ walled garden's authority DNS server. -+ -+ -+ -+ - - - -- The actions specified in an RPZ can be overridden with a -- policy clause in the -+ All of the actions specified in all of the individual records -+ in a policy zone -+ can be overridden with a policy clause in the - response-policy option. -- An organization using an RPZ provided by another organization might -- use this mechanism to redirect domains to its own walled garden. -- -- GIVEN says "do not override but -- perform the action specified in the zone." -- -- DISABLED causes policy records to do -- nothing but log what they might have done. -- The response to the DNS query will be written according to -- any triggered policy records that are not disabled. -- Disabled policy zones should appear first, -- because they will often not be logged -- if a higher precedence trigger is found first. -- -- PASSTHRU causes all policy records -- to act as if they were CNAME records with targets the variable -- part of their owner name. They protect the response from -- being changed. -- -- NXDOMAIN causes all RPZ records -- to specify NXDOMAIN policies. -- -- NODATA overrides with the -- NODATA policy -- -- CNAME domain causes all RPZ -- policy records to act as if they were "cname domain" records. -- -- -+ An organization using a policy zone provided by another -+ organization might use this mechanism to redirect domains -+ to its own walled garden. -+ -+ -+ GIVEN -+ -+ The placeholder policy says "do not override but -+ perform the action specified in the zone." -+ -+ -+ -+ -+ -+ DISABLED -+ -+ -+ The testing override policy causes policy zone records to do -+ nothing but log what they would have done if the -+ policy zone were not disabled. -+ The response to the DNS query will be written (or not) -+ according to any triggered policy records that are not -+ disabled. -+ Disabled policy zones should appear first, -+ because they will often not be logged -+ if a higher precedence trigger is found first. -+ -+ -+ -+ -+ -+ PASSTHRU, -+ DROP, -+ TCP-Only, -+ NXDOMAIN, -+ and -+ NODATA -+ -+ -+ override with the corresponding per-record policy. -+ -+ -+ -+ -+ -+ CNAME domain -+ -+ -+ causes all RPZ policy records to act as if they were -+ "cname domain" records. -+ -+ -+ -+ - - - -- By default, the actions encoded in an RPZ are applied -- only to queries that ask for recursion (RD=1). -- That default can be changed for a single RPZ or all RPZs in a view -+ By default, the actions encoded in a response policy zone -+ are applied only to queries that ask for recursion (RD=1). -+ That default can be changed for a single policy zone or -+ all response policy zones in a view - with a recursive-only no clause. - This feature is useful for serving the same zone files - both inside and outside an RFC 1918 cloud and using RPZ to -@@ -9341,15 +9471,43 @@ - - - -- Also by default, RPZ actions are applied only to DNS requests that -- either do not request DNSSEC metadata (DO=0) or when no DNSSEC -- records are available for request name in the original zone (not -- the response policy zone). -- This default can be changed for all RPZs in a view with a -- break-dnssec yes clause. -- In that case, RPZ actions are applied regardless of DNSSEC. -- The name of the clause option reflects the fact that results -- rewritten by RPZ actions cannot verify. -+ Also by default, RPZ actions are applied only to DNS requests -+ that either do not request DNSSEC metadata (DO=0) or when no -+ DNSSEC records are available for request name in the original -+ zone (not the response policy zone). This default can be -+ changed for all response policy zones in a view with a -+ break-dnssec yes clause. In that case, RPZ -+ actions are applied regardless of DNSSEC. The name of the -+ clause option reflects the fact that results rewritten by RPZ -+ actions cannot verify. -+ -+ -+ -+ No DNS records are needed for a QNAME or Client-IP trigger. -+ The name or IP address itself is sufficient, -+ so in principle the query name need not be recursively resolved. -+ However, not resolving the requested -+ name can leak the fact that response policy rewriting is in use -+ and that the name is listed in a policy zone to operators of -+ servers for listed names. To prevent that information leak, by -+ default any recursion needed for a request is done before any -+ policy triggers are considered. Because listed domains often -+ have slow authoritative servers, this default behavior can cost -+ significant time. -+ The qname-wait-recurse no option -+ overrides that default behavior when recursion cannot -+ change a non-error response. -+ The option does not affect QNAME or client-IP triggers -+ in policy zones listed -+ after other zones containing IP, NSIP and NSDNAME triggers, because -+ those may depend on the A, AAAA, and NS records that would be -+ found during recursive resolution. It also does not affect -+ DNSSEC requests (DO=1) unless break-dnssec yes -+ is in use, because the response would depend on whether or not -+ RRSIG records were found during resolution. -+ The option can cause appear to rewrite error responses -+ such as SERVFAIL when no recursion is done to discover problems -+ at the authoritative server. - - - -@@ -9377,26 +9535,38 @@ - - ; QNAME policy records. There are no periods (.) after the owner names. - nxdomain.domain.com CNAME . ; NXDOMAIN policy -+*.nxdomain.domain.com CNAME . ; NXDOMAIN policy - nodata.domain.com CNAME *. ; NODATA policy -+*.nodata.domain.com CNAME *. ; NODATA policy - bad.domain.com A 10.0.0.1 ; redirect to a walled garden - AAAA 2001:2::1 -+bzone.domain.com CNAME garden.example.com. - - ; do not rewrite (PASSTHRU) OK.DOMAIN.COM - ok.domain.com CNAME rpz-passthru. - --bzone.domain.com CNAME garden.example.com. -- - ; redirect x.bzone.domain.com to x.bzone.domain.com.garden.example.com - *.bzone.domain.com CNAME *.garden.example.com. - - --; IP policy records that rewrite all answers for 127/8 except 127.0.0.1 -+; IP policy records that rewrite all responses containing A records in 127/8 -+; except 127.0.0.1 - 8.0.0.0.127.rpz-ip CNAME . - 32.1.0.0.127.rpz-ip CNAME rpz-passthru. - - ; NSDNAME and NSIP policy records - ns.domain.com.rpz-nsdname CNAME . - 48.zz.2.2001.rpz-nsip CNAME . -+ -+; blacklist and whitelist some DNS clients -+112.zz.2001.rpz-client-ip CNAME rpz-drop. -+8.0.0.0.127.rpz-client-ip CNAME rpz-drop. -+ -+; force some DNS clients and responses in the example.com zone to TCP -+16.0.0.1.10.rpz-client-ip CNAME rpz-tcp-only. -+example.com CNAME rpz-tcp-only. -+*.example.com CNAME rpz-tcp-only. -+ - - - RPZ can affect server performance. -diff -r -u lib/dns/db.c-orig lib/dns/db.c ---- lib/dns/db.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/db.c 2004-01-01 00:00:00.000000000 +0000 -@@ -1007,21 +1007,23 @@ - (db->methods->resigned)(db, rdataset, version); - } - --isc_result_t --dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) --{ -- if (db->methods->rpz_enabled != NULL) -- return ((db->methods->rpz_enabled)(db, st)); -- return (ISC_R_SUCCESS); -+/* -+ * Attach a database to policy zone databases. -+ * This should only happen when the caller has already ensured that -+ * it is dealing with a database that understands response policy zones. -+ */ -+void -+dns_db_rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { -+ REQUIRE(db->methods->rpz_attach != NULL); -+ (db->methods->rpz_attach)(db, rpzs, rpz_num); - } - --void --dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -- dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, -- dns_rdataset_t *ardataset, dns_rpz_st_t *st, -- dns_name_t *query_qname) --{ -- if (db->methods->rpz_findips != NULL) -- (db->methods->rpz_findips)(rpz, rpz_type, zone, db, version, -- ardataset, st, query_qname); -+/* -+ * Finish loading a response policy zone. -+ */ -+isc_result_t -+dns_db_rpz_ready(dns_db_t *db) { -+ if (db->methods->rpz_ready == NULL) -+ return (ISC_R_SUCCESS); -+ return ((db->methods->rpz_ready)(db)); - } -diff -r -u lib/dns/ecdb.c-orig lib/dns/ecdb.c ---- lib/dns/ecdb.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/ecdb.c 2004-01-01 00:00:00.000000000 +0000 -@@ -582,8 +582,8 @@ - NULL, /* resigned */ - NULL, /* isdnssec */ - NULL, /* getrrsetstats */ -- NULL, /* rpz_enabled */ -- NULL, /* rpz_findips */ -+ NULL, /* rpz_attach */ -+ NULL, /* rpz_ready */ - NULL, /* findnodeext */ - NULL /* findext */ - }; -diff -r -u lib/dns/include/dns/db.h-orig lib/dns/include/dns/db.h ---- lib/dns/include/dns/db.h-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/include/dns/db.h 2004-01-01 00:00:00.000000000 +0000 -@@ -172,14 +172,9 @@ - dns_dbversion_t *version); - isc_boolean_t (*isdnssec)(dns_db_t *db); - dns_stats_t *(*getrrsetstats)(dns_db_t *db); -- isc_result_t (*rpz_enabled)(dns_db_t *db, dns_rpz_st_t *st); -- void (*rpz_findips)(dns_rpz_zone_t *rpz, -- dns_rpz_type_t rpz_type, -- dns_zone_t *zone, dns_db_t *db, -- dns_dbversion_t *version, -- dns_rdataset_t *ardataset, -- dns_rpz_st_t *st, -- dns_name_t *query_qname); -+ void (*rpz_attach)(dns_db_t *db, dns_rpz_zones_t *rpzs, -+ dns_rpz_num_t rpz_num); -+ isc_result_t (*rpz_ready)(dns_db_t *db); - isc_result_t (*findnodeext)(dns_db_t *db, dns_name_t *name, - isc_boolean_t create, - dns_clientinfomethods_t *methods, -@@ -1542,30 +1537,17 @@ - * dns_rdatasetstats_create(); otherwise NULL. - */ - --isc_result_t --dns_db_rpz_enabled(dns_db_t *db, dns_rpz_st_t *st); -+void -+dns_db_rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num); - /*%< -- * Mark a database for response policy rewriting -- * or find which RPZ data is available. -+ * Attach the response policy information for a view to a database for a -+ * zone for the view. - */ - --void --dns_db_rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -- dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, -- dns_rdataset_t *ardataset, dns_rpz_st_t *st, -- dns_name_t *query_qname); --/*%< -- * Search the CDIR block tree of a response policy tree of trees for the best -- * match to any of the IP addresses in an A or AAAA rdataset. -- * -- * Requires: -- * \li search in policy zone 'rpz' for a match of 'rpz_type' either -- * DNS_RPZ_TYPE_IP or DNS_RPZ_TYPE_NSIP -- * \li 'zone' and 'db' are the database corresponding to 'rpz' -- * \li 'version' is the required version of the database -- * \li 'ardataset' is an A or AAAA rdataset of addresses to check -- * \li 'found' specifies the previous best match if any or -- * or NULL, an empty name, 0, DNS_RPZ_POLICY_MISS, and 0 -+isc_result_t -+dns_db_rpz_ready(dns_db_t *db); -+/*%< -+ * Finish loading a response policy zone. - */ - - ISC_LANG_ENDDECLS -diff -r -u lib/dns/include/dns/rpz.h-orig lib/dns/include/dns/rpz.h ---- lib/dns/include/dns/rpz.h-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/include/dns/rpz.h 2004-01-01 00:00:00.000000000 +0000 -@@ -25,19 +25,31 @@ - #include - #include - #include -+#include - - ISC_LANG_BEGINDECLS - - #define DNS_RPZ_PREFIX "rpz-" -+/* -+ * Sub-zones of various trigger types. -+ */ -+#define DNS_RPZ_CLIENT_IP_ZONE DNS_RPZ_PREFIX"client-ip" - #define DNS_RPZ_IP_ZONE DNS_RPZ_PREFIX"ip" - #define DNS_RPZ_NSIP_ZONE DNS_RPZ_PREFIX"nsip" - #define DNS_RPZ_NSDNAME_ZONE DNS_RPZ_PREFIX"nsdname" --#define DNS_RPZ_PASSTHRU_ZONE DNS_RPZ_PREFIX"passthru" -+/* -+ * Special policies. -+ */ -+#define DNS_RPZ_PASSTHRU_NAME DNS_RPZ_PREFIX"passthru" -+#define DNS_RPZ_DROP_NAME DNS_RPZ_PREFIX"drop" -+#define DNS_RPZ_TCP_ONLY_NAME DNS_RPZ_PREFIX"tcp-only" - --typedef isc_uint8_t dns_rpz_cidr_bits_t; -+ -+typedef isc_uint8_t dns_rpz_prefix_t; - - typedef enum { - DNS_RPZ_TYPE_BAD, -+ DNS_RPZ_TYPE_CLIENT_IP, - DNS_RPZ_TYPE_QNAME, - DNS_RPZ_TYPE_IP, - DNS_RPZ_TYPE_NSDNAME, -@@ -45,45 +57,151 @@ - } dns_rpz_type_t; - - /* -- * Require DNS_RPZ_POLICY_PASSTHRU < DNS_RPZ_POLICY_NXDOMAIN < -- * DNS_RPZ_POLICY_NODATA < DNS_RPZ_POLICY_CNAME to choose among competing -- * policies. -+ * Require DNS_RPZ_POLICY_PASSTHRU < DNS_RPZ_POLICY_DROP -+ * < DNS_RPZ_POLICY_TCP_ONLY DNS_RPZ_POLICY_NXDOMAIN < DNS_RPZ_POLICY_NODATA -+ * < DNS_RPZ_POLICY_CNAME to choose among competing policies. - */ - typedef enum { - DNS_RPZ_POLICY_GIVEN = 0, /* 'given': what policy record says */ -- DNS_RPZ_POLICY_DISABLED = 1, /* 'cname x': answer with x's rrsets */ -+ DNS_RPZ_POLICY_DISABLED = 1, /* log what would have happened */ - DNS_RPZ_POLICY_PASSTHRU = 2, /* 'passthru': do not rewrite */ -- DNS_RPZ_POLICY_NXDOMAIN = 3, /* 'nxdomain': answer with NXDOMAIN */ -- DNS_RPZ_POLICY_NODATA = 4, /* 'nodata': answer with ANCOUNT=0 */ -- DNS_RPZ_POLICY_CNAME = 5, /* 'cname x': answer with x's rrsets */ -+ DNS_RPZ_POLICY_DROP = 3, /* 'drop': do not respond */ -+ DNS_RPZ_POLICY_TCP_ONLY = 4, /* 'tcp-only': answer UDP with TC=1 */ -+ DNS_RPZ_POLICY_NXDOMAIN = 5, /* 'nxdomain': answer with NXDOMAIN */ -+ DNS_RPZ_POLICY_NODATA = 6, /* 'nodata': answer with ANCOUNT=0 */ -+ DNS_RPZ_POLICY_CNAME = 7, /* 'cname x': answer with x's rrsets */ - DNS_RPZ_POLICY_RECORD, - DNS_RPZ_POLICY_WILDCNAME, - DNS_RPZ_POLICY_MISS, - DNS_RPZ_POLICY_ERROR - } dns_rpz_policy_t; - -+typedef isc_uint8_t dns_rpz_num_t; -+ -+#define DNS_RPZ_MAX_ZONES 32 -+#if DNS_RPZ_MAX_ZONES > 32 -+# if DNS_RPZ_MAX_ZONES > 64 -+# error "rpz zone bit masks must fit in a word" -+# endif -+typedef isc_uint64_t dns_rpz_zbits_t; -+#else -+typedef isc_uint32_t dns_rpz_zbits_t; -+#endif -+ -+#define DNS_RPZ_ALL_ZBITS ((dns_rpz_zbits_t)-1) -+ -+#define DNS_RPZ_INVALID_NUM DNS_RPZ_MAX_ZONES -+ -+#define DNS_RPZ_ZBIT(n) (((dns_rpz_zbits_t)1) << (dns_rpz_num_t)(n)) -+ - /* -- * Specify a response policy zone. -+ * Mask of the specified and higher numbered policy zones -+ * Avoid hassles with (1<<33) or (1<<65) - */ --typedef struct dns_rpz_zone dns_rpz_zone_t; -+#define DNS_RPZ_ZMASK(n) ((dns_rpz_zbits_t)((((n) >= DNS_RPZ_MAX_ZONES-1) ? \ -+ 0 : (1<<((n)+1))) -1)) - -+/* -+ * The number of triggers of each type in a response policy zone. -+ */ -+typedef struct dns_rpz_triggers dns_rpz_triggers_t; -+struct dns_rpz_triggers { -+ int client_ipv4; -+ int client_ipv6; -+ int qname; -+ int ipv4; -+ int ipv6; -+ int nsdname; -+ int nsipv4; -+ int nsipv6; -+}; -+/* -+ * A single response policy zone. -+ */ -+typedef struct dns_rpz_zone dns_rpz_zone_t; - struct dns_rpz_zone { -- ISC_LINK(dns_rpz_zone_t) link; -- int num; /* ordinal in list of policy zones */ -- dns_name_t origin; /* Policy zone name */ -- dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */ -- dns_name_t passthru;/* DNS_RPZ_PASSTHRU_ZONE. */ -- dns_name_t cname; /* override value for ..._CNAME */ -- dns_ttl_t max_policy_ttl; -- dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */ -- isc_boolean_t recursive_only; -- isc_boolean_t defined; -+ isc_refcount_t refs; -+ dns_rpz_num_t num; /* ordinal in list of policy zones */ -+ dns_name_t origin; /* Policy zone name */ -+ dns_name_t client_ip; /* DNS_RPZ_CLIENT_IP_ZONE.origin. */ -+ dns_name_t ip; /* DNS_RPZ_IP_ZONE.origin. */ -+ dns_name_t nsdname; /* DNS_RPZ_NSDNAME_ZONE.origin */ -+ dns_name_t nsip; /* DNS_RPZ_NSIP_ZONE.origin. */ -+ dns_name_t passthru; /* DNS_RPZ_PASSTHRU_NAME. */ -+ dns_name_t drop; /* DNS_RPZ_DROP_NAME. */ -+ dns_name_t tcp_only; /* DNS_RPZ_TCP_ONLY_NAME. */ -+ dns_name_t cname; /* override value for ..._CNAME */ -+ dns_ttl_t max_policy_ttl; -+ dns_rpz_policy_t policy; /* DNS_RPZ_POLICY_GIVEN or override */ - }; - - /* -- * Radix trees for response policy IP addresses. -+ * Radix tree node for response policy IP addresses -+ */ -+typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t; -+ -+/* -+ * Response policy zones known to a view. - */ --typedef struct dns_rpz_cidr dns_rpz_cidr_t; -+typedef struct dns_rpz_zones dns_rpz_zones_t; -+struct dns_rpz_zones { -+ struct { -+ dns_rpz_zbits_t no_rd_ok; -+ isc_boolean_t break_dnssec; -+ isc_boolean_t qname_wait_recurse; -+ unsigned int min_ns_labels; -+ dns_rpz_num_t num_zones; -+ } p; -+ dns_rpz_zone_t *zones[DNS_RPZ_MAX_ZONES]; -+ dns_rpz_triggers_t triggers[DNS_RPZ_MAX_ZONES]; -+ -+ dns_rpz_zbits_t defined; -+ -+ /* -+ * The set of records for a policy zone are in one of these states: -+ * never loaded load_begun=0 have=0 -+ * during initial loading load_begun=1 have=0 -+ * and rbtdb->rpzsp == rbtdb->load_rpzsp -+ * after good load load_begun=1 have!=0 -+ * after failed initial load load_begun=1 have=0 -+ * and rbtdb->load_rpzsp == NULL -+ * reloading after failure load_begun=1 have=0 -+ * reloading after success -+ * main rpzs load_begun=1 have!=0 -+ * load rpzs load_begun=1 have=0 -+ */ -+ dns_rpz_zbits_t load_begun; -+ struct { -+ dns_rpz_zbits_t client_ipv4; -+ dns_rpz_zbits_t client_ipv6; -+ dns_rpz_zbits_t client_ip; -+ dns_rpz_zbits_t qname; -+ dns_rpz_zbits_t ipv4; -+ dns_rpz_zbits_t ipv6; -+ dns_rpz_zbits_t ip; -+ dns_rpz_zbits_t nsdname; -+ dns_rpz_zbits_t nsipv4; -+ dns_rpz_zbits_t nsipv6; -+ dns_rpz_zbits_t nsip; -+ dns_rpz_zbits_t qname_skip_recurse; -+ } have; -+ dns_rpz_triggers_t total_triggers; -+ -+ isc_mem_t *mctx; -+ isc_refcount_t refs; -+ /* -+ * One lock for short term read-only search that guarantees the -+ * consistency of the pointers. -+ * A second lock for maintenance that guarantees no other thread -+ * is adding or deleting nodes. -+ */ -+ isc_mutex_t search_lock; -+ isc_mutex_t maint_lock; -+ -+ dns_rpz_cidr_node_t *cidr; -+ dns_rbt_t *rbt; -+}; -+ - - /* - * context for finding the best policy -@@ -91,22 +209,19 @@ - typedef struct { - unsigned int state; - # define DNS_RPZ_REWRITTEN 0x0001 --# define DNS_RPZ_DONE_QNAME 0x0002 /* qname checked */ --# define DNS_RPZ_DONE_QNAME_IP 0x0004 /* IP addresses of qname checked */ --# define DNS_RPZ_DONE_NSDNAME 0x0008 /* NS name missed; checking addresses */ --# define DNS_RPZ_DONE_IPv4 0x0010 --# define DNS_RPZ_RECURSING 0x0020 --# define DNS_RPZ_HAVE_IP 0x0040 /* a policy zone has IP addresses */ --# define DNS_RPZ_HAVE_NSIPv4 0x0080 /* IPv4 NISP addresses */ --# define DNS_RPZ_HAVE_NSIPv6 0x0100 /* IPv6 NISP addresses */ --# define DNS_RPZ_HAVE_NSDNAME 0x0200 /* NS names */ -+# define DNS_RPZ_DONE_CLIENT_IP 0x0002 /* client IP address checked */ -+# define DNS_RPZ_DONE_QNAME 0x0004 /* qname checked */ -+# define DNS_RPZ_DONE_QNAME_IP 0x0008 /* IP addresses of qname checked */ -+# define DNS_RPZ_DONE_NSDNAME 0x0010 /* NS name missed; checking addresses */ -+# define DNS_RPZ_DONE_IPv4 0x0020 -+# define DNS_RPZ_RECURSING 0x0040 - /* - * Best match so far. - */ - struct { - dns_rpz_type_t type; - dns_rpz_zone_t *rpz; -- dns_rpz_cidr_bits_t prefix; -+ dns_rpz_prefix_t prefix; - dns_rpz_policy_t policy; - dns_ttl_t ttl; - isc_result_t result; -@@ -141,10 +256,15 @@ - dns_rdataset_t *sigrdataset; - dns_rdatatype_t qtype; - } q; -- dns_name_t *qname; -+ /* -+ * p_name: current policy owner name -+ * r_name: recursing for this name to possible policy triggers -+ * f_name: saved found name from before recursion -+ */ -+ dns_name_t *p_name; - dns_name_t *r_name; - dns_name_t *fname; -- dns_fixedname_t _qnamef; -+ dns_fixedname_t _p_namef; - dns_fixedname_t _r_namef; - dns_fixedname_t _fnamef; - } dns_rpz_st_t; -@@ -171,32 +291,41 @@ - const char * - dns_rpz_policy2str(dns_rpz_policy_t policy); - --void --dns_rpz_cidr_free(dns_rpz_cidr_t **cidr); -- --void --dns_rpz_view_destroy(dns_view_t *view); -+dns_rpz_policy_t -+dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset, -+ dns_name_t *selfname); - - isc_result_t --dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin, -- dns_rpz_cidr_t **rbtdb_cidr); --void --dns_rpz_enabled_get(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st); -+dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx); - - void --dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name); -+dns_rpz_attach_rpzs(dns_rpz_zones_t *source, dns_rpz_zones_t **target); - - void --dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name); -+dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp); - - isc_result_t --dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr, -- dns_rpz_type_t type, dns_name_t *canon_name, -- dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix); -+dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp, -+ dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num); - --dns_rpz_policy_t --dns_rpz_decode_cname(dns_rpz_zone_t *rpz, dns_rdataset_t *rdataset, -- dns_name_t *selfname); -+isc_result_t -+dns_rpz_ready(dns_rpz_zones_t *rpzs, -+ dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num); -+ -+isc_result_t -+dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *name); -+ -+void -+dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *name); -+ -+dns_rpz_num_t -+dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr, -+ dns_name_t *ip_name, dns_rpz_prefix_t *prefixp); -+ -+dns_rpz_zbits_t -+dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t zbits, dns_name_t *trig_name); - - ISC_LANG_ENDDECLS - -diff -r -u lib/dns/include/dns/view.h-orig lib/dns/include/dns/view.h ---- lib/dns/include/dns/view.h-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/include/dns/view.h 2004-01-01 00:00:00.000000000 +0000 -@@ -164,10 +164,7 @@ - dns_acl_t * v4_aaaa_acl; - dns_dns64list_t dns64; - unsigned int dns64cnt; -- ISC_LIST(dns_rpz_zone_t) rpz_zones; -- isc_boolean_t rpz_recursive_only; -- isc_boolean_t rpz_break_dnssec; -- unsigned int rpz_min_ns_labels; -+ dns_rpz_zones_t *rpzs; - - /* - * Configurable data for server use only, -diff -r -u lib/dns/include/dns/zone.h-orig lib/dns/include/dns/zone.h ---- lib/dns/include/dns/zone.h-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/include/dns/zone.h 2004-01-01 00:00:00.000000000 +0000 -@@ -2081,19 +2081,20 @@ - */ - - isc_result_t --dns_zone_rpz_enable(dns_zone_t *zone); -+dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs, -+ dns_rpz_num_t rpz_num); - /*% - * Set the response policy associated with a zone. - */ - --isc_result_t -+void - dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db); - /*% - * If a zone is a response policy zone, mark its new database. - */ - --isc_boolean_t --dns_zone_get_rpz(dns_zone_t *zone); -+dns_rpz_num_t -+dns_zone_get_rpz_num(dns_zone_t *zone); - - void - dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level); -diff -r -u lib/dns/rbtdb.c-orig lib/dns/rbtdb.c ---- lib/dns/rbtdb.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/rbtdb.c 2004-01-01 00:00:00.000000000 +0000 -@@ -453,7 +453,9 @@ - dns_rbt_t * tree; - dns_rbt_t * nsec; - dns_rbt_t * nsec3; -- dns_rpz_cidr_t * rpz_cidr; -+ dns_rpz_zones_t *rpzs; -+ dns_rpz_num_t rpz_num; -+ dns_rpz_zones_t *load_rpzs; - - /* Unlocked */ - unsigned int quantum; -@@ -972,8 +974,18 @@ - dns_stats_detach(&rbtdb->rrsetstats); - - #ifdef BIND9 -- if (rbtdb->rpz_cidr != NULL) -- dns_rpz_cidr_free(&rbtdb->rpz_cidr); -+ if (rbtdb->load_rpzs != NULL) { -+ /* -+ * We must be cleaning up after a failed zone loading. -+ */ -+ REQUIRE(rbtdb->rpzs != NULL && -+ rbtdb->rpz_num < rbtdb->rpzs->p.num_zones); -+ dns_rpz_detach_rpzs(&rbtdb->load_rpzs); -+ } -+ if (rbtdb->rpzs != NULL) { -+ REQUIRE(rbtdb->rpz_num < rbtdb->rpzs->p.num_zones); -+ dns_rpz_detach_rpzs(&rbtdb->rpzs); -+ } - #endif - - isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks, -@@ -1515,11 +1527,11 @@ - switch (node->nsec) { - case DNS_RBT_NSEC_NORMAL: - #ifdef BIND9 -- if (rbtdb->rpz_cidr != NULL) { -+ if (rbtdb->rpzs != NULL) { - dns_fixedname_init(&fname); - name = dns_fixedname_name(&fname); - dns_rbt_fullnamefromnode(node, name); -- dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name); -+ dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name); - } - #endif - result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); -@@ -1555,11 +1567,11 @@ - isc_result_totext(result)); - } - } -+ result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); - #ifdef BIND9 -- if (rbtdb->rpz_cidr != NULL) -- dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name); -+ if (rbtdb->rpzs != NULL) -+ dns_rpz_delete(rbtdb->rpzs, rbtdb->rpz_num, name); - #endif -- result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); - break; - case DNS_RBT_NSEC_NSEC: - result = dns_rbt_deletenode(rbtdb->nsec, node, ISC_FALSE); -@@ -1573,7 +1585,7 @@ - DNS_LOGCATEGORY_DATABASE, - DNS_LOGMODULE_CACHE, - ISC_LOG_WARNING, -- "delete_cnode(): " -+ "delete_node(): " - "dns_rbt_deletenode: %s", - isc_result_totext(result)); - } -@@ -2540,14 +2552,15 @@ - result = dns_rbt_addnode(tree, name, &node); - if (result == ISC_R_SUCCESS) { - #ifdef BIND9 -- if (tree == rbtdb->tree && rbtdb->rpz_cidr != NULL) { -+ if (rbtdb->rpzs != NULL && tree == rbtdb->tree) { - dns_fixedname_t fnamef; - dns_name_t *fname; - - dns_fixedname_init(&fnamef); - fname = dns_fixedname_name(&fnamef); - dns_rbt_fullnamefromnode(node, fname); -- dns_rpz_cidr_addip(rbtdb->rpz_cidr, fname); -+ result = dns_rpz_add(rbtdb->rpzs, -+ rbtdb->rpz_num, fname); - } - #endif - dns_rbt_namefromnode(node, &nodename); -@@ -4549,228 +4562,45 @@ - return (result); - } - -+#ifdef BIND9 - /* -- * Mark a database for response policy rewriting -- * or find which RPZ data is available. -+ * Connect this RBTDB to the response policy zone summary data for the view. - */ --#ifdef BIND9 --static isc_result_t --rpz_enabled(dns_db_t *db, dns_rpz_st_t *st) --{ -- dns_rbtdb_t *rbtdb; -- isc_result_t result; -+static void -+rpz_attach(dns_db_t *db, dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { -+ dns_rbtdb_t * rbtdb; - -- result = ISC_R_SUCCESS; - rbtdb = (dns_rbtdb_t *)db; - REQUIRE(VALID_RBTDB(rbtdb)); -- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); -- if (st != NULL) { -- dns_rpz_enabled_get(rbtdb->rpz_cidr, st); -- } else { -- result = dns_rpz_new_cidr(rbtdb->common.mctx, -- &rbtdb->common.origin, -- &rbtdb->rpz_cidr); -- } -- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); -- return (result); -+ -+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); -+ REQUIRE(rbtdb->rpzs == NULL && rbtdb->rpz_num == DNS_RPZ_INVALID_NUM); -+ dns_rpz_attach_rpzs(rpzs, &rbtdb->rpzs); -+ rbtdb->rpz_num = rpz_num; -+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); - } - - /* -- * Search the CDIR block tree of a response policy tree of trees for all of -- * the IP addresses in an A or AAAA rdataset. -- * Among the policies for all IPv4 and IPv6 addresses for a name, choose -- * the earliest configured policy, -- * QNAME over IP over NSDNAME over NSIP, -- * the longest prefix, -- * the lexically smallest address. -- * The caller must have already checked that any existing policy was not -- * configured earlier than this policy zone and does not have a higher -- * precedence type. -+ * Enable this RBTDB as a response policy zone. - */ --static void --rpz_findips(dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type, -- dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version, -- dns_rdataset_t *ardataset, dns_rpz_st_t *st, -- dns_name_t *query_qname) --{ -- dns_rbtdb_t *rbtdb; -- struct in_addr ina; -- struct in6_addr in6a; -- isc_netaddr_t netaddr; -- dns_fixedname_t selfnamef, qnamef; -- dns_name_t *selfname, *qname; -- dns_rbtnode_t *node; -- dns_rdataset_t zrdataset; -- dns_rpz_cidr_bits_t prefix; -+static isc_result_t -+rpz_ready(dns_db_t *db) { -+ dns_rbtdb_t * rbtdb; - isc_result_t result; -- dns_rpz_policy_t rpz_policy; -- dns_ttl_t ttl; - - rbtdb = (dns_rbtdb_t *)db; - REQUIRE(VALID_RBTDB(rbtdb)); -- RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); -- -- if (rbtdb->rpz_cidr == NULL) { -- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); -- return; -- } -- -- dns_fixedname_init(&selfnamef); -- dns_fixedname_init(&qnamef); -- selfname = dns_fixedname_name(&selfnamef); -- qname = dns_fixedname_name(&qnamef); -- -- for (result = dns_rdataset_first(ardataset); -- result == ISC_R_SUCCESS; -- result = dns_rdataset_next(ardataset)) { -- dns_rdata_t rdata = DNS_RDATA_INIT; -- dns_rdataset_current(ardataset, &rdata); -- switch (rdata.type) { -- case dns_rdatatype_a: -- INSIST(rdata.length == 4); -- memmove(&ina.s_addr, rdata.data, 4); -- isc_netaddr_fromin(&netaddr, &ina); -- break; -- case dns_rdatatype_aaaa: -- INSIST(rdata.length == 16); -- memmove(in6a.s6_addr, rdata.data, 16); -- isc_netaddr_fromin6(&netaddr, &in6a); -- break; -- default: -- continue; -- } -- -- result = dns_rpz_cidr_find(rbtdb->rpz_cidr, &netaddr, rpz_type, -- selfname, qname, &prefix); -- if (result != ISC_R_SUCCESS) -- continue; - -- /* -- * If we already have a rule, discard this new rule if -- * is not better. -- * The caller has checked that st->m.rpz->num > rpz->num -- * or st->m.rpz->num == rpz->num and st->m.type >= rpz_type -- */ -- if (st->m.policy != DNS_RPZ_POLICY_MISS && -- st->m.rpz->num == rpz->num && -- (st->m.type < rpz_type || -- (st->m.type == rpz_type && -- (st->m.prefix > prefix || -- (st->m.prefix == prefix && -- 0 > dns_name_rdatacompare(st->qname, qname)))))) -- continue; -- -- /* -- * We have rpz_st an entry with a prefix at least as long as -- * the prefix of the entry we had before. Find the node -- * corresponding to CDIR tree entry. -- */ -- node = NULL; -- result = dns_rbt_findnode(rbtdb->tree, qname, NULL, -- &node, NULL, 0, NULL, NULL); -- if (result != ISC_R_SUCCESS) { -- char namebuf[DNS_NAME_FORMATSIZE]; -- -- dns_name_format(qname, namebuf, sizeof(namebuf)); -- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -- DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -- "rpz_findips findnode(%s) failed: %s", -- namebuf, isc_result_totext(result)); -- continue; -- } -- /* -- * First look for a simple rewrite of the IP address. -- * If that fails, look for a CNAME. If we cannot find -- * a CNAME or the CNAME is neither of the special forms -- * "*" or ".", treat it like a real CNAME. -- */ -- dns_rdataset_init(&zrdataset); -- result = dns_db_findrdataset(db, node, version, ardataset->type, -- 0, 0, &zrdataset, NULL); -- if (result != ISC_R_SUCCESS) -- result = dns_db_findrdataset(db, node, version, -- dns_rdatatype_cname, -- 0, 0, &zrdataset, NULL); -- if (result == ISC_R_SUCCESS) { -- if (zrdataset.type != dns_rdatatype_cname) { -- rpz_policy = DNS_RPZ_POLICY_RECORD; -- } else { -- rpz_policy = dns_rpz_decode_cname(rpz, -- &zrdataset, -- selfname); -- if (rpz_policy == DNS_RPZ_POLICY_RECORD || -- rpz_policy == DNS_RPZ_POLICY_WILDCNAME) -- result = DNS_R_CNAME; -- } -- ttl = zrdataset.ttl; -- } else { -- rpz_policy = DNS_RPZ_POLICY_RECORD; -- result = DNS_R_NXRRSET; -- ttl = DNS_RPZ_TTL_DEFAULT; -- } -- -- /* -- * Use an overriding action specified in the configuration file -- */ -- if (rpz->policy != DNS_RPZ_POLICY_GIVEN) { -- /* -- * only log DNS_RPZ_POLICY_DISABLED hits -- */ -- if (rpz->policy == DNS_RPZ_POLICY_DISABLED) { -- if (isc_log_wouldlog(dns_lctx, -- DNS_RPZ_INFO_LEVEL)) { -- char qname_buf[DNS_NAME_FORMATSIZE]; -- char rpz_qname_buf[DNS_NAME_FORMATSIZE]; -- dns_name_format(query_qname, qname_buf, -- sizeof(qname_buf)); -- dns_name_format(qname, rpz_qname_buf, -- sizeof(rpz_qname_buf)); -- -- isc_log_write(dns_lctx, -- DNS_LOGCATEGORY_RPZ, -- DNS_LOGMODULE_RBTDB, -- DNS_RPZ_INFO_LEVEL, -- "disabled rpz %s %s rewrite" -- " %s via %s", -- dns_rpz_type2str(rpz_type), -- dns_rpz_policy2str(rpz_policy), -- qname_buf, rpz_qname_buf); -- } -- continue; -- } -- -- rpz_policy = rpz->policy; -- } -- -- if (dns_rdataset_isassociated(st->m.rdataset)) -- dns_rdataset_disassociate(st->m.rdataset); -- if (st->m.node != NULL) -- dns_db_detachnode(st->m.db, &st->m.node); -- if (st->m.db != NULL) -- dns_db_detach(&st->m.db); -- if (st->m.zone != NULL) -- dns_zone_detach(&st->m.zone); -- st->m.rpz = rpz; -- st->m.type = rpz_type; -- st->m.prefix = prefix; -- st->m.policy = rpz_policy; -- st->m.ttl = ISC_MIN(ttl, rpz->max_policy_ttl); -- st->m.result = result; -- dns_name_copy(qname, st->qname, NULL); -- if ((rpz_policy == DNS_RPZ_POLICY_RECORD || -- rpz_policy == DNS_RPZ_POLICY_WILDCNAME) && -- result != DNS_R_NXRRSET) { -- dns_rdataset_clone(&zrdataset,st->m.rdataset); -- dns_db_attachnode(db, node, &st->m.node); -- } -- dns_db_attach(db, &st->m.db); -- st->m.version = version; -- dns_zone_attach(zone, &st->m.zone); -- if (dns_rdataset_isassociated(&zrdataset)) -- dns_rdataset_disassociate(&zrdataset); -+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); -+ if (rbtdb->rpzs == NULL) { -+ INSIST(rbtdb->rpz_num == DNS_RPZ_INVALID_NUM); -+ result = ISC_R_SUCCESS; -+ } else { -+ result = dns_rpz_ready(rbtdb->rpzs, &rbtdb->load_rpzs, -+ rbtdb->rpz_num); - } -- -- RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); -+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); -+ return (result); - } - #endif - -@@ -6938,8 +6768,9 @@ - - done: - #ifdef BIND9 -- if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL) -- dns_rpz_cidr_addip(rbtdb->rpz_cidr, name); -+ if (rbtdb->rpzs != NULL && noderesult == ISC_R_SUCCESS) -+ noderesult = dns_rpz_add(rbtdb->load_rpzs, rbtdb->rpz_num, -+ name); - #endif - if (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS) - *nodep = node; -@@ -7074,6 +6905,20 @@ - - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); - -+#ifdef BIND9 -+ if (rbtdb->rpzs != NULL) { -+ isc_result_t result; -+ -+ result = dns_rpz_beginload(&rbtdb->load_rpzs, -+ rbtdb->rpzs, rbtdb->rpz_num); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(rbtdb->common.mctx, loadctx, -+ sizeof(*loadctx)); -+ return (result); -+ } -+ } -+#endif -+ - REQUIRE((rbtdb->attributes & (RBTDB_ATTR_LOADED|RBTDB_ATTR_LOADING)) - == 0); - rbtdb->attributes |= RBTDB_ATTR_LOADING; -@@ -7476,8 +7321,8 @@ - isdnssec, - NULL, - #ifdef BIND9 -- rpz_enabled, -- rpz_findips, -+ rpz_attach, -+ rpz_ready, - #else - NULL, - NULL, -@@ -7791,6 +7636,9 @@ - } - rbtdb->attributes = 0; - rbtdb->task = NULL; -+ rbtdb->rpzs = NULL; -+ rbtdb->load_rpzs = NULL; -+ rbtdb->rpz_num = DNS_RPZ_INVALID_NUM; - - /* - * Version Initialization. -diff -r -u lib/dns/rpz.c-orig lib/dns/rpz.c ---- lib/dns/rpz.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/rpz.c 2004-01-01 00:00:00.000000000 +0000 -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -44,9 +45,13 @@ - /* - * Parallel radix trees for databases of response policy IP addresses - * -- * The radix or Patricia trees are somewhat specialized to handle response -- * policy addresses by representing the two test of IP IP addresses and name -- * server IP addresses in a single tree. -+ * The radix or patricia trees are somewhat specialized to handle response -+ * policy addresses by representing the two sets of IP addresses and name -+ * server IP addresses in a single tree. One set of IP addresses is -+ * for rpz-ip policies or policies triggered by addresses in A or -+ * AAAA records in responses. -+ * The second set is for rpz-nsip policies or policies triggered by addresses -+ * in A or AAAA records for NS records that are authorities for responses. - * - * Each leaf indicates that an IP address is listed in the IP address or the - * name server IP address policy sub-zone (or both) of the corresponding -@@ -55,7 +60,8 @@ - * tree, the node in the policy zone's database is found by converting - * the IP address to a domain name in a canonical form. - * -- * The response policy zone canonical form of IPv6 addresses is one of: -+ * -+ * The response policy zone canonical form of an IPv6 address is one of: - * prefix.W.W.W.W.W.W.W.W - * prefix.WORDS.zz - * prefix.WORDS.zz.WORDS -@@ -72,7 +78,7 @@ - * prefix is the prefix length of the address between 1 and 32 - * B is a number between 0 and 255 - * -- * IPv4 addresses are distinguished from IPv6 addresses by having -+ * Names for IPv4 addresses are distinguished from IPv6 addresses by having - * 5 labels all of which are numbers, and a prefix between 1 and 32. - */ - -@@ -90,43 +96,89 @@ - } dns_rpz_cidr_key_t; - - #define ADDR_V4MAPPED 0xffff -+#define KEY_IS_IPV4(prefix,ip) ((prefix) >= 96 && (ip)->w[0] == 0 && \ -+ (ip)->w[1] == 0 && (ip)->w[2] == ADDR_V4MAPPED) -+ -+#define DNS_RPZ_WORD_MASK(b) ((b) == 0 ? (dns_rpz_cidr_word_t)(-1) \ -+ : ((dns_rpz_cidr_word_t)(-1) \ -+ << (DNS_RPZ_CIDR_WORD_BITS - (b)))) -+ -+/* -+ * Get bit #n from the array of words of an IP address. -+ */ -+#define DNS_RPZ_IP_BIT(ip, n) (1 & ((ip)->w[(n)/DNS_RPZ_CIDR_WORD_BITS] >> \ -+ (DNS_RPZ_CIDR_WORD_BITS \ -+ - 1 - ((n) % DNS_RPZ_CIDR_WORD_BITS)))) - --#define DNS_RPZ_WORD_MASK(b) \ -- ((b) == 0 ? (dns_rpz_cidr_word_t)(-1) \ -- : ((dns_rpz_cidr_word_t)(-1) \ -- << (DNS_RPZ_CIDR_WORD_BITS - (b)))) -- --#define DNS_RPZ_IP_BIT(ip, bitno) \ -- (1 & ((ip)->w[(bitno)/DNS_RPZ_CIDR_WORD_BITS] >> \ -- (DNS_RPZ_CIDR_WORD_BITS - 1 - ((bitno) % DNS_RPZ_CIDR_WORD_BITS)))) -+/* -+ * A triplet of arrays of bits flagging the existence of -+ * client-IP, IP, and NSIP policy triggers. -+ */ -+typedef struct dns_rpz_addr_zbits dns_rpz_addr_zbits_t; -+struct dns_rpz_addr_zbits { -+ dns_rpz_zbits_t client_ip; -+ dns_rpz_zbits_t ip; -+ dns_rpz_zbits_t nsip; -+}; - --typedef struct dns_rpz_cidr_node dns_rpz_cidr_node_t; --typedef isc_uint8_t dns_rpz_cidr_flags_t; -+/* -+ * A CIDR or radix tree node. -+ */ - struct dns_rpz_cidr_node { -- dns_rpz_cidr_node_t *parent; -- dns_rpz_cidr_node_t *child[2]; -- dns_rpz_cidr_key_t ip; -- dns_rpz_cidr_bits_t bits; -- dns_rpz_cidr_flags_t flags; --#define DNS_RPZ_CIDR_FG_IP 0x01 /* has IP data or is parent of IP */ --#define DNS_RPZ_CIDR_FG_IP_DATA 0x02 /* has IP data */ --#define DNS_RPZ_CIDR_FG_NSIPv4 0x04 /* has or is parent of NSIPv4 data */ --#define DNS_RPZ_CIDR_FG_NSIPv6 0x08 /* has or is parent of NSIPv6 data */ --#define DNS_RPZ_CIDR_FG_NSIP_DATA 0x10 /* has NSIP data */ -+ dns_rpz_cidr_node_t *parent; -+ dns_rpz_cidr_node_t *child[2]; -+ dns_rpz_cidr_key_t ip; -+ dns_rpz_prefix_t prefix; -+ dns_rpz_addr_zbits_t set; -+ dns_rpz_addr_zbits_t sum; -+}; -+ -+/* -+ * The data in a RBT node has two pairs of bits for policy zones. -+ * One pair is for the corresponding name of the node such as example.com -+ * and the other pair is for a wildcard child such as *.example.com. -+ */ -+/* -+ * A pair of arrays of bits flagging the existence of -+ * QNAME and NSDNAME policy triggers. -+ */ -+typedef struct dns_rpz_nm_zbits dns_rpz_nm_zbits_t; -+struct dns_rpz_nm_zbits { -+ dns_rpz_zbits_t qname; -+ dns_rpz_zbits_t ns; - }; - --struct dns_rpz_cidr { -- isc_mem_t *mctx; -- isc_boolean_t have_nsdname; /* zone has NSDNAME record */ -- dns_rpz_cidr_node_t *root; -- dns_name_t ip_name; /* RPZ_IP_ZONE.origin. */ -- dns_name_t nsip_name; /* RPZ_NSIP_ZONE.origin. */ -- dns_name_t nsdname_name; /* RPZ_NSDNAME_ZONE.origin */ -+typedef struct dns_rpz_nm_data dns_rpz_nm_data_t; -+struct dns_rpz_nm_data { -+ dns_rpz_nm_zbits_t set; -+ dns_rpz_nm_zbits_t wild; - }; - -+#if 0 -+/* -+ * Catch a name while debugging. -+ */ -+static void -+catch_name(const dns_name_t *src_name, const char *tgt, const char *str) { -+ dns_fixedname_t tgt_namef; -+ dns_name_t *tgt_name; -+ -+ dns_fixedname_init(&tgt_namef); -+ tgt_name = dns_fixedname_name(&tgt_namef); -+ dns_name_fromstring(tgt_name, tgt, DNS_NAME_DOWNCASE, NULL); -+ if (dns_name_equal(src_name, tgt_name)) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "rpz hit failed: %s %s", str, tgt); -+ } -+} -+#endif -+ - const char * - dns_rpz_type2str(dns_rpz_type_t type) { - switch (type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ return ("CLIENT-IP"); - case DNS_RPZ_TYPE_QNAME: - return ("QNAME"); - case DNS_RPZ_TYPE_IP: -@@ -138,32 +190,34 @@ - case DNS_RPZ_TYPE_BAD: - break; - } -- FATAL_ERROR(__FILE__, __LINE__, -- "impossible rpz type %d", type); -+ FATAL_ERROR(__FILE__, __LINE__, "impossible rpz type %d", type); - return ("impossible"); - } - - dns_rpz_policy_t - dns_rpz_str2policy(const char *str) { -+ static struct { -+ const char *str; -+ dns_rpz_policy_t policy; -+ } tbl[] = { -+ {"given", DNS_RPZ_POLICY_GIVEN}, -+ {"disabled", DNS_RPZ_POLICY_DISABLED}, -+ {"passthru", DNS_RPZ_POLICY_PASSTHRU}, -+ {"drop", DNS_RPZ_POLICY_DROP}, -+ {"tcp-only", DNS_RPZ_POLICY_TCP_ONLY}, -+ {"nxdomain", DNS_RPZ_POLICY_NXDOMAIN}, -+ {"nodata", DNS_RPZ_POLICY_NODATA}, -+ {"cname", DNS_RPZ_POLICY_CNAME}, -+ {"no-op", DNS_RPZ_POLICY_PASSTHRU}, /* old passthru */ -+ }; -+ unsigned int n; -+ - if (str == NULL) - return (DNS_RPZ_POLICY_ERROR); -- if (!strcasecmp(str, "given")) -- return (DNS_RPZ_POLICY_GIVEN); -- if (!strcasecmp(str, "disabled")) -- return (DNS_RPZ_POLICY_DISABLED); -- if (!strcasecmp(str, "passthru")) -- return (DNS_RPZ_POLICY_PASSTHRU); -- if (!strcasecmp(str, "nxdomain")) -- return (DNS_RPZ_POLICY_NXDOMAIN); -- if (!strcasecmp(str, "nodata")) -- return (DNS_RPZ_POLICY_NODATA); -- if (!strcasecmp(str, "cname")) -- return (DNS_RPZ_POLICY_CNAME); -- /* -- * Obsolete -- */ -- if (!strcasecmp(str, "no-op")) -- return (DNS_RPZ_POLICY_PASSTHRU); -+ for (n = 0; n < sizeof(tbl)/sizeof(tbl[0]); ++n) { -+ if (!strcasecmp(tbl[n].str, str)) -+ return (tbl[n].policy); -+ } - return (DNS_RPZ_POLICY_ERROR); - } - -@@ -175,6 +229,12 @@ - case DNS_RPZ_POLICY_PASSTHRU: - str = "PASSTHRU"; - break; -+ case DNS_RPZ_POLICY_DROP: -+ str = "DROP"; -+ break; -+ case DNS_RPZ_POLICY_TCP_ONLY: -+ str = "TCP-ONLY"; -+ break; - case DNS_RPZ_POLICY_NXDOMAIN: - str = "NXDOMAIN"; - break; -@@ -196,243 +256,274 @@ - return (str); - } - --/* -- * Free the radix tree of a response policy database. -- */ --void --dns_rpz_cidr_free(dns_rpz_cidr_t **cidrp) { -- dns_rpz_cidr_node_t *cur, *child, *parent; -- dns_rpz_cidr_t *cidr; -- -- REQUIRE(cidrp != NULL); -- -- cidr = *cidrp; -- if (cidr == NULL) -- return; -- -- cur = cidr->root; -- while (cur != NULL) { -- /* Depth first. */ -- child = cur->child[0]; -- if (child != NULL) { -- cur = child; -- continue; -- } -- child = cur->child[1]; -- if (child != NULL) { -- cur = child; -- continue; -- } -+static int -+zbit_to_num(dns_rpz_zbits_t zbit) { -+ dns_rpz_num_t rpz_num; - -- /* Delete this leaf and go up. */ -- parent = cur->parent; -- if (parent == NULL) -- cidr->root = NULL; -- else -- parent->child[parent->child[1] == cur] = NULL; -- isc_mem_put(cidr->mctx, cur, sizeof(*cur)); -- cur = parent; -+ INSIST(zbit != 0); -+ rpz_num = 0; -+#if DNS_RPZ_MAX_ZONES > 32 -+ if ((zbit & 0xffffffff00000000L) != 0) { -+ zbit >>= 32; -+ rpz_num += 32; - } -- -- dns_name_free(&cidr->ip_name, cidr->mctx); -- dns_name_free(&cidr->nsip_name, cidr->mctx); -- dns_name_free(&cidr->nsdname_name, cidr->mctx); -- isc_mem_put(cidr->mctx, cidr, sizeof(*cidr)); -- *cidrp = NULL; -+#endif -+ if ((zbit & 0xffff0000) != 0) { -+ zbit >>= 16; -+ rpz_num += 16; -+ } -+ if ((zbit & 0xff00) != 0) { -+ zbit >>= 8; -+ rpz_num += 8; -+ } -+ if ((zbit & 0xf0) != 0) { -+ zbit >>= 4; -+ rpz_num += 4; -+ } -+ if ((zbit & 0xc) != 0) { -+ zbit >>= 2; -+ rpz_num += 2; -+ } -+ if ((zbit & 2) != 0) -+ ++rpz_num; -+ return (rpz_num); - } - - /* -- * Forget a view's list of policy zones. -+ * Make a set of bit masks given one or more bits and their type. - */ --void --dns_rpz_view_destroy(dns_view_t *view) { -- dns_rpz_zone_t *zone; -- -- REQUIRE(view != NULL); -+static void -+make_addr_set(dns_rpz_addr_zbits_t *tgt_set, dns_rpz_zbits_t zbits, -+ dns_rpz_type_t type) -+{ -+ switch (type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ tgt_set->client_ip = zbits; -+ tgt_set->ip = 0; -+ tgt_set->nsip = 0; -+ break; -+ case DNS_RPZ_TYPE_IP: -+ tgt_set->client_ip = 0; -+ tgt_set->ip = zbits; -+ tgt_set->nsip = 0; -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ tgt_set->client_ip = 0; -+ tgt_set->ip = 0; -+ tgt_set->nsip = zbits; -+ break; -+ default: -+ INSIST(0); -+ break; -+ } -+} - -- while (!ISC_LIST_EMPTY(view->rpz_zones)) { -- zone = ISC_LIST_HEAD(view->rpz_zones); -- ISC_LIST_UNLINK(view->rpz_zones, zone, link); -- if (dns_name_dynamic(&zone->origin)) -- dns_name_free(&zone->origin, view->mctx); -- if (dns_name_dynamic(&zone->passthru)) -- dns_name_free(&zone->passthru, view->mctx); -- if (dns_name_dynamic(&zone->nsdname)) -- dns_name_free(&zone->nsdname, view->mctx); -- if (dns_name_dynamic(&zone->cname)) -- dns_name_free(&zone->cname, view->mctx); -- isc_mem_put(view->mctx, zone, sizeof(*zone)); -+static void -+make_nm_set(dns_rpz_nm_zbits_t *tgt_set, -+ dns_rpz_num_t rpz_num, dns_rpz_type_t type) -+{ -+ switch (type) { -+ case DNS_RPZ_TYPE_QNAME: -+ tgt_set->qname = DNS_RPZ_ZBIT(rpz_num); -+ tgt_set->ns = 0; -+ break; -+ case DNS_RPZ_TYPE_NSDNAME: -+ tgt_set->qname = 0; -+ tgt_set->ns = DNS_RPZ_ZBIT(rpz_num); -+ break; -+ default: -+ INSIST(0); -+ break; - } - } - - /* -- * Start a new radix tree for a response policy zone. -+ * Mark a node and all of its parents as having client-IP, IP, or NSIP data - */ --isc_result_t --dns_rpz_new_cidr(isc_mem_t *mctx, dns_name_t *origin, -- dns_rpz_cidr_t **rbtdb_cidr) --{ -- isc_result_t result; -- dns_rpz_cidr_t *cidr; -- -- REQUIRE(rbtdb_cidr != NULL && *rbtdb_cidr == NULL); -- -- cidr = isc_mem_get(mctx, sizeof(*cidr)); -- if (cidr == NULL) -- return (ISC_R_NOMEMORY); -- memset(cidr, 0, sizeof(*cidr)); -- cidr->mctx = mctx; -+static void -+set_sum_pair(dns_rpz_cidr_node_t *cnode) { -+ dns_rpz_cidr_node_t *child; -+ dns_rpz_addr_zbits_t sum; - -- dns_name_init(&cidr->ip_name, NULL); -- result = dns_name_fromstring2(&cidr->ip_name, DNS_RPZ_IP_ZONE, origin, -- DNS_NAME_DOWNCASE, mctx); -- if (result != ISC_R_SUCCESS) { -- isc_mem_put(mctx, cidr, sizeof(*cidr)); -- return (result); -- } -+ do { -+ sum = cnode->set; - -- dns_name_init(&cidr->nsip_name, NULL); -- result = dns_name_fromstring2(&cidr->nsip_name, DNS_RPZ_NSIP_ZONE, -- origin, DNS_NAME_DOWNCASE, mctx); -- if (result != ISC_R_SUCCESS) { -- dns_name_free(&cidr->ip_name, mctx); -- isc_mem_put(mctx, cidr, sizeof(*cidr)); -- return (result); -- } -+ child = cnode->child[0]; -+ if (child != NULL) { -+ sum.client_ip |= child->sum.client_ip; -+ sum.ip |= child->sum.ip; -+ sum.nsip |= child->sum.nsip; -+ } - -- dns_name_init(&cidr->nsdname_name, NULL); -- result = dns_name_fromstring2(&cidr->nsdname_name, DNS_RPZ_NSDNAME_ZONE, -- origin, DNS_NAME_DOWNCASE, mctx); -- if (result != ISC_R_SUCCESS) { -- dns_name_free(&cidr->nsip_name, mctx); -- dns_name_free(&cidr->ip_name, mctx); -- isc_mem_put(mctx, cidr, sizeof(*cidr)); -- return (result); -- } -+ child = cnode->child[1]; -+ if (child != NULL) { -+ sum.client_ip |= child->sum.client_ip; -+ sum.ip |= child->sum.ip; -+ sum.nsip |= child->sum.nsip; -+ } - -- *rbtdb_cidr = cidr; -- return (ISC_R_SUCCESS); -+ if (cnode->sum.client_ip == sum.client_ip && -+ cnode->sum.ip == sum.ip && -+ cnode->sum.nsip == sum.nsip) -+ break; -+ cnode->sum = sum; -+ cnode = cnode->parent; -+ } while (cnode != NULL); - } - --/* -- * See if a policy zone has IP, NSIP, or NSDNAME rules or records. -- */ --void --dns_rpz_enabled_get(dns_rpz_cidr_t *cidr, dns_rpz_st_t *st) { -- if (cidr == NULL) -- return; -- if (cidr->root != NULL && -- (cidr->root->flags & DNS_RPZ_CIDR_FG_IP) != 0) -- st->state |= DNS_RPZ_HAVE_IP; -- if (cidr->root != NULL && -- (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv4) != 0) -- st->state |= DNS_RPZ_HAVE_NSIPv4; -- if (cidr->root != NULL && -- (cidr->root->flags & DNS_RPZ_CIDR_FG_NSIPv6) != 0) -- st->state |= DNS_RPZ_HAVE_NSIPv6; -- if (cidr->have_nsdname) -- st->state |= DNS_RPZ_HAVE_NSDNAME; --} -- --static inline dns_rpz_cidr_flags_t --get_flags(const dns_rpz_cidr_key_t *ip, dns_rpz_cidr_bits_t prefix, -- dns_rpz_type_t rpz_type) --{ -- if (rpz_type == DNS_RPZ_TYPE_NSIP) { -- if (prefix >= 96 && -- ip->w[0] == 0 && ip->w[1] == 0 && -- ip->w[2] == ADDR_V4MAPPED) -- return (DNS_RPZ_CIDR_FG_NSIP_DATA | -- DNS_RPZ_CIDR_FG_NSIPv4); -- else -- return (DNS_RPZ_CIDR_FG_NSIP_DATA | -- DNS_RPZ_CIDR_FG_NSIPv6); -+static void -+fix_qname_skip_recurse(dns_rpz_zones_t *rpzs) { -+ dns_rpz_zbits_t zbits; -+ -+ /* -+ * Get a mask covering all policy zones that are not subordinate to -+ * other policy zones containing triggers that require that the -+ * qname be resolved before they can be checked. -+ */ -+ if (rpzs->p.qname_wait_recurse) { -+ zbits = 0; - } else { -- return (DNS_RPZ_CIDR_FG_IP | DNS_RPZ_CIDR_FG_IP_DATA); -+ zbits = (rpzs->have.ipv4 || rpzs->have.ipv6 || -+ rpzs->have.nsdname || -+ rpzs->have.nsipv4 || rpzs->have.nsipv6); -+ if (zbits == 0) { -+ zbits = DNS_RPZ_ALL_ZBITS; -+ } else { -+ zbits = DNS_RPZ_ZMASK(zbit_to_num(zbits)); -+ } - } -+ rpzs->have.qname_skip_recurse = zbits; -+ -+ rpzs->have.client_ip = rpzs->have.client_ipv4 | rpzs->have.client_ipv6; -+ rpzs->have.ip = rpzs->have.ipv4 | rpzs->have.ipv6; -+ rpzs->have.nsip = rpzs->have.nsipv4 | rpzs->have.nsipv6; - } - --/* -- * Mark a node as having IP or NSIP data and all of its parents -- * as members of the IP or NSIP tree. -- */ - static void --set_node_flags(dns_rpz_cidr_node_t *node, dns_rpz_type_t rpz_type) { -- dns_rpz_cidr_flags_t flags; -+adj_trigger_cnt(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, -+ const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix, -+ isc_boolean_t inc) -+{ -+ int *cnt; -+ dns_rpz_zbits_t *have; - -- flags = get_flags(&node->ip, node->bits, rpz_type); -- node->flags |= flags; -- flags &= ~(DNS_RPZ_CIDR_FG_NSIP_DATA | DNS_RPZ_CIDR_FG_IP_DATA); -- for (;;) { -- node = node->parent; -- if (node == NULL) -- return; -- node->flags |= flags; -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ REQUIRE(tgt_ip != NULL); -+ if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) { -+ cnt = &rpzs->triggers[rpz_num].client_ipv4; -+ have = &rpzs->have.client_ipv4; -+ } else { -+ cnt = &rpzs->triggers[rpz_num].client_ipv6; -+ have = &rpzs->have.client_ipv6; -+ } -+ break; -+ case DNS_RPZ_TYPE_QNAME: -+ cnt = &rpzs->triggers[rpz_num].qname; -+ have = &rpzs->have.qname; -+ break; -+ case DNS_RPZ_TYPE_IP: -+ REQUIRE(tgt_ip != NULL); -+ if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) { -+ cnt = &rpzs->triggers[rpz_num].ipv4; -+ have = &rpzs->have.ipv4; -+ } else { -+ cnt = &rpzs->triggers[rpz_num].ipv6; -+ have = &rpzs->have.ipv6; -+ } -+ break; -+ case DNS_RPZ_TYPE_NSDNAME: -+ cnt = &rpzs->triggers[rpz_num].nsdname; -+ have = &rpzs->have.nsdname; -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ REQUIRE(tgt_ip != NULL); -+ if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) { -+ cnt = &rpzs->triggers[rpz_num].nsipv4; -+ have = &rpzs->have.nsipv4; -+ } else { -+ cnt = &rpzs->triggers[rpz_num].nsipv6; -+ have = &rpzs->have.nsipv6; -+ } -+ break; -+ default: -+ INSIST(0); -+ } -+ -+ if (inc) { -+ if (++*cnt == 1) { -+ *have |= DNS_RPZ_ZBIT(rpz_num); -+ fix_qname_skip_recurse(rpzs); -+ } -+ } else { -+ REQUIRE(*cnt > 0); -+ if (--*cnt == 0) { -+ *have &= ~DNS_RPZ_ZBIT(rpz_num); -+ fix_qname_skip_recurse(rpzs); -+ } - } - } - --/* -- * Make a radix tree node. -- */ - static dns_rpz_cidr_node_t * --new_node(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *ip, -- dns_rpz_cidr_bits_t bits, dns_rpz_cidr_flags_t flags) -+new_node(dns_rpz_zones_t *rpzs, -+ const dns_rpz_cidr_key_t *ip, dns_rpz_prefix_t prefix, -+ const dns_rpz_cidr_node_t *child) - { -- dns_rpz_cidr_node_t *node; -+ dns_rpz_cidr_node_t *new; - int i, words, wlen; - -- node = isc_mem_get(cidr->mctx, sizeof(*node)); -- if (node == NULL) -+ new = isc_mem_get(rpzs->mctx, sizeof(*new)); -+ if (new == NULL) - return (NULL); -- memset(node, 0, sizeof(*node)); -+ memset(new, 0, sizeof(*new)); - -- node->flags = flags & ~(DNS_RPZ_CIDR_FG_IP_DATA | -- DNS_RPZ_CIDR_FG_NSIP_DATA); -+ if (child != NULL) -+ new->sum = child->sum; - -- node->bits = bits; -- words = bits / DNS_RPZ_CIDR_WORD_BITS; -- wlen = bits % DNS_RPZ_CIDR_WORD_BITS; -+ new->prefix = prefix; -+ words = prefix / DNS_RPZ_CIDR_WORD_BITS; -+ wlen = prefix % DNS_RPZ_CIDR_WORD_BITS; - i = 0; - while (i < words) { -- node->ip.w[i] = ip->w[i]; -+ new->ip.w[i] = ip->w[i]; - ++i; - } - if (wlen != 0) { -- node->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen); -+ new->ip.w[i] = ip->w[i] & DNS_RPZ_WORD_MASK(wlen); - ++i; - } - while (i < DNS_RPZ_CIDR_WORDS) -- node->ip.w[i++] = 0; -+ new->ip.w[i++] = 0; - -- return (node); -+ return (new); - } - - static void - badname(int level, dns_name_t *name, const char *str1, const char *str2) { -- char printname[DNS_NAME_FORMATSIZE]; -+ char namebuf[DNS_NAME_FORMATSIZE]; - - /* - * bin/tests/system/rpz/tests.sh looks for "invalid rpz". - */ -- if (level < DNS_RPZ_DEBUG_QUIET -- && isc_log_wouldlog(dns_lctx, level)) { -- dns_name_format(name, printname, sizeof(printname)); -+ if (level < DNS_RPZ_DEBUG_QUIET && -+ isc_log_wouldlog(dns_lctx, level)) { -+ dns_name_format(name, namebuf, sizeof(namebuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, - DNS_LOGMODULE_RBTDB, level, - "invalid rpz IP address \"%s\"%s%s", -- printname, str1, str2); -+ namebuf, str1, str2); - } - } - - /* - * Convert an IP address from radix tree binary (host byte order) to -- * to its canonical response policy domain name and its name in the -+ * to its canonical response policy domain name without the origin of the - * policy zone. - */ - static isc_result_t --ip2name(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip, -- dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type, -- dns_name_t *canon_name, dns_name_t *search_name) -+ip2name(const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix, -+ dns_name_t *base_name, dns_name_t *ip_name) - { - #ifndef INET6_ADDRSTRLEN - #define INET6_ADDRSTRLEN 46 -@@ -440,22 +531,18 @@ - int w[DNS_RPZ_CIDR_WORDS*2]; - char str[1+8+1+INET6_ADDRSTRLEN+1]; - isc_buffer_t buffer; -- dns_name_t *name; - isc_result_t result; - isc_boolean_t zeros; - int i, n, len; - -- if (tgt_prefix > 96 && -- tgt_ip->w[0] == 0 && -- tgt_ip->w[1] == 0 && -- tgt_ip->w[2] == ADDR_V4MAPPED) { -+ if (KEY_IS_IPV4(tgt_prefix, tgt_ip)) { - len = snprintf(str, sizeof(str), "%d.%d.%d.%d.%d", - tgt_prefix - 96, - tgt_ip->w[3] & 0xff, - (tgt_ip->w[3]>>8) & 0xff, - (tgt_ip->w[3]>>16) & 0xff, - (tgt_ip->w[3]>>24) & 0xff); -- if (len == -1 || len > (int)sizeof(str)) -+ if (len < 0 || len > (int)sizeof(str)) - return (ISC_R_FAILURE); - } else { - for (i = 0; i < DNS_RPZ_CIDR_WORDS; i++) { -@@ -469,9 +556,9 @@ - return (ISC_R_FAILURE); - i = 0; - while (i < DNS_RPZ_CIDR_WORDS * 2) { -- if (w[i] != 0 || zeros -- || i >= DNS_RPZ_CIDR_WORDS * 2 - 1 -- || w[i+1] != 0) { -+ if (w[i] != 0 || zeros || -+ i >= DNS_RPZ_CIDR_WORDS * 2 - 1 || -+ w[i+1] != 0) { - INSIST((size_t)len <= sizeof(str)); - n = snprintf(&str[len], sizeof(str) - len, - ".%x", w[i++]); -@@ -495,48 +582,31 @@ - } - } - -- if (canon_name != NULL) { -- isc__buffer_init(&buffer, str, sizeof(str)); -- isc__buffer_add(&buffer, len); -- result = dns_name_fromtext(canon_name, &buffer, -- dns_rootname, 0, NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- } -- if (search_name != NULL) { -- isc__buffer_init(&buffer, str, sizeof(str)); -- isc__buffer_add(&buffer, len); -- if (type == DNS_RPZ_TYPE_NSIP) -- name = &cidr->nsip_name; -- else -- name = &cidr->ip_name; -- result = dns_name_fromtext(search_name, &buffer, name, 0, NULL); -- if (result != ISC_R_SUCCESS) -- return (result); -- } -- return (ISC_R_SUCCESS); -+ isc__buffer_init(&buffer, str, sizeof(str)); -+ isc__buffer_add(&buffer, len); -+ result = dns_name_fromtext(ip_name, &buffer, base_name, 0, NULL); -+ return (result); - } - - /* -- * Decide which kind of IP address response policy zone a name is in. -+ * Determine the type a of a name in a response policy zone. - */ - static dns_rpz_type_t --set_type(dns_rpz_cidr_t *cidr, dns_name_t *name) { -+type_from_name(dns_rpz_zone_t *rpz, dns_name_t *name) { - -- if (dns_name_issubdomain(name, &cidr->ip_name)) -+ if (dns_name_issubdomain(name, &rpz->ip)) - return (DNS_RPZ_TYPE_IP); - -- /* -- * Require `./configure --enable-rpz-nsip` and nsdname -- * until consistency problems are resolved. -- */ -+ if (dns_name_issubdomain(name, &rpz->client_ip)) -+ return (DNS_RPZ_TYPE_CLIENT_IP); -+ - #ifdef ENABLE_RPZ_NSIP -- if (dns_name_issubdomain(name, &cidr->nsip_name)) -+ if (dns_name_issubdomain(name, &rpz->nsip)) - return (DNS_RPZ_TYPE_NSIP); - #endif - - #ifdef ENABLE_RPZ_NSDNAME -- if (dns_name_issubdomain(name, &cidr->nsdname_name)) -+ if (dns_name_issubdomain(name, &rpz->nsdname)) - return (DNS_RPZ_TYPE_NSDNAME); - #endif - -@@ -545,73 +615,80 @@ - - /* - * Convert an IP address from canonical response policy domain name form -- * to radix tree binary (host byte order). -+ * to radix tree binary (host byte order) for adding or deleting IP or NSIP -+ * data. - */ - static isc_result_t --name2ipkey(dns_rpz_cidr_t *cidr, int level, dns_name_t *src_name, -- dns_rpz_type_t type, dns_rpz_cidr_key_t *tgt_ip, -- dns_rpz_cidr_bits_t *tgt_prefix) -+name2ipkey(int log_level, -+ const dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, dns_name_t *src_name, -+ dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t *tgt_prefix, -+ dns_rpz_addr_zbits_t *new_set) - { -- isc_result_t result; -- dns_fixedname_t fname; -- dns_name_t *ipname; -- char ipstr[DNS_NAME_FORMATSIZE]; -+ dns_rpz_zone_t *rpz; -+ char ip_str[DNS_NAME_FORMATSIZE]; -+ dns_offsets_t ip_name_offsets; -+ dns_fixedname_t ip_name2f; -+ dns_name_t ip_name, *ip_name2; - const char *prefix_str, *cp, *end; - char *cp2; - int ip_labels; -- dns_rpz_cidr_bits_t bits; -- unsigned long prefix, l; -+ dns_rpz_prefix_t prefix; -+ unsigned long prefix_num, l; -+ isc_result_t result; - int i; - -- /* -- * Need at least enough labels for the shortest name, -- * :: or 128.*.RPZ_x_ZONE.rpz.LOCALHOST. -- */ -+ REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones); -+ rpz = rpzs->zones[rpz_num]; -+ REQUIRE(rpz != NULL); -+ -+ make_addr_set(new_set, DNS_RPZ_ZBIT(rpz_num), rpz_type); -+ - ip_labels = dns_name_countlabels(src_name); -- ip_labels -= dns_name_countlabels(&cidr->ip_name); -- ip_labels--; -- if (ip_labels < 1) { -- badname(level, src_name, "; too short", ""); -+ if (rpz_type == DNS_RPZ_TYPE_QNAME) -+ ip_labels -= dns_name_countlabels(&rpz->origin); -+ else -+ ip_labels -= dns_name_countlabels(&rpz->nsdname); -+ if (ip_labels < 2) { -+ badname(log_level, src_name, "; too short", ""); - return (ISC_R_FAILURE); - } -+ dns_name_init(&ip_name, ip_name_offsets); -+ dns_name_getlabelsequence(src_name, 0, ip_labels, &ip_name); - - /* - * Get text for the IP address - */ -- dns_fixedname_init(&fname); -- ipname = dns_fixedname_name(&fname); -- dns_name_split(src_name, dns_name_countlabels(&cidr->ip_name), -- ipname, NULL); -- dns_name_format(ipname, ipstr, sizeof(ipstr)); -- end = &ipstr[strlen(ipstr)+1]; -- prefix_str = ipstr; -+ dns_name_format(&ip_name, ip_str, sizeof(ip_str)); -+ end = &ip_str[strlen(ip_str)+1]; -+ prefix_str = ip_str; - -- prefix = strtoul(prefix_str, &cp2, 10); -+ prefix_num = strtoul(prefix_str, &cp2, 10); - if (*cp2 != '.') { -- badname(level, src_name, -+ badname(log_level, src_name, - "; invalid leading prefix length", ""); - return (ISC_R_FAILURE); - } - *cp2 = '\0'; -- if (prefix < 1U || prefix > 128U) { -- badname(level, src_name, -+ if (prefix_num < 1U || prefix_num > 128U) { -+ badname(log_level, src_name, - "; invalid prefix length of ", prefix_str); - return (ISC_R_FAILURE); - } - cp = cp2+1; - -- if (ip_labels == 4 && !strchr(cp, 'z')) { -+ if (--ip_labels == 4 && !strchr(cp, 'z')) { - /* - * Convert an IPv4 address - * from the form "prefix.w.z.y.x" - */ -- if (prefix > 32U) { -- badname(level, src_name, -+ if (prefix_num > 32U) { -+ badname(log_level, src_name, - "; invalid IPv4 prefix length of ", prefix_str); - return (ISC_R_FAILURE); - } -- prefix += 96; -- *tgt_prefix = (dns_rpz_cidr_bits_t)prefix; -+ prefix_num += 96; -+ *tgt_prefix = (dns_rpz_prefix_t)prefix_num; - tgt_ip->w[0] = 0; - tgt_ip->w[1] = 0; - tgt_ip->w[2] = ADDR_V4MAPPED; -@@ -621,7 +698,7 @@ - if (l > 255U || (*cp2 != '.' && *cp2 != '\0')) { - if (*cp2 == '.') - *cp2 = '\0'; -- badname(level, src_name, -+ badname(log_level, src_name, - "; invalid IPv4 octet ", cp); - return (ISC_R_FAILURE); - } -@@ -632,7 +709,7 @@ - /* - * Convert a text IPv6 address. - */ -- *tgt_prefix = (dns_rpz_cidr_bits_t)prefix; -+ *tgt_prefix = (dns_rpz_prefix_t)prefix_num; - for (i = 0; - ip_labels > 0 && i < DNS_RPZ_CIDR_WORDS * 2; - ip_labels--) { -@@ -651,7 +728,7 @@ - (*cp2 != '.' && *cp2 != '\0')) { - if (*cp2 == '.') - *cp2 = '\0'; -- badname(level, src_name, -+ badname(log_level, src_name, - "; invalid IPv6 word ", cp); - return (ISC_R_FAILURE); - } -@@ -665,36 +742,37 @@ - } - } - if (cp != end) { -- badname(level, src_name, "", ""); -+ badname(log_level, src_name, "", ""); - return (ISC_R_FAILURE); - } - - /* - * Check for 1s after the prefix length. - */ -- bits = (dns_rpz_cidr_bits_t)prefix; -- while (bits < DNS_RPZ_CIDR_KEY_BITS) { -+ prefix = (dns_rpz_prefix_t)prefix_num; -+ while (prefix < DNS_RPZ_CIDR_KEY_BITS) { - dns_rpz_cidr_word_t aword; - -- i = bits % DNS_RPZ_CIDR_WORD_BITS; -- aword = tgt_ip->w[bits / DNS_RPZ_CIDR_WORD_BITS]; -+ i = prefix % DNS_RPZ_CIDR_WORD_BITS; -+ aword = tgt_ip->w[prefix / DNS_RPZ_CIDR_WORD_BITS]; - if ((aword & ~DNS_RPZ_WORD_MASK(i)) != 0) { -- badname(level, src_name, -+ badname(log_level, src_name, - "; too small prefix length of ", prefix_str); - return (ISC_R_FAILURE); - } -- bits -= i; -- bits += DNS_RPZ_CIDR_WORD_BITS; -+ prefix -= i; -+ prefix += DNS_RPZ_CIDR_WORD_BITS; - } - - /* -- * Convert the address back to a canonical policy domain name -- * to ensure that it is in canonical form. -+ * Convert the address back to a canonical domain name -+ * to ensure that the original name is in canonical form. - */ -- result = ip2name(cidr, tgt_ip, (dns_rpz_cidr_bits_t) prefix, -- type, NULL, ipname); -- if (result != ISC_R_SUCCESS || !dns_name_equal(src_name, ipname)) { -- badname(level, src_name, "; not canonical", ""); -+ dns_fixedname_init(&ip_name2f); -+ ip_name2 = dns_fixedname_name(&ip_name2f); -+ result = ip2name(tgt_ip, (dns_rpz_prefix_t)prefix_num, NULL, ip_name2); -+ if (result != ISC_R_SUCCESS || !dns_name_equal(&ip_name, ip_name2)) { -+ badname(log_level, src_name, "; not canonical", ""); - return (ISC_R_FAILURE); - } - -@@ -702,10 +780,54 @@ - } - - /* -- * Find first differing bit. -+ * Get trigger name and data bits for adding or deleting summary NSDNAME -+ * or QNAME data. - */ --static int --ffbit(dns_rpz_cidr_word_t w) { -+static void -+name2data(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, const dns_name_t *src_name, -+ dns_name_t *trig_name, dns_rpz_nm_data_t *new_data) -+{ -+ dns_rpz_zone_t *rpz; -+ dns_offsets_t tmp_name_offsets; -+ dns_name_t tmp_name; -+ unsigned int prefix_len, n; -+ -+ REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones); -+ rpz = rpzs->zones[rpz_num]; -+ REQUIRE(rpz != NULL); -+ -+ /* -+ * Handle wildcards by putting only the parent into the -+ * summary RBT. The summary database only causes a check of the -+ * real policy zone where wildcards will be handled. -+ */ -+ if (dns_name_iswildcard(src_name)) { -+ prefix_len = 1; -+ memset(&new_data->set, 0, sizeof(new_data->set)); -+ make_nm_set(&new_data->wild, rpz_num, rpz_type); -+ } else { -+ prefix_len = 0; -+ make_nm_set(&new_data->set, rpz_num, rpz_type); -+ memset(&new_data->wild, 0, sizeof(new_data->wild)); -+ } -+ -+ dns_name_init(&tmp_name, tmp_name_offsets); -+ n = dns_name_countlabels(src_name); -+ n -= prefix_len; -+ if (rpz_type == DNS_RPZ_TYPE_QNAME) -+ n -= dns_name_countlabels(&rpz->origin); -+ else -+ n -= dns_name_countlabels(&rpz->nsdname); -+ dns_name_getlabelsequence(src_name, prefix_len, n, &tmp_name); -+ (void)dns_name_concatenate(&tmp_name, dns_rootname, trig_name, NULL); -+} -+ -+/* -+ * Find the first differing bit in a key (IP address) word. -+ */ -+static inline int -+ffs_keybit(dns_rpz_cidr_word_t w) { - int bit; - - bit = DNS_RPZ_CIDR_WORD_BITS-1; -@@ -731,17 +853,17 @@ - } - - /* -- * Find the first differing bit in two keys. -+ * Find the first differing bit in two keys (IP addresses). - */ - static int --diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_cidr_bits_t bits1, -- const dns_rpz_cidr_key_t *key2, dns_rpz_cidr_bits_t bits2) -+diff_keys(const dns_rpz_cidr_key_t *key1, dns_rpz_prefix_t prefix1, -+ const dns_rpz_cidr_key_t *key2, dns_rpz_prefix_t prefix2) - { - dns_rpz_cidr_word_t delta; -- dns_rpz_cidr_bits_t maxbit, bit; -+ dns_rpz_prefix_t maxbit, bit; - int i; - -- maxbit = ISC_MIN(bits1, bits2); -+ maxbit = ISC_MIN(prefix1, prefix2); - - /* - * find the first differing words -@@ -751,7 +873,7 @@ - i++, bit += DNS_RPZ_CIDR_WORD_BITS) { - delta = key1->w[i] ^ key2->w[i]; - if (delta != 0) { -- bit += ffbit(delta); -+ bit += ffs_keybit(delta); - break; - } - } -@@ -759,133 +881,170 @@ - } - - /* -+ * Given a hit while searching the radix trees, -+ * clear all bits for higher numbered zones. -+ */ -+static inline dns_rpz_zbits_t -+trim_zbits(dns_rpz_zbits_t zbits, dns_rpz_zbits_t found) { -+ dns_rpz_zbits_t x; -+ -+ /* -+ * Isolate the first or smallest numbered hit bit. -+ * Make a mask of that bit and all smaller numbered bits. -+ */ -+ x = zbits & found; -+ x &= (~x + 1); -+ x = (x << 1) - 1; -+ return (zbits &= x); -+} -+ -+/* - * Search a radix tree for an IP address for ordinary lookup - * or for a CIDR block adding or deleting an entry -- * The tree read (for simple search) or write lock must be held by the caller. - * -- * Return ISC_R_SUCCESS, ISC_R_NOTFOUND, DNS_R_PARTIALMATCH, ISC_R_EXISTS, -- * ISC_R_NOMEMORY -+ * Return ISC_R_SUCCESS, DNS_R_PARTIALMATCH, ISC_R_NOTFOUND, -+ * and *found=longest match node -+ * or with create==ISC_TRUE, ISC_R_EXISTS or ISC_R_NOMEMORY - */ - static isc_result_t --search(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip, -- dns_rpz_cidr_bits_t tgt_prefix, dns_rpz_type_t type, -- isc_boolean_t create, -- dns_rpz_cidr_node_t **found) /* NULL or longest match node */ -+search(dns_rpz_zones_t *rpzs, -+ const dns_rpz_cidr_key_t *tgt_ip, dns_rpz_prefix_t tgt_prefix, -+ const dns_rpz_addr_zbits_t *tgt_set, isc_boolean_t create, -+ dns_rpz_cidr_node_t **found) - { - dns_rpz_cidr_node_t *cur, *parent, *child, *new_parent, *sibling; -+ dns_rpz_addr_zbits_t set; - int cur_num, child_num; -- dns_rpz_cidr_bits_t dbit; -- dns_rpz_cidr_flags_t flags, data_flag; -+ dns_rpz_prefix_t dbit; - isc_result_t find_result; - -- flags = get_flags(tgt_ip, tgt_prefix, type); -- data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA | -- DNS_RPZ_CIDR_FG_NSIP_DATA); -- -+ set = *tgt_set; - find_result = ISC_R_NOTFOUND; -- if (found != NULL) -- *found = NULL; -- cur = cidr->root; -+ *found = NULL; -+ cur = rpzs->cidr; - parent = NULL; - cur_num = 0; - for (;;) { - if (cur == NULL) { - /* -- * No child so we cannot go down. Fail or -- * add the target as a child of the current parent. -+ * No child so we cannot go down. -+ * Quit with whatever we already found -+ * or add the target as a child of the current parent. - */ - if (!create) - return (find_result); -- child = new_node(cidr, tgt_ip, tgt_prefix, 0); -+ child = new_node(rpzs, tgt_ip, tgt_prefix, NULL); - if (child == NULL) - return (ISC_R_NOMEMORY); - if (parent == NULL) -- cidr->root = child; -+ rpzs->cidr = child; - else - parent->child[cur_num] = child; - child->parent = parent; -- set_node_flags(child, type); -- if (found != NULL) -- *found = cur; -+ child->set.client_ip |= tgt_set->client_ip; -+ child->set.ip |= tgt_set->ip; -+ child->set.nsip |= tgt_set->nsip; -+ set_sum_pair(child); -+ *found = cur; - return (ISC_R_SUCCESS); - } - -- /* -- * Pretend a node not in the correct tree does not exist -- * if we are not adding to the tree, -- * If we are adding, then continue down to eventually -- * add a node and mark/put this node in the correct tree. -- */ -- if ((cur->flags & flags) == 0 && !create) -- return (find_result); -+ if ((cur->sum.client_ip & set.client_ip) == 0 && -+ (cur->sum.ip & set.ip) == 0 && -+ (cur->sum.nsip & set.nsip) == 0) { -+ /* -+ * This node has no relevant data -+ * and is in none of the target trees. -+ * Pretend it does not exist if we are not adding. -+ * -+ * If we are adding, continue down to eventually add -+ * a node and mark/put this node in the correct tree. -+ */ -+ if (!create) -+ return (find_result); -+ } - -- dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->bits); -+ dbit = diff_keys(tgt_ip, tgt_prefix, &cur->ip, cur->prefix); - /* -- * dbit <= tgt_prefix and dbit <= cur->bits always. -+ * dbit <= tgt_prefix and dbit <= cur->prefix always. - * We are finished searching if we matched all of the target. - */ - if (dbit == tgt_prefix) { -- if (tgt_prefix == cur->bits) { -+ if (tgt_prefix == cur->prefix) { - /* -- * The current node matches the target exactly. -- * It is the answer if it has data. -+ * The node's key matches the target exactly. - */ -- if ((cur->flags & data_flag) != 0) { -- if (create) -- return (ISC_R_EXISTS); -- if (found != NULL) -- *found = cur; -- return (ISC_R_SUCCESS); -+ if ((cur->set.client_ip & set.client_ip) != 0 || -+ (cur->set.ip & set.ip) != 0 || -+ (cur->set.nsip & set.nsip) != 0) { -+ /* -+ * It is the answer if it has data. -+ */ -+ *found = cur; -+ if (create) { -+ find_result = ISC_R_EXISTS; -+ } else { -+ find_result = ISC_R_SUCCESS; -+ } - } else if (create) { - /* -- * The node had no data but does now. -+ * The node lacked relevant data, -+ * but will have it now. - */ -- set_node_flags(cur, type); -- if (found != NULL) -- *found = cur; -- return (ISC_R_SUCCESS); -+ cur->set.client_ip |= tgt_set->client_ip; -+ cur->set.ip |= tgt_set->ip; -+ cur->set.nsip |= tgt_set->nsip; -+ set_sum_pair(cur); -+ *found = cur; -+ find_result = ISC_R_SUCCESS; - } - return (find_result); - } - - /* -- * We know tgt_prefix < cur_bits which means that -+ * We know tgt_prefix < cur->prefix which means that - * the target is shorter than the current node. - * Add the target as the current node's parent. - */ - if (!create) - return (find_result); - -- new_parent = new_node(cidr, tgt_ip, tgt_prefix, -- cur->flags); -+ new_parent = new_node(rpzs, tgt_ip, tgt_prefix, cur); - if (new_parent == NULL) - return (ISC_R_NOMEMORY); - new_parent->parent = parent; - if (parent == NULL) -- cidr->root = new_parent; -+ rpzs->cidr = new_parent; - else - parent->child[cur_num] = new_parent; - child_num = DNS_RPZ_IP_BIT(&cur->ip, tgt_prefix+1); - new_parent->child[child_num] = cur; - cur->parent = new_parent; -- set_node_flags(new_parent, type); -- if (found != NULL) -- *found = new_parent; -+ new_parent->set = *tgt_set; -+ set_sum_pair(new_parent); -+ *found = new_parent; - return (ISC_R_SUCCESS); - } - -- if (dbit == cur->bits) { -- /* -- * We have a partial match by matching of all of the -- * current node but only part of the target. -- * Try to go down. -- */ -- if ((cur->flags & data_flag) != 0) { -+ if (dbit == cur->prefix) { -+ if ((cur->set.client_ip & set.client_ip) != 0 || -+ (cur->set.ip & set.ip) != 0 || -+ (cur->set.nsip & set.nsip) != 0) { -+ /* -+ * We have a partial match between of all of the -+ * current node but only part of the target. -+ * Continue searching for other hits in the -+ * same or lower numbered trees. -+ */ - find_result = DNS_R_PARTIALMATCH; -- if (found != NULL) -- *found = cur; -+ *found = cur; -+ set.client_ip = trim_zbits(set.ip, -+ cur->set.client_ip); -+ set.ip = trim_zbits(set.ip, -+ cur->set.ip); -+ set.nsip = trim_zbits(set.nsip, -+ cur->set.nsip); - } -- - parent = cur; - cur_num = DNS_RPZ_IP_BIT(tgt_ip, dbit); - cur = cur->child[cur_num]; -@@ -894,7 +1053,7 @@ - - - /* -- * dbit < tgt_prefix and dbit < cur->bits, -+ * dbit < tgt_prefix and dbit < cur->prefix, - * so we failed to match both the target and the current node. - * Insert a fork of a parent above the current node and - * add the target as a sibling of the current node -@@ -902,17 +1061,17 @@ - if (!create) - return (find_result); - -- sibling = new_node(cidr, tgt_ip, tgt_prefix, 0); -+ sibling = new_node(rpzs, tgt_ip, tgt_prefix, NULL); - if (sibling == NULL) - return (ISC_R_NOMEMORY); -- new_parent = new_node(cidr, tgt_ip, dbit, cur->flags); -+ new_parent = new_node(rpzs, tgt_ip, dbit, cur); - if (new_parent == NULL) { -- isc_mem_put(cidr->mctx, sibling, sizeof(*sibling)); -+ isc_mem_put(rpzs->mctx, sibling, sizeof(*sibling)); - return (ISC_R_NOMEMORY); - } - new_parent->parent = parent; - if (parent == NULL) -- cidr->root = new_parent; -+ rpzs->cidr = new_parent; - else - parent->child[cur_num] = new_parent; - child_num = DNS_RPZ_IP_BIT(tgt_ip, dbit); -@@ -920,129 +1079,670 @@ - new_parent->child[1-child_num] = cur; - cur->parent = new_parent; - sibling->parent = new_parent; -- set_node_flags(sibling, type); -- if (found != NULL) -- *found = sibling; -+ sibling->set = *tgt_set; -+ set_sum_pair(sibling); -+ *found = sibling; - return (ISC_R_SUCCESS); - } - } - - /* -- * Add an IP address to the radix tree of a response policy database. -- * The tree write lock must be held by the caller. -+ * Add an IP address to the radix tree. - */ --void --dns_rpz_cidr_addip(dns_rpz_cidr_t *cidr, dns_name_t *name) { -- isc_result_t result; -+static isc_result_t -+add_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, dns_name_t *src_name) -+{ - dns_rpz_cidr_key_t tgt_ip; -- dns_rpz_cidr_bits_t tgt_prefix; -- dns_rpz_type_t type; -- -- REQUIRE(cidr != NULL); -+ dns_rpz_prefix_t tgt_prefix; -+ dns_rpz_addr_zbits_t set; -+ dns_rpz_cidr_node_t *found; -+ isc_result_t result; - -+ result = name2ipkey(DNS_RPZ_ERROR_LEVEL, rpzs, rpz_num, rpz_type, -+ src_name, &tgt_ip, &tgt_prefix, &set); - /* -- * No worries if the new name is not an IP address. -+ * Log complaints about bad owner names but let the zone load. - */ -- type = set_type(cidr, name); -- switch (type) { -- case DNS_RPZ_TYPE_IP: -- case DNS_RPZ_TYPE_NSIP: -- break; -- case DNS_RPZ_TYPE_NSDNAME: -- cidr->have_nsdname = ISC_TRUE; -- return; -- case DNS_RPZ_TYPE_QNAME: -- case DNS_RPZ_TYPE_BAD: -- return; -- } -- result = name2ipkey(cidr, DNS_RPZ_ERROR_LEVEL, name, -- type, &tgt_ip, &tgt_prefix); - if (result != ISC_R_SUCCESS) -- return; -+ return (ISC_R_SUCCESS); - -- result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_TRUE, NULL); -- if (result == ISC_R_EXISTS && -- isc_log_wouldlog(dns_lctx, DNS_RPZ_ERROR_LEVEL)) -- { -- char printname[DNS_NAME_FORMATSIZE]; -+ result = search(rpzs, &tgt_ip, tgt_prefix, &set, ISC_TRUE, &found); -+ if (result != ISC_R_SUCCESS) { -+ char namebuf[DNS_NAME_FORMATSIZE]; - - /* - * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". - */ -- dns_name_format(name, printname, sizeof(printname)); -+ dns_name_format(src_name, namebuf, sizeof(namebuf)); - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, - DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -- "rpz add failed; \"%s\" is a duplicate name", -- printname); -+ "rpz add_cidr(%s) failed: %s", -+ namebuf, isc_result_totext(result)); -+ return (result); - } -+ -+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, ISC_TRUE); -+ return (result); - } - --/* -- * Delete an IP address from the radix tree of a response policy database. -- * The tree write lock must be held by the caller. -- */ --void --dns_rpz_cidr_deleteip(dns_rpz_cidr_t *cidr, dns_name_t *name) { -+static isc_result_t -+add_nm(dns_rpz_zones_t *rpzs, dns_name_t *trig_name, -+ const dns_rpz_nm_data_t *new_data) -+{ -+ dns_rbtnode_t *nmnode; -+ dns_rpz_nm_data_t *nm_data; - isc_result_t result; -- dns_rpz_cidr_key_t tgt_ip; -- dns_rpz_cidr_bits_t tgt_prefix; -- dns_rpz_type_t type; -- dns_rpz_cidr_node_t *tgt = NULL, *parent, *child; -- dns_rpz_cidr_flags_t flags, data_flag; - -- if (cidr == NULL) -- return; -+ nmnode = NULL; -+ result = dns_rbt_addnode(rpzs->rbt, trig_name, &nmnode); -+ switch (result) { -+ case ISC_R_SUCCESS: -+ case ISC_R_EXISTS: -+ nm_data = nmnode->data; -+ if (nm_data == NULL) { -+ nm_data = isc_mem_get(rpzs->mctx, sizeof(*nm_data)); -+ if (nm_data == NULL) -+ return (ISC_R_NOMEMORY); -+ *nm_data = *new_data; -+ nmnode->data = nm_data; -+ return (ISC_R_SUCCESS); -+ } -+ break; -+ default: -+ return (result); -+ } - - /* -- * Decide which kind of policy zone IP address it is, if either -- * and then find its node. -+ * Do not count bits that are already present - */ -- type = set_type(cidr, name); -- switch (type) { -- case DNS_RPZ_TYPE_IP: -- case DNS_RPZ_TYPE_NSIP: -- break; -- case DNS_RPZ_TYPE_NSDNAME: -+ if ((nm_data->set.qname & new_data->set.qname) != 0 || -+ (nm_data->set.ns & new_data->set.ns) != 0 || -+ (nm_data->wild.qname & new_data->wild.qname) != 0 || -+ (nm_data->wild.ns & new_data->wild.ns) != 0) { -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ - /* -- * We cannot easily count nsdnames because -- * internal rbt nodes get deleted. -+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". - */ -- return; -+ dns_name_format(trig_name, namebuf, sizeof(namebuf)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "rpz add_nm(%s): bits already set", namebuf); -+ return (ISC_R_EXISTS); -+ } -+ -+ nm_data->set.qname |= new_data->set.qname; -+ nm_data->set.ns |= new_data->set.ns; -+ nm_data->wild.qname |= new_data->wild.qname; -+ nm_data->wild.ns |= new_data->wild.ns; -+ return (ISC_R_SUCCESS); -+} -+ -+static isc_result_t -+add_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, dns_name_t *src_name) -+{ -+ dns_rpz_nm_data_t new_data; -+ dns_fixedname_t trig_namef; -+ dns_name_t *trig_name; -+ isc_result_t result; -+ -+ dns_fixedname_init(&trig_namef); -+ trig_name = dns_fixedname_name(&trig_namef); -+ name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &new_data); -+ -+ result = add_nm(rpzs, trig_name, &new_data); -+ if (result == ISC_R_SUCCESS) -+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_TRUE); -+ return (result); -+} -+ -+/* -+ * Callback to free the data for a node in the summary RBT database. -+ */ -+static void -+rpz_node_deleter(void *nm_data, void *mctx) { -+ isc_mem_put(mctx, nm_data, sizeof(dns_rpz_nm_data_t)); -+} -+ -+/* -+ * Get ready for a new set of policy zones. -+ */ -+isc_result_t -+dns_rpz_new_zones(dns_rpz_zones_t **rpzsp, isc_mem_t *mctx) { -+ dns_rpz_zones_t *new; -+ isc_result_t result; -+ -+ REQUIRE(rpzsp != NULL && *rpzsp == NULL); -+ -+ *rpzsp = NULL; -+ -+ new = isc_mem_get(mctx, sizeof(*new)); -+ if (new == NULL) -+ return (ISC_R_NOMEMORY); -+ memset(new, 0, sizeof(*new)); -+ -+ result = isc_mutex_init(&new->search_lock); -+ if (result != ISC_R_SUCCESS) { -+ isc_mem_put(mctx, new, sizeof(*new)); -+ return (result); -+ } -+ -+ result = isc_mutex_init(&new->maint_lock); -+ if (result != ISC_R_SUCCESS) { -+ DESTROYLOCK(&new->search_lock); -+ isc_mem_put(mctx, new, sizeof(*new)); -+ return (result); -+ } -+ -+ result = isc_refcount_init(&new->refs, 1); -+ if (result != ISC_R_SUCCESS) { -+ DESTROYLOCK(&new->maint_lock); -+ DESTROYLOCK(&new->search_lock); -+ isc_mem_put(mctx, new, sizeof(*new)); -+ return (result); -+ } -+ -+ result = dns_rbt_create(mctx, rpz_node_deleter, mctx, &new->rbt); -+ if (result != ISC_R_SUCCESS) { -+ isc_refcount_decrement(&new->refs, NULL); -+ isc_refcount_destroy(&new->refs); -+ DESTROYLOCK(&new->maint_lock); -+ DESTROYLOCK(&new->search_lock); -+ isc_mem_put(mctx, new, sizeof(*new)); -+ return (result); -+ } -+ -+ isc_mem_attach(mctx, &new->mctx); -+ -+ *rpzsp = new; -+ return (ISC_R_SUCCESS); -+} -+ -+/* -+ * Free the radix tree of a response policy database. -+ */ -+static void -+cidr_free(dns_rpz_zones_t *rpzs) { -+ dns_rpz_cidr_node_t *cur, *child, *parent; -+ -+ cur = rpzs->cidr; -+ while (cur != NULL) { -+ /* Depth first. */ -+ child = cur->child[0]; -+ if (child != NULL) { -+ cur = child; -+ continue; -+ } -+ child = cur->child[1]; -+ if (child != NULL) { -+ cur = child; -+ continue; -+ } -+ -+ /* Delete this leaf and go up. */ -+ parent = cur->parent; -+ if (parent == NULL) -+ rpzs->cidr = NULL; -+ else -+ parent->child[parent->child[1] == cur] = NULL; -+ isc_mem_put(rpzs->mctx, cur, sizeof(*cur)); -+ cur = parent; -+ } -+} -+ -+/* -+ * Discard a response policy zone blob -+ * before discarding the overall rpz structure. -+ */ -+static void -+rpz_detach(dns_rpz_zone_t **rpzp, dns_rpz_zones_t *rpzs) { -+ dns_rpz_zone_t *rpz; -+ unsigned int refs; -+ -+ rpz = *rpzp; -+ *rpzp = NULL; -+ isc_refcount_decrement(&rpz->refs, &refs); -+ if (refs != 0) -+ return; -+ isc_refcount_destroy(&rpz->refs); -+ -+ if (dns_name_dynamic(&rpz->origin)) -+ dns_name_free(&rpz->origin, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->client_ip)) -+ dns_name_free(&rpz->client_ip, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->ip)) -+ dns_name_free(&rpz->ip, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->nsdname)) -+ dns_name_free(&rpz->nsdname, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->nsip)) -+ dns_name_free(&rpz->nsip, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->passthru)) -+ dns_name_free(&rpz->passthru, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->drop)) -+ dns_name_free(&rpz->drop, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->tcp_only)) -+ dns_name_free(&rpz->tcp_only, rpzs->mctx); -+ if (dns_name_dynamic(&rpz->cname)) -+ dns_name_free(&rpz->cname, rpzs->mctx); -+ -+ isc_mem_put(rpzs->mctx, rpz, sizeof(*rpz)); -+} -+ -+void -+dns_rpz_attach_rpzs(dns_rpz_zones_t *rpzs, dns_rpz_zones_t **rpzsp) { -+ REQUIRE(rpzsp != NULL && *rpzsp == NULL); -+ isc_refcount_increment(&rpzs->refs, NULL); -+ *rpzsp = rpzs; -+} -+ -+/* -+ * Forget a view's policy zones. -+ */ -+void -+dns_rpz_detach_rpzs(dns_rpz_zones_t **rpzsp) { -+ dns_rpz_zones_t *rpzs; -+ dns_rpz_zone_t *rpz; -+ dns_rpz_num_t rpz_num; -+ unsigned int refs; -+ -+ REQUIRE(rpzsp != NULL); -+ rpzs = *rpzsp; -+ REQUIRE(rpzs != NULL); -+ -+ *rpzsp = NULL; -+ isc_refcount_decrement(&rpzs->refs, &refs); -+ -+ /* -+ * Forget the last of view's rpz machinery after the last reference. -+ */ -+ if (refs == 0) { -+ for (rpz_num = 0; rpz_num < DNS_RPZ_MAX_ZONES; ++rpz_num) { -+ rpz = rpzs->zones[rpz_num]; -+ rpzs->zones[rpz_num] = NULL; -+ if (rpz != NULL) -+ rpz_detach(&rpz, rpzs); -+ } -+ -+ cidr_free(rpzs); -+ dns_rbt_destroy(&rpzs->rbt); -+ DESTROYLOCK(&rpzs->maint_lock); -+ DESTROYLOCK(&rpzs->search_lock); -+ isc_refcount_destroy(&rpzs->refs); -+ isc_mem_putanddetach(&rpzs->mctx, rpzs, sizeof(*rpzs)); -+ } -+} -+ -+/* -+ * Create empty summary database to load one zone. -+ * The RBTDB write tree lock must be held. -+ */ -+isc_result_t -+dns_rpz_beginload(dns_rpz_zones_t **load_rpzsp, -+ dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) -+{ -+ dns_rpz_zones_t *load_rpzs; -+ dns_rpz_zone_t *rpz; -+ dns_rpz_zbits_t tgt; -+ isc_result_t result; -+ -+ REQUIRE(rpz_num < rpzs->p.num_zones); -+ rpz = rpzs->zones[rpz_num]; -+ REQUIRE(rpz != NULL); -+ -+ /* -+ * When reloading a zone, there are usually records among the summary -+ * data for the zone. Some of those records might be deleted by the -+ * reloaded zone data. To deal with that case: -+ * reload the new zone data into a new blank summary database -+ * if the reload fails, discard the new summary database -+ * if the new zone data is acceptable, copy the records for the -+ * other zones into the new summary database and replace the -+ * old summary database with the new. -+ * -+ * At the first attempt to load a zone, there is no summary data -+ * for the zone and so no records that need to be deleted. -+ * This is also the most common case of policy zone loading. -+ * Most policy zone maintenance should be by incremental changes -+ * and so by the addition and deletion of individual records. -+ * Detect that case and load records the first time into the -+ * operational summary database -+ */ -+ tgt = DNS_RPZ_ZBIT(rpz_num); -+ LOCK(&rpzs->maint_lock); -+ LOCK(&rpzs->search_lock); -+ if ((rpzs->load_begun & tgt) == 0) { -+ /* -+ * There is no existing version of the target zone. -+ */ -+ rpzs->load_begun |= tgt; -+ dns_rpz_attach_rpzs(rpzs, load_rpzsp); -+ UNLOCK(&rpzs->search_lock); -+ UNLOCK(&rpzs->maint_lock); -+ -+ } else { -+ UNLOCK(&rpzs->search_lock); -+ UNLOCK(&rpzs->maint_lock); -+ -+ result = dns_rpz_new_zones(load_rpzsp, rpzs->mctx); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+ load_rpzs = *load_rpzsp; -+ load_rpzs->p.num_zones = rpzs->p.num_zones; -+ load_rpzs->total_triggers = rpzs->total_triggers; -+ memcpy(load_rpzs->triggers, rpzs->triggers, -+ sizeof(load_rpzs->triggers)); -+ memset(&load_rpzs->triggers[rpz_num], 0, -+ sizeof(load_rpzs->triggers[rpz_num])); -+ load_rpzs->zones[rpz_num] = rpz; -+ isc_refcount_increment(&rpz->refs, NULL); -+ } -+ -+ return (ISC_R_SUCCESS); -+} -+ -+static void -+fix_triggers(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num) { -+ dns_rpz_num_t n; -+ const dns_rpz_zone_t *rpz; -+ dns_rpz_triggers_t old_totals; -+ dns_rpz_zbits_t zbit; -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ -+# define SET_TRIG(n, zbit, type) \ -+ if (rpzs->triggers[n].type == 0) { \ -+ rpzs->have.type &= ~zbit; \ -+ } else { \ -+ rpzs->total_triggers.type += rpzs->triggers[n].type; \ -+ rpzs->have.type |= zbit; \ -+ } -+ -+ memcpy(&old_totals, &rpzs->total_triggers, sizeof(old_totals)); -+ memset(&rpzs->total_triggers, 0, sizeof(rpzs->total_triggers)); -+ for (n = 0; n < rpzs->p.num_zones; ++n) { -+ rpz = rpzs->zones[n]; -+ zbit = DNS_RPZ_ZBIT(n); -+ SET_TRIG(n, zbit, client_ipv4); -+ SET_TRIG(n, zbit, client_ipv6); -+ SET_TRIG(n, zbit, qname); -+ SET_TRIG(n, zbit, ipv4); -+ SET_TRIG(n, zbit, ipv6); -+ SET_TRIG(n, zbit, nsdname); -+ SET_TRIG(n, zbit, nsipv4); -+ SET_TRIG(n, zbit, nsipv6); -+ } -+ -+ fix_qname_skip_recurse(rpzs); -+ -+ dns_name_format(&rpzs->zones[rpz_num]->origin, -+ namebuf, sizeof(namebuf)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_INFO_LEVEL, -+ "(re)loading policy zone '%s' changed from" -+ " %d to %d qname, %d to %d nsdname," -+ " %d to %d IP, %d to %d NSIP entries", -+ namebuf, -+ old_totals.qname, rpzs->total_triggers.qname, -+ old_totals.nsdname, rpzs->total_triggers.nsdname, -+ old_totals.ipv4 + old_totals.ipv6, -+ rpzs->total_triggers.ipv4 + rpzs->total_triggers.ipv6, -+ old_totals.nsipv4 + old_totals.nsipv6, -+ rpzs->total_triggers.nsipv4 + rpzs->total_triggers.nsipv6); -+ -+# undef SET_TRIG -+} -+ -+/* -+ * Finish loading one zone. -+ * The RBTDB write tree lock must be held. -+ */ -+isc_result_t -+dns_rpz_ready(dns_rpz_zones_t *rpzs, -+ dns_rpz_zones_t **load_rpzsp, dns_rpz_num_t rpz_num) -+{ -+ dns_rpz_zones_t *load_rpzs; -+ const dns_rpz_cidr_node_t *cnode, *next_cnode, *parent_cnode; -+ dns_rpz_cidr_node_t *found; -+ dns_rpz_zbits_t new_bit; -+ dns_rpz_addr_zbits_t new_ip; -+ dns_rbt_t *rbt; -+ dns_rbtnodechain_t chain; -+ dns_rbtnode_t *nmnode; -+ dns_rpz_nm_data_t *nm_data, new_data; -+ dns_fixedname_t labelf, originf, namef; -+ dns_name_t *label, *origin, *name; -+ isc_result_t result; -+ -+ INSIST(rpzs != NULL); -+ LOCK(&rpzs->maint_lock); -+ load_rpzs = *load_rpzsp; -+ INSIST(load_rpzs != NULL); -+ -+ if (load_rpzs == rpzs) { -+ /* -+ * This is a successful initial zone loading, -+ * perhaps for a new instance of a view. -+ */ -+ fix_triggers(rpzs, rpz_num); -+ UNLOCK(&rpzs->maint_lock); -+ dns_rpz_detach_rpzs(load_rpzsp); -+ return (ISC_R_SUCCESS); -+ } -+ -+ LOCK(&load_rpzs->maint_lock); -+ LOCK(&load_rpzs->search_lock); -+ -+ /* -+ * Unless there is only one policy zone, copy the other policy zones -+ * from the old policy structure to the new summary databases. -+ */ -+ if (rpzs->p.num_zones > 1) { -+ new_bit = ~DNS_RPZ_ZBIT(rpz_num); -+ -+ /* -+ * Copy to the radix tree. -+ */ -+ for (cnode = rpzs->cidr; cnode != NULL; cnode = next_cnode) { -+ new_ip.ip = cnode->set.ip & new_bit; -+ new_ip.client_ip = cnode->set.client_ip & new_bit; -+ new_ip.nsip = cnode->set.nsip & new_bit; -+ if (new_ip.client_ip != 0 || -+ new_ip.ip != 0 || -+ new_ip.nsip != 0) { -+ result = search(load_rpzs, -+ &cnode->ip, cnode->prefix, -+ &new_ip, ISC_TRUE, &found); -+ if (result == ISC_R_NOMEMORY) -+ goto unlock_and_detach; -+ INSIST(result == ISC_R_SUCCESS); -+ } -+ /* -+ * Do down and to the left as far as possible. -+ */ -+ next_cnode = cnode->child[0]; -+ if (next_cnode != NULL) -+ continue; -+ /* -+ * Go up until we find a branch to the right where -+ * we previously took the branch to the left. -+ */ -+ for (;;) { -+ parent_cnode = cnode->parent; -+ if (parent_cnode == NULL) -+ break; -+ if (parent_cnode->child[0] == cnode) { -+ next_cnode = parent_cnode->child[1]; -+ if (next_cnode != NULL) -+ break; -+ } -+ cnode = parent_cnode; -+ } -+ } -+ -+ /* -+ * Copy to the summary RBT. -+ */ -+ dns_fixedname_init(&namef); -+ name = dns_fixedname_name(&namef); -+ dns_fixedname_init(&labelf); -+ label = dns_fixedname_name(&labelf); -+ dns_fixedname_init(&originf); -+ origin = dns_fixedname_name(&originf); -+ dns_rbtnodechain_init(&chain, NULL); -+ result = dns_rbtnodechain_first(&chain, rpzs->rbt, NULL, NULL); -+ while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) { -+ result = dns_rbtnodechain_current(&chain, label, origin, -+ &nmnode); -+ INSIST(result == ISC_R_SUCCESS); -+ nm_data = nmnode->data; -+ if (nm_data != NULL) { -+ new_data.set.qname = (nm_data->set.qname & -+ new_bit); -+ new_data.set.ns = nm_data->set.ns & new_bit; -+ new_data.wild.qname = (nm_data->wild.qname & -+ new_bit); -+ new_data.wild.ns = nm_data->wild.ns & new_bit; -+ if (new_data.set.qname != 0 || -+ new_data.set.ns != 0 || -+ new_data.wild.qname != 0 || -+ new_data.wild.ns != 0) { -+ result = dns_name_concatenate(label, -+ origin, name, NULL); -+ INSIST(result == ISC_R_SUCCESS); -+ result = add_nm(load_rpzs, name, -+ &new_data); -+ if (result != ISC_R_SUCCESS) -+ goto unlock_and_detach; -+ } -+ } -+ result = dns_rbtnodechain_next(&chain, NULL, NULL); -+ } -+ if (result != ISC_R_NOMORE && result != ISC_R_NOTFOUND) { -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "dns_rpz_ready(): unexpected %s", -+ isc_result_totext(result)); -+ goto unlock_and_detach; -+ } -+ } -+ -+ fix_triggers(load_rpzs, rpz_num); -+ -+ /* -+ * Exchange the summary databases. -+ */ -+ LOCK(&rpzs->search_lock); -+ -+ found = rpzs->cidr; -+ rpzs->cidr = load_rpzs->cidr; -+ load_rpzs->cidr = found; -+ -+ rbt = rpzs->rbt; -+ rpzs->rbt = load_rpzs->rbt; -+ load_rpzs->rbt = rbt; -+ -+ rpzs->total_triggers = load_rpzs->total_triggers; -+ -+ UNLOCK(&rpzs->search_lock); -+ -+ result = ISC_R_SUCCESS; -+ -+ unlock_and_detach: -+ UNLOCK(&rpzs->maint_lock); -+ UNLOCK(&load_rpzs->search_lock); -+ UNLOCK(&load_rpzs->maint_lock); -+ dns_rpz_detach_rpzs(load_rpzsp); -+ return (result); -+} -+ -+/* -+ * Add an IP address to the radix tree or a name to the summary database. -+ */ -+isc_result_t -+dns_rpz_add(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, dns_name_t *src_name) -+{ -+ dns_rpz_zone_t *rpz; -+ dns_rpz_type_t rpz_type; -+ isc_result_t result = ISC_R_FAILURE; -+ -+ REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones); -+ rpz = rpzs->zones[rpz_num]; -+ REQUIRE(rpz != NULL); -+ -+ rpz_type = type_from_name(rpz, src_name); -+ -+ LOCK(&rpzs->maint_lock); -+ LOCK(&rpzs->search_lock); -+ -+ switch (rpz_type) { - case DNS_RPZ_TYPE_QNAME: -+ case DNS_RPZ_TYPE_NSDNAME: -+ result = add_name(rpzs, rpz_num, rpz_type, src_name); -+ break; -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ case DNS_RPZ_TYPE_IP: -+ case DNS_RPZ_TYPE_NSIP: -+ result = add_cidr(rpzs, rpz_num, rpz_type, src_name); -+ break; - case DNS_RPZ_TYPE_BAD: -- return; -+ break; - } - -+ UNLOCK(&rpzs->search_lock); -+ UNLOCK(&rpzs->maint_lock); -+ return (result); -+} -+ -+/* -+ * Remove an IP address from the radix tree. -+ */ -+static void -+del_cidr(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, dns_name_t *src_name) -+{ -+ isc_result_t result; -+ dns_rpz_cidr_key_t tgt_ip; -+ dns_rpz_prefix_t tgt_prefix; -+ dns_rpz_addr_zbits_t tgt_set; -+ dns_rpz_cidr_node_t *tgt, *parent, *child; -+ - /* -- * Do not get excited about the deletion of interior rbt nodes. -+ * Do not worry about invalid rpz IP address names. If we -+ * are here, then something relevant was added and so was -+ * valid. Invalid names here are usually internal RBTDB nodes. - */ -- result = name2ipkey(cidr, DNS_RPZ_DEBUG_QUIET, name, -- type, &tgt_ip, &tgt_prefix); -+ result = name2ipkey(DNS_RPZ_DEBUG_QUIET, rpzs, rpz_num, rpz_type, -+ src_name, &tgt_ip, &tgt_prefix, &tgt_set); - if (result != ISC_R_SUCCESS) - return; - -- result = search(cidr, &tgt_ip, tgt_prefix, type, ISC_FALSE, &tgt); -+ result = search(rpzs, &tgt_ip, tgt_prefix, &tgt_set, ISC_FALSE, &tgt); - if (result != ISC_R_SUCCESS) { -- badname(DNS_RPZ_ERROR_LEVEL, name, "; missing rpz node", ""); -+ INSIST(result == ISC_R_NOTFOUND || -+ result == DNS_R_PARTIALMATCH); -+ /* -+ * Do not worry about missing summary RBT nodes that probably -+ * correspond to RBTDB nodes that were implicit RBT nodes -+ * that were later added for (often empty) wildcards -+ * and then to the RBTDB deferred cleanup list. -+ */ - return; - } - - /* - * Mark the node and its parents to reflect the deleted IP address. -+ * Do not count bits that are already clear for internal RBTDB nodes. - */ -- flags = get_flags(&tgt_ip, tgt_prefix, type); -- data_flag = flags & (DNS_RPZ_CIDR_FG_IP_DATA | -- DNS_RPZ_CIDR_FG_NSIP_DATA); -- tgt->flags &= ~data_flag; -- for (parent = tgt; parent != NULL; parent = parent->parent) { -- if ((parent->flags & data_flag) != 0 || -- (parent->child[0] != NULL && -- (parent->child[0]->flags & flags) != 0) || -- (parent->child[1] != NULL && -- (parent->child[1]->flags & flags) != 0)) -- break; -- parent->flags &= ~flags; -- } -+ tgt_set.client_ip &= tgt->set.client_ip; -+ tgt_set.ip &= tgt->set.ip; -+ tgt_set.nsip &= tgt->set.nsip; -+ tgt->set.client_ip &= ~tgt_set.client_ip; -+ tgt->set.ip &= ~tgt_set.ip; -+ tgt->set.nsip &= ~tgt_set.nsip; -+ set_sum_pair(tgt); -+ -+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, &tgt_ip, tgt_prefix, ISC_FALSE); - - /* - * We might need to delete 2 nodes. -@@ -1054,13 +1754,14 @@ - */ - if ((child = tgt->child[0]) != NULL) { - if (tgt->child[1] != NULL) -- return; -+ break; - } else { - child = tgt->child[1]; - } -- if ((tgt->flags & (DNS_RPZ_CIDR_FG_IP_DATA | -- DNS_RPZ_CIDR_FG_NSIP_DATA)) != 0) -- return; -+ if (tgt->set.client_ip != 0 || -+ tgt->set.ip != 0 || -+ tgt->set.nsip != 0) -+ break; - - /* - * Replace the pointer to this node in the parent with -@@ -1068,7 +1769,7 @@ - */ - parent = tgt->parent; - if (parent == NULL) { -- cidr->root = child; -+ rpzs->cidr = child; - } else { - parent->child[parent->child[1] == tgt] = child; - } -@@ -1077,26 +1778,144 @@ - */ - if (child != NULL) - child->parent = parent; -- isc_mem_put(cidr->mctx, tgt, sizeof(*tgt)); -+ isc_mem_put(rpzs->mctx, tgt, sizeof(*tgt)); - - tgt = parent; - } while (tgt != NULL); - } - -+static void -+del_name(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_rpz_type_t rpz_type, dns_name_t *src_name) -+{ -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ dns_fixedname_t trig_namef; -+ dns_name_t *trig_name; -+ dns_rbtnode_t *nmnode; -+ dns_rpz_nm_data_t *nm_data, del_data; -+ isc_result_t result; -+ -+ dns_fixedname_init(&trig_namef); -+ trig_name = dns_fixedname_name(&trig_namef); -+ name2data(rpzs, rpz_num, rpz_type, src_name, trig_name, &del_data); -+ -+ /* -+ * No need for a summary database of names with only 1 policy zone. -+ */ -+ if (rpzs->p.num_zones <= 1) { -+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_FALSE); -+ return; -+ } -+ -+ nmnode = NULL; -+ result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL, 0, -+ NULL, NULL); -+ if (result != ISC_R_SUCCESS) { -+ /* -+ * Do not worry about missing summary RBT nodes that probably -+ * correspond to RBTDB nodes that were implicit RBT nodes -+ * that were later added for (often empty) wildcards -+ * and then to the RBTDB deferred cleanup list. -+ */ -+ if (result == ISC_R_NOTFOUND) -+ return; -+ dns_name_format(src_name, namebuf, sizeof(namebuf)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "rpz del_name(%s) node search failed: %s", -+ namebuf, isc_result_totext(result)); -+ return; -+ } -+ -+ nm_data = nmnode->data; -+ INSIST(nm_data != NULL); -+ -+ /* -+ * Do not count bits that next existed for RBT nodes that would we -+ * would not have found in a summary for a single RBTDB tree. -+ */ -+ del_data.set.qname &= nm_data->set.qname; -+ del_data.set.ns &= nm_data->set.ns; -+ del_data.wild.qname &= nm_data->wild.qname; -+ del_data.wild.ns &= nm_data->wild.ns; -+ -+ nm_data->set.qname &= ~del_data.set.qname; -+ nm_data->set.ns &= ~del_data.set.ns; -+ nm_data->wild.qname &= ~del_data.wild.qname; -+ nm_data->wild.ns &= ~del_data.wild.ns; -+ -+ if (nm_data->set.qname == 0 && nm_data->set.ns == 0 && -+ nm_data->wild.qname == 0 && nm_data->wild.ns == 0) { -+ result = dns_rbt_deletenode(rpzs->rbt, nmnode, ISC_FALSE); -+ if (result != ISC_R_SUCCESS) { -+ /* -+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". -+ */ -+ dns_name_format(src_name, namebuf, sizeof(namebuf)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "rpz del_name(%s) node delete failed: %s", -+ namebuf, isc_result_totext(result)); -+ } -+ } -+ -+ adj_trigger_cnt(rpzs, rpz_num, rpz_type, NULL, 0, ISC_FALSE); -+} -+ - /* -- * Caller must hold tree lock. -- * Return ISC_R_NOTFOUND -- * or ISC_R_SUCCESS and the found entry's canonical and search names -- * and its prefix length -+ * Remove an IP address from the radix tree or a name from the summary database. - */ --isc_result_t --dns_rpz_cidr_find(dns_rpz_cidr_t *cidr, const isc_netaddr_t *netaddr, -- dns_rpz_type_t type, dns_name_t *canon_name, -- dns_name_t *search_name, dns_rpz_cidr_bits_t *prefix) -+void -+dns_rpz_delete(dns_rpz_zones_t *rpzs, dns_rpz_num_t rpz_num, -+ dns_name_t *src_name) { -+ dns_rpz_zone_t *rpz; -+ dns_rpz_type_t rpz_type; -+ -+ REQUIRE(rpzs != NULL && rpz_num < rpzs->p.num_zones); -+ rpz = rpzs->zones[rpz_num]; -+ REQUIRE(rpz != NULL); -+ -+ rpz_type = type_from_name(rpz, src_name); -+ -+ LOCK(&rpzs->maint_lock); -+ LOCK(&rpzs->search_lock); -+ -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_QNAME: -+ case DNS_RPZ_TYPE_NSDNAME: -+ del_name(rpzs, rpz_num, rpz_type, src_name); -+ break; -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ case DNS_RPZ_TYPE_IP: -+ case DNS_RPZ_TYPE_NSIP: -+ del_cidr(rpzs, rpz_num, rpz_type, src_name); -+ break; -+ case DNS_RPZ_TYPE_BAD: -+ break; -+ } -+ -+ UNLOCK(&rpzs->search_lock); -+ UNLOCK(&rpzs->maint_lock); -+} -+ -+/* -+ * Search the summary radix tree to get a relative owner name in a -+ * policy zone relevant to a triggering IP address. -+ * rpz_type and zbits limit the search for IP address netaddr -+ * return the policy zone's number or DNS_RPZ_INVALID_NUM -+ * ip_name is the relative owner name found and -+ * *prefixp is its prefix length. -+ */ -+dns_rpz_num_t -+dns_rpz_find_ip(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t zbits, const isc_netaddr_t *netaddr, -+ dns_name_t *ip_name, dns_rpz_prefix_t *prefixp) - { - dns_rpz_cidr_key_t tgt_ip; -- isc_result_t result; -+ dns_rpz_addr_zbits_t tgt_set; - dns_rpz_cidr_node_t *found; -+ isc_result_t result; -+ dns_rpz_num_t rpz_num; - int i; - - /* -@@ -1107,29 +1926,163 @@ - tgt_ip.w[1] = 0; - tgt_ip.w[2] = ADDR_V4MAPPED; - tgt_ip.w[3] = ntohl(netaddr->type.in.s_addr); -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ zbits &= rpzs->have.client_ipv4; -+ break; -+ case DNS_RPZ_TYPE_IP: -+ zbits &= rpzs->have.ipv4; -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ zbits &= rpzs->have.nsipv4; -+ break; -+ default: -+ INSIST(0); -+ break; -+ } - } else if (netaddr->family == AF_INET6) { - dns_rpz_cidr_key_t src_ip6; - - /* - * Given the int aligned struct in_addr member of netaddr->type - * one could cast netaddr->type.in6 to dns_rpz_cidr_key_t *, -- * but there are objections. -+ * but some people object. - */ -- memmove(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w)); -+ memcpy(src_ip6.w, &netaddr->type.in6, sizeof(src_ip6.w)); - for (i = 0; i < 4; i++) { - tgt_ip.w[i] = ntohl(src_ip6.w[i]); - } -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ zbits &= rpzs->have.client_ipv6; -+ break; -+ case DNS_RPZ_TYPE_IP: -+ zbits &= rpzs->have.ipv6; -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ zbits &= rpzs->have.nsipv6; -+ break; -+ default: -+ INSIST(0); -+ break; -+ } - } else { -- return (ISC_R_NOTFOUND); -+ return (DNS_RPZ_INVALID_NUM); - } - -- result = search(cidr, &tgt_ip, 128, type, ISC_FALSE, &found); -- if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) -- return (result); -+ if (zbits == 0) -+ return (DNS_RPZ_INVALID_NUM); -+ make_addr_set(&tgt_set, zbits, rpz_type); -+ -+ LOCK(&rpzs->search_lock); -+ result = search(rpzs, &tgt_ip, 128, &tgt_set, ISC_FALSE, &found); -+ if (result == ISC_R_NOTFOUND) { -+ /* -+ * There are no eligible zones for this IP address. -+ */ -+ UNLOCK(&rpzs->search_lock); -+ return (DNS_RPZ_INVALID_NUM); -+ } - -- *prefix = found->bits; -- return (ip2name(cidr, &found->ip, found->bits, type, -- canon_name, search_name)); -+ /* -+ * Construct the trigger name for the longest matching trigger -+ * in the first eligible zone with a match. -+ */ -+ *prefixp = found->prefix; -+ switch (rpz_type) { -+ case DNS_RPZ_TYPE_CLIENT_IP: -+ rpz_num = zbit_to_num(found->set.client_ip & tgt_set.client_ip); -+ break; -+ case DNS_RPZ_TYPE_IP: -+ rpz_num = zbit_to_num(found->set.ip & tgt_set.ip); -+ break; -+ case DNS_RPZ_TYPE_NSIP: -+ rpz_num = zbit_to_num(found->set.nsip & tgt_set.nsip); -+ break; -+ default: -+ INSIST(0); -+ break; -+ } -+ result = ip2name(&found->ip, found->prefix, dns_rootname, ip_name); -+ UNLOCK(&rpzs->search_lock); -+ if (result != ISC_R_SUCCESS) { -+ /* -+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". -+ */ -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "rpz ip2name() failed: %s", -+ isc_result_totext(result)); -+ return (DNS_RPZ_INVALID_NUM); -+ } -+ return (rpz_num); -+} -+ -+/* -+ * Search the summary radix tree for policy zones with triggers matching -+ * a name. -+ */ -+dns_rpz_zbits_t -+dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, -+ dns_rpz_zbits_t zbits, dns_name_t *trig_name) -+{ -+ char namebuf[DNS_NAME_FORMATSIZE]; -+ dns_rbtnode_t *nmnode; -+ const dns_rpz_nm_data_t *nm_data; -+ dns_rpz_zbits_t found_zbits; -+ isc_result_t result; -+ -+ if (zbits == 0) -+ return (0); -+ -+ found_zbits = 0; -+ -+ LOCK(&rpzs->search_lock); -+ -+ nmnode = NULL; -+ result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, NULL, -+ DNS_RBTFIND_EMPTYDATA, NULL, NULL); -+ switch (result) { -+ case ISC_R_SUCCESS: -+ nm_data = nmnode->data; -+ if (nm_data != NULL) { -+ if (rpz_type == DNS_RPZ_TYPE_QNAME) -+ found_zbits = nm_data->set.qname; -+ else -+ found_zbits = nm_data->set.ns; -+ } -+ nmnode = nmnode->parent; -+ /* fall thru */ -+ case DNS_R_PARTIALMATCH: -+ while (nmnode != NULL) { -+ nm_data = nmnode->data; -+ if (nm_data != NULL) { -+ if (rpz_type == DNS_RPZ_TYPE_QNAME) -+ found_zbits |= nm_data->wild.qname; -+ else -+ found_zbits |= nm_data->wild.ns; -+ } -+ nmnode = nmnode->parent; -+ } -+ break; -+ -+ case ISC_R_NOTFOUND: -+ break; -+ -+ default: -+ /* -+ * bin/tests/system/rpz/tests.sh looks for "rpz.*failed". -+ */ -+ dns_name_format(trig_name, namebuf, sizeof(namebuf)); -+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RPZ, -+ DNS_LOGMODULE_RBTDB, DNS_RPZ_ERROR_LEVEL, -+ "dns_rpz_find_name(%s) failed: %s", -+ namebuf, isc_result_totext(result)); -+ break; -+ } -+ -+ UNLOCK(&rpzs->search_lock); -+ return (zbits & found_zbits); - } - - /* -@@ -1144,10 +2097,10 @@ - isc_result_t result; - - result = dns_rdataset_first(rdataset); -- RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ INSIST(result == ISC_R_SUCCESS); - dns_rdataset_current(rdataset, &rdata); - result = dns_rdata_tostruct(&rdata, &cname, NULL); -- RUNTIME_CHECK(result == ISC_R_SUCCESS); -+ INSIST(result == ISC_R_SUCCESS); - dns_rdata_reset(&rdata); - - /* -@@ -1174,7 +2127,19 @@ - } - - /* -- * CNAME PASSTHRU.origin means "do not rewrite. -+ * CNAME rpz-tcp-only. means "send truncated UDP responses." -+ */ -+ if (dns_name_equal(&cname.cname, &rpz->tcp_only)) -+ return (DNS_RPZ_POLICY_TCP_ONLY); -+ -+ /* -+ * CNAME rpz-drop. means "do not respond." -+ */ -+ if (dns_name_equal(&cname.cname, &rpz->drop)) -+ return (DNS_RPZ_POLICY_DROP); -+ -+ /* -+ * CNAME rpz-passthru. means "do not rewrite." - */ - if (dns_name_equal(&cname.cname, &rpz->passthru)) - return (DNS_RPZ_POLICY_PASSTHRU); -diff -r -u lib/dns/view.c-orig lib/dns/view.c ---- lib/dns/view.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/view.c 2004-01-01 00:00:00.000000000 +0000 -@@ -197,9 +197,7 @@ - view->maxbits = 0; - view->v4_aaaa = dns_v4_aaaa_ok; - view->v4_aaaa_acl = NULL; -- ISC_LIST_INIT(view->rpz_zones); -- view->rpz_recursive_only = ISC_TRUE; -- view->rpz_break_dnssec = ISC_FALSE; -+ view->rpzs = NULL; - dns_fixedname_init(&view->dlv_fixed); - view->managed_keys = NULL; - view->redirect = NULL; -@@ -336,7 +334,8 @@ - dns_acache_putdb(view->acache, view->cachedb); - dns_acache_detach(&view->acache); - } -- dns_rpz_view_destroy(view); -+ if (view->rpzs != NULL) -+ dns_rpz_detach_rpzs(&view->rpzs); - #ifdef USE_RRL - dns_rrl_view_destroy(view); - #else /* USE_RRL */ -diff -r -u lib/dns/xfrin.c-orig lib/dns/xfrin.c ---- lib/dns/xfrin.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/xfrin.c 2004-01-01 00:00:00.000000000 +0000 -@@ -279,7 +279,7 @@ - 0, NULL, /* XXX guess */ - dbp); - if (result == ISC_R_SUCCESS) -- result = dns_zone_rpz_enable_db(xfr->zone, *dbp); -+ dns_zone_rpz_enable_db(xfr->zone, *dbp); - return (result); - } - -diff -r -u lib/dns/zone.c-orig lib/dns/zone.c ---- lib/dns/zone.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/dns/zone.c 2004-01-01 00:00:00.000000000 +0000 -@@ -357,9 +357,10 @@ - isc_boolean_t added; - - /*% -- * whether this is a response policy zone -+ * response policy data to be relayed to the database - */ -- isc_boolean_t is_rpz; -+ dns_rpz_zones_t *rpzs; -+ dns_rpz_num_t rpz_num; - - /*% - * Serial number update method. -@@ -940,7 +941,8 @@ - zone->nodes = 100; - zone->privatetype = (dns_rdatatype_t)0xffffU; - zone->added = ISC_FALSE; -- zone->is_rpz = ISC_FALSE; -+ zone->rpzs = NULL; -+ zone->rpz_num = DNS_RPZ_INVALID_NUM; - ISC_LIST_INIT(zone->forwards); - zone->raw = NULL; - zone->secure = NULL; -@@ -1043,6 +1045,13 @@ - zone_detachdb(zone); - if (zone->acache != NULL) - dns_acache_detach(&zone->acache); -+#ifdef BIND9 -+ if (zone->rpzs != NULL) { -+ REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones); -+ dns_rpz_detach_rpzs(&zone->rpzs); -+ zone->rpz_num = DNS_RPZ_INVALID_NUM; -+ } -+#endif - zone_freedbargs(zone); - RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0) - == ISC_R_SUCCESS); -@@ -1535,7 +1544,9 @@ - * Set the response policy index and information for a zone. - */ - isc_result_t --dns_zone_rpz_enable(dns_zone_t *zone) { -+dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs, -+ dns_rpz_num_t rpz_num) -+{ - /* - * Only RBTDB zones can be used for response policy zones, - * because only they have the code to load the create the summary data. -@@ -1546,26 +1557,37 @@ - strcmp(zone->db_argv[0], "rbt64") != 0) - return (ISC_R_NOTIMPLEMENTED); - -- zone->is_rpz = ISC_TRUE; -+ /* -+ * This must happen only once or be redundant. -+ */ -+ LOCK_ZONE(zone); -+ if (zone->rpzs != NULL) { -+ REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num); -+ } else { -+ REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM); -+ dns_rpz_attach_rpzs(rpzs, &zone->rpzs); -+ zone->rpz_num = rpz_num; -+ } -+ rpzs->defined |= DNS_RPZ_ZBIT(rpz_num); -+ UNLOCK_ZONE(zone); - - return (ISC_R_SUCCESS); - } - --isc_boolean_t --dns_zone_get_rpz(dns_zone_t *zone) { -- return (zone->is_rpz); -+dns_rpz_num_t -+dns_zone_get_rpz_num(dns_zone_t *zone) { -+ return (zone->rpz_num); - } - - /* - * If a zone is a response policy zone, mark its new database. - */ --isc_result_t -+void - dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) { --#ifdef BIND9 -- if (zone->is_rpz) -- return (dns_db_rpz_enabled(db, NULL)); --#endif -- return (ISC_R_SUCCESS); -+ if (zone->rpz_num != DNS_RPZ_INVALID_NUM) { -+ REQUIRE(zone->rpzs != NULL); -+ dns_db_rpz_attach(db, zone->rpzs, zone->rpz_num); -+ } - } - - static isc_result_t -@@ -2025,9 +2047,7 @@ - isc_result_t tresult; - unsigned int options; - -- result = dns_zone_rpz_enable_db(zone, db); -- if (result != ISC_R_SUCCESS) -- return (result); -+ dns_zone_rpz_enable_db(zone, db); - options = get_master_options(zone); - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) - options |= DNS_MASTER_MANYERRORS; -@@ -4210,6 +4230,11 @@ - if (result != ISC_R_SUCCESS) - goto cleanup; - } else { -+#ifdef BIND9 -+ result = dns_db_rpz_ready(db); -+ if (result != ISC_R_SUCCESS) -+ goto cleanup; -+#endif - zone_attachdb(zone, db); - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); - DNS_ZONE_SETFLAG(zone, -@@ -13455,6 +13480,12 @@ - if (inline_raw(zone)) - REQUIRE(LOCKED_ZONE(zone->secure)); - -+#ifdef BIND9 -+ result = dns_db_rpz_ready(db); -+ if (result != ISC_R_SUCCESS) -+ return (result); -+#endif -+ - result = zone_get_from_db(zone, db, &nscount, &soacount, - NULL, NULL, NULL, NULL, NULL, NULL); - if (result == ISC_R_SUCCESS) { -diff -r -u lib/isccfg/namedconf.c-orig lib/isccfg/namedconf.c ---- lib/isccfg/namedconf.c-orig 2004-01-01 00:00:00.000000000 +0000 -+++ lib/isccfg/namedconf.c 2004-01-01 00:00:00.000000000 +0000 -@@ -1054,11 +1054,12 @@ - - /*% - * response-policy { -- * zone [ policy (given|disabled|passthru| -+ * zone [ policy (given|disabled|passthru|drop|tcp-only| - * nxdomain|nodata|cname ) ] - * [ recursive-only yes|no ] [ max-policy-ttl number ] ; - * } [ recursive-only yes|no ] [ max-policy-ttl number ] ; -- * [ break-dnssec yes|no ] [ min-ns-dots number ] ; -+ * [ break-dnssec yes|no ] [ min-ns-dots number ] -+ * [ qname-wait-recurse yes|no ] - */ - - static void -@@ -1083,7 +1084,7 @@ - - /* - * Parse -- * given|disabled|passthru|nxdomain|nodata|cname -+ * given|disabled|passthru|drop|tcp-only|nxdomain|nodata|cname - */ - static isc_result_t - cfg_parse_rpz_policy(cfg_parser_t *pctx, const cfg_type_t *type, -@@ -1214,9 +1215,12 @@ - doc_keyvalue, &cfg_rep_string, - &zone_kw - }; -+/* -+ * "no-op" is an obsolete equivalent of "passthru". -+ */ - static const char *rpz_policies[] = { -- "given", "disabled", "passthru", "no-op", "nxdomain", "nodata", -- "cname", NULL -+ "given", "disabled", "passthru", "no-op", "drop", "tcp-only", -+ "nxdomain", "nodata", "cname", NULL - }; - static cfg_type_t cfg_type_rpz_policy_name = { - "policy name", cfg_parse_enum, cfg_print_ustring, -@@ -1261,6 +1265,7 @@ - { "break-dnssec", &cfg_type_boolean, 0 }, - { "max-policy-ttl", &cfg_type_uint32, 0 }, - { "min-ns-dots", &cfg_type_uint32, 0 }, -+ { "qname-wait-recurse", &cfg_type_boolean, 0 }, - { NULL, NULL, 0 } - }; - static cfg_type_t cfg_type_rpz = { -diff -r -u version-orig version ---- version-orig 2004-01-01 00:00:00.000000000 +0000 -+++ version 2004-01-01 00:00:00.000000000 +0000 -@@ -7,7 +7,7 @@ - DESCRIPTION="(Extended Support Version)" - MAJORVER=9 - MINORVER=9 --PATCHVER=5 -+PATCHVER=5-rpz2+rl.14038.05 - RELEASETYPE=-P - RELEASEVER=1 - EXTENSIONS=