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 1785748..f0828d2 100644 --- a/baselibs.conf +++ b/baselibs.conf @@ -1,9 +1,25 @@ -bind-libs - obsoletes "bind-utils-" - provides "bind-utils-" -arch ppc package bind-devel - requires -bind- - requires "bind-libs- = " -arch sparcv9 package bind-devel - requires -bind- - requires "bind-libs- = " +libbind9-140 +libdns146 +libidnkit1 +libidnkitlite1 +libidnkitres1 +libirs141 +libisc142 + obsoletes "bind-libs- = " + provides "bind-libs- = " +libisccc140 +libisccfg140 +liblwres141 +bind-devel + requires -bind- + requires "libbind9-140- = " + requires "libdns146- = " + requires "libirs141- = " + requires "libisc142- = " + requires "libisccc140- = " + requires "libisccfg140- = " + requires "liblwres141- = " +idnkit-devel + requires "libdns146- = " + requires "libidnkit1- = " + requires "libidnkitlite1- = " diff --git a/bind-9.10.1-P1.tar.gz b/bind-9.10.1-P1.tar.gz new file mode 100644 index 0000000..e4c5158 --- /dev/null +++ b/bind-9.10.1-P1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:974343108d32f253a130383d0ba51290fb7bf372092f1451f264a9e3ac09898d +size 8356463 diff --git a/bind-9.10.1-P1.tar.gz.asc b/bind-9.10.1-P1.tar.gz.asc new file mode 100644 index 0000000..c3bb036 --- /dev/null +++ b/bind-9.10.1-P1.tar.gz.asc @@ -0,0 +1,12 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG/MacGPG2 v2.0.17 (Darwin) +Comment: GPGTools - http://gpgtools.org + +iQEcBAABAgAGBQJUbrEDAAoJEEWseFcYnNvFws8H/2I6YJNbUxY4rS6/alBUwIWy +N3oUSb290Szatl1sAUjlZ6SQbIgvKKxPRcp6HwKvhpecc+/Y0EAN43IWrGrndnoX +Fvfutn68I9cWCSFROnlOOlrmSFCs6Xg7OHZJy5mkf5cm9DflXYo3Xp6b1VCk7Z6j +jxuXGn7Uj4a/Ylk1ERV9ELl4qXugPj8J9bN+cjtr6iBl8yxXKwuZiiSDaZZf36w0 +SziClj2G8CA0UOGDu7XxPENJdJZPmS+sopxXWBpU7pL0EojcrFPbGENU9FtzHrjq +oVte/sQlrXfZXjo4op7tTeQH7d7PE6i01p+VJwG9YDtAQ3HA5jovSTBiiEtICfU= +=LVgj +-----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 c3f8227..62b6448 100644 --- a/bind.changes +++ b/bind.changes @@ -1,7 +1,257 @@ +------------------------------------------------------------------- +Thu Dec 11 13:03:30 UTC 2014 - jengelh@inai.de + +- Corrections to baselibs.conf + +------------------------------------------------------------------- +Tue Dec 9 21:45:10 UTC 2014 - lmuelle@suse.com + +- Update to version 9.10.1-P1 + - A flaw in delegation handling could be exploited to put named into an + infinite loop. This has been addressed by placing limits on the number of + levels of recursion named will allow (default 7), and the number of + iterative queries that it will send (default 50) before terminating a + recursive query (CVE-2014-8500); (bnc#908994). + The recursion depth limit is configured via the "max-recursion-depth" + option, and the query limit via the "max-recursion-queries" option. + [RT #37580] + - When geoip-directory was reconfigured during named run-time, the + previously loaded GeoIP data could remain, potentially causing wrong ACLs + to be used or wrong results to be served based on geolocation + (CVE-2014-8680). [RT #37720]; (bnc#908995). + - Lookups in GeoIP databases that were not loaded could cause an assertion + failure (CVE-2014-8680). [RT #37679]; (bnc#908995). + - The caching of GeoIP lookups did not always handle address families + correctly, potentially resulting in an assertion failure (CVE-2014-8680). + [RT #37672]; (bnc#908995). + +------------------------------------------------------------------- +Sun Dec 7 16:54:03 UTC 2014 - jengelh@inai.de + +- Convert some hard PreReq to leaner Requires(pre). +- Typographical and orthographic fixes to description texts. + +------------------------------------------------------------------- +Fri Dec 05 19:35:00 UTC 2014 - Led + +- Fix bashisms in the createNamedConfInclude script. +- Post scripts: remove '-e' option of 'echo' that may be unsupported + in some POSIX-compliant shells. + +------------------------------------------------------------------- +Fri Dec 5 14:54:53 UTC 2014 - lmuelle@suse.com + +- Add openssl engines to the lwresd chroot. +- Add /etc/lwresd.conf with attribute ghost to the list of files. +- Add /run/lwresd to the list of files of the lwresd package. +- Shift /run/named from the chroot sub to the main bind package. +- Drop /proc from the chroot as multi CPU systems work fine even without it. + +------------------------------------------------------------------- +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 +- Removed pid-path.diff patch as /run/{named,lwresd}/ are used by default. +- Update baselibs.conf (added libirs and library interface version updates). + +------------------------------------------------------------------- +Fri Nov 14 09:18:26 UTC 2014 - dimstar@opensuse.org + +- No longer perform gpg validation; osc source_validator does it + implicit: + + Drop gpg-offline BuildRequires. + + No longer execute gpg_verify. + +------------------------------------------------------------------- +Wed Oct 1 15:26:40 UTC 2014 - jengelh@inai.de + +- Implement shlib packaging guidelines and give an improved + description on the library components +- Put idnkit components in separate packages +- Add runidn.diff to resolve runidn not working at all + ------------------------------------------------------------------- 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 @@ -150,12 +400,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 @@ -240,7 +490,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 @@ -752,7 +1002,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 @@ -937,7 +1187,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 @@ -961,7 +1211,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) ------------------------------------------------------------------- @@ -998,7 +1248,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 @@ -1041,7 +1291,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 ------------------------------------------------------------------- @@ -1053,9 +1303,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 @@ -1104,7 +1354,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 @@ -1235,7 +1485,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) ------------------------------------------------------------------- @@ -1257,7 +1507,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 @@ -1287,7 +1537,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 ------------------------------------------------------------------- @@ -1607,7 +1857,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 @@ -1648,17 +1898,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 @@ -1701,7 +1951,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 @@ -1716,7 +1966,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 ------------------------------------------------------------------- @@ -1815,7 +2065,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 @@ -1830,7 +2080,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 @@ -1845,7 +2095,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 @@ -1877,7 +2127,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 1332d39..a87ce6d 100644 --- a/bind.spec +++ b/bind.spec @@ -18,7 +18,31 @@ Name: bind %define pkg_name bind -%define pkg_vers 9.9.5-P1 +%define pkg_vers 9.10.1-P1 +%define rpm_vers 9.10.1P1 +%define idn_vers 1.0 +Summary: Domain Name System (DNS) Server (named) +License: ISC +Group: Productivity/Networking/DNS/Servers +Version: %rpm_vers +Release: 0 + +Source: ftp://ftp.isc.org/isc/bind9/%{pkg_vers}/bind-%{pkg_vers}.tar.gz +Source3: ftp://ftp.isc.org/isc/bind9/%{pkg_vers}/bind-%{pkg_vers}.tar.gz.asc +# from http://www.isc.org/about/openpgp/ ... changes yearly apparently. +Source4: %name.keyring +Source1: vendor-files.tar.bz2 +Source2: baselibs.conf +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 +Patch4: perl-path.diff +Patch51: pie_compile.diff +Patch52: named-bootconf.diff +Patch53: bind-sdb-ldap.patch +Patch100: configure.in.diff2 +Patch101: runidn.diff BuildRequires: krb5-devel BuildRequires: libcap BuildRequires: libcap-devel @@ -30,44 +54,16 @@ BuildRequires: openssl BuildRequires: openssl-devel BuildRequires: python-base BuildRequires: update-desktop-files -Summary: Domain Name System (DNS) Server (named) -License: ISC -Group: Productivity/Networking/DNS/Servers -Version: 9.9.5P1 -Release: 0 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 +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 +Requires(pre): /usr/sbin/groupadd /usr/sbin/useradd /usr/sbin/usermod Url: http://isc.org/sw/bind/ -Source: ftp://ftp.isc.org/isc/bind9/%{pkg_vers}/bind-%{pkg_vers}.tar.gz -Source3: ftp://ftp.isc.org/isc/bind9/%{pkg_vers}/bind-%{pkg_vers}.tar.gz.asc -# from http://www.isc.org/about/openpgp/ ... changes yearly apparently. -Source4: %name.keyring -Source1: vendor-files.tar.bz2 -Source2: baselibs.conf -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 -Patch53: bind-sdb-ldap.patch -Patch100: configure.in.diff2 -%if 0%{?suse_version} > 1220 -BuildRequires: gpg-offline -%endif - -# 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 @@ -101,10 +97,194 @@ Name System (DNS) protocols and provides an openly redistributable reference implementation of the major components of the Domain Name System. This package includes the components to operate a DNS server. +%package -n idnkit +Summary: Toolkit for internationalized domain names +Group: Productivity/Networking/DNS/Utilities +Version: %idn_vers +Release: 0 +# Added on 2014-10-01 +Provides: bind-utils:%_bindir/idnconv +Provides: bind-utils:%_bindir/runidn + +%description -n idnkit +idnkit is a toolkit for handling internationalized domain names. It +consists of the following components. + +* library for handling internationalized domain names (libidnkit) +* codeset conversion utility (idnconv) +* a command which adds IDN feature dynamically to Unix applications + (runidn) + +%package -n idnkit-devel +Summary: Development files for idnkit +Group: Development/Libraries/C and C++ +Version: %idn_vers +Release: 0 +Provides: bind-devel:%_includedir/bind/idn +Requires: libidnkit1 = %idn_vers +Requires: libidnkitlite1 = %idn_vers +Requires: libidnkitres1 = %idn_vers + +%description -n idnkit-devel +idnkit is a toolkit for handling internationalized domain names. This +subpackage contains the header files needed for building programs +with it. + +%package -n libbind9-140 +Summary: BIND9 shared library used by BIND +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%description -n libbind9-140 +This library contains a few utility functions used by the BIND +server and utilities. + +%package -n libdns146 +Summary: DNS library used by BIND +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%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 +name resolution, it supports advanced features such as DNSSEC +validation and caching. This module supports both synchronous and +asynchronous mode. + +It also contains the Advanced Database (ADB) and Simple Database +(SDB) APIs. ADB allows user-written routines to replace BIND’s +internal database function for both nominated and all zones. SDB +allows a user-written driver to supply zone data either from +alternate data sources (for instance, a relational database) or using +specialized algorithms (for instance, for load-balancing). +[Book links for SDB: "Pro DNS and BIND 10", R. Aitchison, Apress] + +%package -n libidnkit1 +Summary: BIND Internationalized Domain Names library +Group: System/Libraries +Version: %idn_vers +Release: 0 + +%description -n libidnkit1 +The libidnkit library support various manipulations of +internationalized domain names. + +libidnkit internally uses iconv function to provide encoding +conversion from UTF-8 to the local encoding (such as ISO-8859-1, +usually determined by the current locale), and vise versa. + +%package -n libidnkitlite1 +Summary: BIND Internationalized Domain Names lightweight library +Group: System/Libraries +Version: %idn_vers +Release: 0 + +%description -n libidnkitlite1 +The libidnkitlite library support various manipulations of +internationalized domain names. + +libidnkitlite is lightweight version of libidnkit. It assumes local +encoding is UTF-8 so that it never uses iconv. + +%package -n libidnkitres1 +Summary: Resolver function library with IDN support +Group: System/Libraries +Version: %idn_vers +Release: 0 + +%description -n libidnkitres1 +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 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 used by BIND +Group: System/Libraries +Version: %rpm_vers +Release: 0 +# Added on 2014-10-01. Does not really matter where it is put, we just need to +# flush the old name from the rpmdb. The libs will be automatically pulled in +# by way of rpm symbol requirements already. +Obsoletes: bind-libs = %version-%release +Provides: bind-libs < %version-%release + +%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 libisccc140 +Summary: Command Channel Library used by BIND +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%description -n libisccc140 +This library is used for communicating with BIND servers' +administrative command channel (port 953 by default). + +%package -n libisccfg140 +Summary: Exported ISC configuration shared library +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%description -n libisccfg140 +This BIND library contains the configuration file parser + +%package -n liblwres141 +Summary: Lightweight Resolver API library +Group: System/Libraries +Version: %rpm_vers +Release: 0 + +%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 +lookup requests to a resolver daemon, lwresd, running on the local +host. The resover daemon performs the lookup using the DNS or +possibly other name service protocols, and returns the results to the +application through the library. The library and resolver daemon +communicate using a UDP-based protocol. + %package chrootenv Summary: Chroot environment for BIND named and lwresd Group: Productivity/Networking/DNS/Servers -PreReq: /usr/sbin/groupadd /usr/sbin/useradd +Version: %rpm_vers +Release: 0 +Requires(pre): /usr/sbin/groupadd /usr/sbin/useradd %description chrootenv This package contains all directories and files which are common to the @@ -114,16 +294,19 @@ structure below /var/lib/named. %package devel Summary: Development Libraries and Header Files of BIND Group: Development/Libraries/C and C++ -Requires: %{name}-libs = %{version} +Version: %rpm_vers +Release: 0 +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 @@ -134,6 +317,8 @@ System (DNS) protocols. %package doc Summary: BIND documentation Group: Documentation/Other +Version: %rpm_vers +Release: 0 %if 0%{?suse_version} >= 1120 BuildArch: noarch %endif @@ -143,26 +328,14 @@ Documentation of the Berkeley Internet Name Domain (BIND) Domain Name System implementation of the Domain Name System (DNS) protocols. This includes also the BIND Administrator Reference Manual (ARM). -%package libs -Summary: Shared libraries of BIND -Group: Development/Libraries/C and C++ -# bug437293 -%ifarch ppc64 -Obsoletes: bind-libs-64bit -%endif -# - -%description libs -This package contains the shared libraries of the Berkeley Internet -Name Domain (BIND) Domain Name System implementation of the Domain Name -System (DNS) protocols. - %package lwresd Summary: Lightweight Resolver Daemon Group: Productivity/Networking/DNS/Utilities +Version: %rpm_vers +Release: 0 Requires: %{name}-chrootenv Provides: dns_daemon -PreReq: /usr/sbin/groupadd /usr/sbin/useradd +Requires(pre): /usr/sbin/groupadd /usr/sbin/useradd %if %suse_version > 1131 PreReq: sysvinit(network) sysvinit(syslog) %endif @@ -178,16 +351,13 @@ protocol. %package utils Summary: Utilities to query and test DNS Group: Productivity/Networking/DNS/Utilities +Version: %rpm_vers +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 @@ -195,15 +365,11 @@ test and query the Domain Name System (DNS). The Berkeley Internet Name Domain (BIND) DNS server is found in the package named bind. %prep -%if 0%{?suse_version} > 1220 -%gpg_verify %{S:3} -%endif %setup -q -n %{pkg_name}-%{pkg_vers} #%setup -n %{pkg_name}-%{version} -T -D -a1 -a50 %setup -q -n %{pkg_name}-%{pkg_vers} -T -D -a1 %patch -p1 %patch1 -p1 -%patch2 -p0 %patch4 -p0 #%patch50 %if 0%{?suse_version} >= 1000 @@ -214,7 +380,7 @@ Name Domain (BIND) DNS server is found in the package named bind. %if 0%{?suse_version} <= 1010 %patch100 -p1 %endif -%patch200 -p0 +%patch101 -p1 # modify settings of some files regarding to OS version and vendor function replaceStrings() { @@ -222,8 +388,8 @@ function replaceStrings() sed -e "s@__NSD__@/lib@g" \ -e "s@__BIND_PACKAGE_NAME__@%{pkg_name}@g" \ -e "s@__VENDOR__@%{VENDOR}@g" \ - "${file}" >"${file}.new" && \ - mv "${file}.new" "${file}" + -e "s@___lib__@%{_lib}@g" \ + -i "${file}" } pushd vendor-files for file in docu/README tools/createNamedConfInclude config/{README,named.conf} init/{named,lwresd} sysconfig/{named-common,named-named,syslog-named}; do @@ -236,7 +402,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} @@ -267,15 +434,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} @@ -313,16 +480,16 @@ 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 \ ${RPM_BUILD_ROOT}/%{_defaultdocdir}/bind \ - ${RPM_BUILD_ROOT}/var/lib/named/{etc/named.d,dev,dyn,log,master,slave,var/{lib,run/named}} \ + ${RPM_BUILD_ROOT}/var/lib/named/{etc/named.d,dev,dyn,log,master,slave,var/{lib,run/{lwresd,named}}} \ ${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 @@ -355,8 +522,10 @@ touch ${RPM_BUILD_ROOT}/var/lib/named/dev/log ln -s ../.. ${RPM_BUILD_ROOT}/var/lib/named/var/lib/named ln -s ../log ${RPM_BUILD_ROOT}/var/lib/named/var %if "%_rundir" == "/run" +ln -s ../var/lib/named/var/run/lwresd ${RPM_BUILD_ROOT}/run ln -s ../var/lib/named/var/run/named ${RPM_BUILD_ROOT}/run %else +ln -s ../lib/named/var/run/lwresd ${RPM_BUILD_ROOT}/var/run ln -s ../lib/named/var/run/named ${RPM_BUILD_ROOT}/var/run %endif for file in named-common named-named syslog-named; do @@ -454,7 +623,7 @@ if [ -f etc/named.conf ] && grep -qi '^[[:space:]]*directory[[:space:]]*"/var/na echo -n "Backup old /etc/named.conf to " | tee -a ${CONVLOG} oldconfig=$( old etc/named.conf) 2>/dev/null oldconfig=${oldconfig##*/} - echo -en "/etc/${oldconfig}. Conversion " | tee -a ${CONVLOG} + echo -n "/etc/${oldconfig}. Conversion " | tee -a ${CONVLOG} sed -e "s@\"/var/named\"@\"/var/lib/named\"@" "etc/${oldconfig}" > etc/named.conf 2>/dev/null conv_rc=$? if [ ${conv_rc} -eq 0 ]; then @@ -508,7 +677,8 @@ if [ -s etc/named.conf.include -a -z "${NAMED_RUN_CHROOTED}" ]; then done TMPFILE=$( mktemp /var/tmp/named.sysconfig.XXXXXX) if [ $? -ne 0 ]; then - echo -e "Can't create temp file. Please add your included files from /etc/named.conf to\nNAMED_CONF_INCLUDE_FILES of /etc/sysconfig/named manually." + echo "Can't create temp file. Please add your included files from /etc/named.conf to" + echo "NAMED_CONF_INCLUDE_FILES of /etc/sysconfig/named manually." return fi chmod --reference=etc/sysconfig/named ${TMPFILE} @@ -537,6 +707,27 @@ fi %insserv_cleanup %service_del_postun named +%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 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} %{USERADD_NAMED} @@ -585,10 +776,6 @@ if [ -x usr/sbin/lwresd -a ! -f etc/rndc.key ]; then fi # --------------------------------------------------------------------------- -%post libs -p /sbin/ldconfig - -%postun libs -p /sbin/ldconfig - %files %defattr(-,root,root) %attr(0644,root,named) %config(noreplace) /%{_sysconfdir}/named.conf @@ -597,21 +784,25 @@ fi %attr(0644,root,named) %ghost /%{_sysconfdir}/named.conf.include %attr(0640,root,named) %ghost %config(noreplace) /%{_sysconfdir}/rndc.key %config /%{_sysconfdir}/init.d/named +%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/bind %{_bindir}/bind9-config %{_sbindir}/rcnamed %{_sbindir}/named %{_sbindir}/named-checkconf %{_sbindir}/named-checkzone %{_sbindir}/named-compilezone -%doc %{_mandir}/man1/bind9-config.1.gz -%doc %{_mandir}/man5/named.conf.5.gz -%doc %{_mandir}/man8/named-checkconf.8.gz -%doc %{_mandir}/man8/named-checkzone.8.gz -%doc %{_mandir}/man8/named.8.gz -%doc %{_mandir}/man8/named-compilezone.8.gz +%{_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 +%{_mandir}/man8/named.8.gz +%{_mandir}/man8/named-compilezone.8.gz %dir %{_datadir}/bind %{_datadir}/bind/createNamedConfInclude %{_datadir}/bind/ldapdump +%ghost %{_rundir}/named %{_var}/adm/fillup-templates/sysconfig.named-named %dir %{_var}/lib/named/master %attr(-,named,named) %dir %{_var}/lib/named/dyn @@ -621,7 +812,71 @@ fi %config %{_var}/lib/named/localhost.zone %ghost %{_var}/lib/named/etc/localtime %attr(0644,root,named) %ghost %{_var}/lib/named/etc/named.conf.include -%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/bind +%attr(-,named,named) %dir %{_var}/lib/named/var/run/named + +%files -n idnkit +%defattr(-,root,root) +%config(noreplace) %{_sysconfdir}/idn.conf +%config(noreplace) %{_sysconfdir}/idnalias.conf +%{_bindir}/idnconv +%{_bindir}/runidn +%{_mandir}/man1/idnconv.1.gz +%{_mandir}/man1/runidn.1.gz +%{_mandir}/man5/idn.conf.5.gz +%{_mandir}/man5/idnalias.conf.5.gz +%{_mandir}/man5/idnrc.5.gz +%{_datadir}/idnkit/ + +%files -n idnkit-devel +%defattr(-,root,root) +%dir %_includedir/bind/ +%_includedir/bind/idn/ +%_libdir/libidn*.so +%_mandir/man3/libidn*.3* + +%files -n libbind9-140 +%defattr(-,root,root) +%_libdir/libbind9.so.140* + +%files -n libdns146 +%defattr(-,root,root) +%_libdir/libdns.so.146* + +%files -n libidnkit1 +%defattr(-,root,root) +%_libdir/libidnkit.so.1* + +%files -n libidnkitlite1 +%defattr(-,root,root) +%_libdir/libidnkitlite.so.1* + +%files -n libidnkitres1 +%defattr(-,root,root) +%_libdir/libidnkitres.so.1* + +%files -n libirs141 +%defattr(-,root,root) +%_libdir/libirs.so.141* + +%files -n libirs-devel +%defattr(-,root,root) +%_libdir/libirs.so + +%files -n libisc142 +%defattr(-,root,root) +%_libdir/libisc.so.142* + +%files -n libisccc140 +%defattr(-,root,root) +%_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) @@ -633,55 +888,43 @@ fi %dir %{_var}/lib/named/var/lib %dir %{_var}/lib/named/var/run %attr(-,named,named) %dir %{_var}/lib/named/log -%attr(-,named,named) %dir %{_var}/lib/named/var/run/named %ghost %{_var}/lib/named/etc/named.d/rndc.access.conf %ghost %{_var}/lib/named/dev/log %attr(0666, root, root) %dev(c, 1, 3) %{_var}/lib/named/dev/null %attr(0666, root, root) %dev(c, 1, 8) %{_var}/lib/named/dev/random %{_var}/lib/named/var/lib/named %{_var}/lib/named/var/log -%ghost %{_rundir}/named %{_var}/adm/fillup-templates/sysconfig.named-common %{_var}/adm/fillup-templates/sysconfig.syslog-named %files devel %defattr(-,root,root) %{_bindir}/isc-config.sh -#%{_libdir}/*.a -%{_libdir}/*.so -#%{_libdir}/libbind.la -#%{_libdir}/libbind9.la -#%{_libdir}/libdns.la -#%{_libdir}/libidnkit.la -#%{_libdir}/libidnkitlite.la -#%{_libdir}/libisc.la -#%{_libdir}/libisccc.la -#%{_libdir}/libisccfg.la -#%{_libdir}/liblwres.la +%{_libdir}/libbind9.so +%{_libdir}/libdns.so +%{_libdir}/libisc*.so +%{_libdir}/liblwres.so %{_includedir}/bind -%doc %{_mandir}/man3/* +%exclude %{_includedir}/bind/idn +%{_mandir}/man3/lwres*.3* %files doc -f filelist-bind-doc %defattr(-,root,root) %dir %doc %{_defaultdocdir}/bind %doc %{_datadir}/susehelp -%files libs -%defattr(-,root,root) -%{_libdir}/*.so.* -#%{_libdir}/libidnkitres.la - %files lwresd %defattr(-,root,root) +%ghost %attr(0644,root,named) %config(noreplace) /%{_sysconfdir}/lwresd.conf %config /etc/init.d/lwresd %{_sbindir}/rclwresd %{_sbindir}/lwresd -%doc %{_mandir}/man8/lwresd.8.gz +%{_mandir}/man8/lwresd.8.gz +%ghost %{_rundir}/lwresd +%attr(-,named,named) %dir %{_var}/lib/named/var/run/lwresd %files utils %defattr(-,root,root) -%config(noreplace) %{_sysconfdir}/idn.conf -%config(noreplace) %{_sysconfdir}/idnalias.conf %dir /etc/named.d %config(noreplace) /etc/named.d/rndc-access.conf %config(noreplace) /etc/bind.keys @@ -689,13 +932,12 @@ 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}/idnconv %{_bindir}/nslookup %{_bindir}/nsupdate %{_bindir}/genDDNSkey -%{_bindir}/runidn %{_sbindir}/arpaname %{_sbindir}/ddns-confgen %if 0%{?suse_version} > 1110 @@ -716,40 +958,36 @@ fi %{_sbindir}/nsec3hash %{_sbindir}/rndc %{_sbindir}/rndc-confgen -%dir %{_datadir}/idnkit -%{_datadir}/idnkit/jp.map +%{_sbindir}/tsig-keygen %dir %doc %{_defaultdocdir}/bind %{_defaultdocdir}/bind/README.%{VENDOR} -%doc %{_mandir}/man1/arpaname.1.gz -%doc %{_mandir}/man1/dig.1.gz -%doc %{_mandir}/man1/host.1.gz -%doc %{_mandir}/man1/isc-config.sh.1.gz -%doc %{_mandir}/man1/nslookup.1.gz -%doc %{_mandir}/man1/nsupdate.1.gz -%doc %{_mandir}/man5/rndc.conf.5.gz -%doc %{_mandir}/man8/ddns-confgen.8.gz +%{_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 +%{_mandir}/man1/nslookup.1.gz +%{_mandir}/man1/nsupdate.1.gz +%{_mandir}/man5/rndc.conf.5.gz +%{_mandir}/man8/ddns-confgen.8.gz %if 0%{?suse_version} > 1110 -%doc %{_mandir}/man8/dnssec-checkds.8.gz -%doc %{_mandir}/man8/dnssec-coverage.8.gz +%{_mandir}/man8/dnssec-checkds.8.gz +%{_mandir}/man8/dnssec-coverage.8.gz %endif -%doc %{_mandir}/man8/dnssec-dsfromkey.8.gz -%doc %{_mandir}/man8/dnssec-keyfromlabel.8.gz -%doc %{_mandir}/man8/dnssec-keygen.8.gz -%doc %{_mandir}/man8/dnssec-revoke.8.gz -%doc %{_mandir}/man8/dnssec-settime.8.gz -%doc %{_mandir}/man8/dnssec-signzone.8.gz -%doc %{_mandir}/man8/dnssec-verify.8.gz -%doc %{_mandir}/man8/genrandom.8.gz -%doc %{_mandir}/man8/isc-hmac-fixup.8.gz -%doc %{_mandir}/man8/named-journalprint.8.gz -%doc %{_mandir}/man8/nsec3hash.8.gz -%doc %{_mandir}/man8/rndc.8.gz -%doc %{_mandir}/man8/rndc-confgen.8.gz -# idn kit -%doc %{_mandir}/man1/idnconv.1.gz -%doc %{_mandir}/man1/runidn.1.gz -%doc %{_mandir}/man5/idn.conf.5.gz -%doc %{_mandir}/man5/idnalias.conf.5.gz -%doc %{_mandir}/man5/idnrc.5.gz +%{_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 +%{_mandir}/man8/dnssec-settime.8.gz +%{_mandir}/man8/dnssec-signzone.8.gz +%{_mandir}/man8/dnssec-verify.8.gz +%{_mandir}/man8/genrandom.8.gz +%{_mandir}/man8/isc-hmac-fixup.8.gz +%{_mandir}/man8/named-journalprint.8.gz +%{_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= diff --git a/runidn.diff b/runidn.diff new file mode 100644 index 0000000..4769bb8 --- /dev/null +++ b/runidn.diff @@ -0,0 +1,34 @@ +From: Jan Engelhardt +Date: 2014-10-01 19:52:10.339340849 +0200 + +We do not normally ship the .la files in openSUSE; +make runidn work without it. +And do it portably (\$LIB), too, which the original runidn can't. +--- + contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: bind-9.9.5-P1/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in +=================================================================== +--- bind-9.9.5-P1.orig/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in ++++ bind-9.9.5-P1/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in +@@ -79,6 +79,7 @@ if test "$iconv_file" != none; then + preload="$iconv_file@PRELOAD_SEP@" + fi + ++if false; then + prefix=@prefix@ + exec_prefix=@exec_prefix@ + libdir=`echo @libdir@` +@@ -96,6 +97,11 @@ EOF + exit 1 + fi + preload=$preload$libdir/$dlname ++else ++prefix=$(echo "@prefix@") ++exec_prefix=$(echo "@exec_prefix@") ++preload="$exec_prefix/\$LIB/libidnkitres.so.1" ++fi + + # Set @PRELOAD_VAR@. + if [ X$@PRELOAD_VAR@ = X ]; then diff --git a/vendor-files.tar.bz2 b/vendor-files.tar.bz2 index a633361..5e259cb 100644 --- a/vendor-files.tar.bz2 +++ b/vendor-files.tar.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb6ae69f7d5b51be2e3b1755d38c793cb6f06460ea9ef5b98a4b0c7d86976cbb -size 21545 +oid sha256:c4f97ac0bc0800e12c6f870d651d15d507f00a35968deb16f1197f4b24b27b98 +size 22288