aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind9/bin/named
diff options
context:
space:
mode:
authorDoug Barton <dougb@FreeBSD.org>2011-07-16 11:12:09 +0000
committerDoug Barton <dougb@FreeBSD.org>2011-07-16 11:12:09 +0000
commit7afecc12f4d7b56f03438d5f41b837b9696f0a94 (patch)
tree7873e6a2dac5f9ddbfefa3b07f3cf0570f682321 /contrib/bind9/bin/named
parenta9285ae5c428d2017b1b907b8403ebe30f369bec (diff)
parent473038528ab5bd55332138ebf791ab91a25f747b (diff)
Upgrade to version 9.8.0-P4
This version has many new features, see /usr/share/doc/bind9/README for details.
Notes
Notes: svn path=/head/; revision=224092
Diffstat (limited to 'contrib/bind9/bin/named')
-rw-r--r--contrib/bind9/bin/named/Makefile.in33
-rw-r--r--contrib/bind9/bin/named/bind.keys.h99
-rw-r--r--contrib/bind9/bin/named/bind9.xsl2
-rw-r--r--contrib/bind9/bin/named/bind9.xsl.h4
-rw-r--r--contrib/bind9/bin/named/builtin.c205
-rw-r--r--contrib/bind9/bin/named/client.c130
-rw-r--r--contrib/bind9/bin/named/config.c74
-rw-r--r--contrib/bind9/bin/named/control.c11
-rw-r--r--contrib/bind9/bin/named/include/named/client.h17
-rw-r--r--contrib/bind9/bin/named/include/named/config.h7
-rw-r--r--contrib/bind9/bin/named/include/named/control.h9
-rw-r--r--contrib/bind9/bin/named/include/named/globals.h21
-rw-r--r--contrib/bind9/bin/named/include/named/log.h2
-rw-r--r--contrib/bind9/bin/named/include/named/lwdclient.h2
-rw-r--r--contrib/bind9/bin/named/include/named/main.h9
-rw-r--r--contrib/bind9/bin/named/include/named/notify.h2
-rw-r--r--contrib/bind9/bin/named/include/named/query.h17
-rw-r--r--contrib/bind9/bin/named/include/named/server.h53
-rw-r--r--contrib/bind9/bin/named/include/named/tsigconf.h7
-rw-r--r--contrib/bind9/bin/named/include/named/types.h6
-rw-r--r--contrib/bind9/bin/named/include/named/zoneconf.h19
-rw-r--r--contrib/bind9/bin/named/interfacemgr.c2
-rw-r--r--contrib/bind9/bin/named/log.c2
-rw-r--r--contrib/bind9/bin/named/lwdgabn.c6
-rw-r--r--contrib/bind9/bin/named/lwdgrbn.c6
-rw-r--r--contrib/bind9/bin/named/lwresd.82
-rw-r--r--contrib/bind9/bin/named/lwresd.c7
-rw-r--r--contrib/bind9/bin/named/lwresd.docbook2
-rw-r--r--contrib/bind9/bin/named/lwresd.html2
-rw-r--r--contrib/bind9/bin/named/main.c132
-rw-r--r--contrib/bind9/bin/named/named.811
-rw-r--r--contrib/bind9/bin/named/named.conf.567
-rw-r--r--contrib/bind9/bin/named/named.conf.docbook68
-rw-r--r--contrib/bind9/bin/named/named.conf.html92
-rw-r--r--contrib/bind9/bin/named/named.docbook17
-rw-r--r--contrib/bind9/bin/named/named.html26
-rw-r--r--contrib/bind9/bin/named/query.c2245
-rw-r--r--contrib/bind9/bin/named/server.c2454
-rw-r--r--contrib/bind9/bin/named/statschannel.c19
-rw-r--r--contrib/bind9/bin/named/tkeyconf.c28
-rw-r--r--contrib/bind9/bin/named/tsigconf.c10
-rw-r--r--contrib/bind9/bin/named/unix/Makefile.in4
-rw-r--r--contrib/bind9/bin/named/unix/include/named/os.h8
-rw-r--r--contrib/bind9/bin/named/unix/os.c186
-rw-r--r--contrib/bind9/bin/named/update.c1060
-rw-r--r--contrib/bind9/bin/named/xfrout.c204
-rw-r--r--contrib/bind9/bin/named/zoneconf.c531
47 files changed, 6553 insertions, 1367 deletions
diff --git a/contrib/bind9/bin/named/Makefile.in b/contrib/bind9/bin/named/Makefile.in
index ee7613435759..a3dbb3802dc9 100644
--- a/contrib/bind9/bin/named/Makefile.in
+++ b/contrib/bind9/bin/named/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2002 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.101 2008-09-23 17:25:47 jinmei Exp $
+# $Id: Makefile.in,v 1.114 2010-12-22 09:00:40 marka Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -43,9 +43,9 @@ DLZDRIVER_LIBS = @DLZ_DRIVER_LIBS@
CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include -I. \
${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
- ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES}
+ ${DLZDRIVER_INCLUDES} ${DBDRIVER_INCLUDES} @DST_OPENSSL_INC@
-CDEFINES = @USE_DLZ@
+CDEFINES = @USE_DLZ@ @USE_PKCS11@ @USE_OPENSSL@
CWARNINGS =
@@ -53,6 +53,7 @@ DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
ISCCCLIBS = ../../lib/isccc/libisccc.@A@
ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
LWRESLIBS = ../../lib/lwres/liblwres.@A@
BIND9LIBS = ../../lib/bind9/libbind9.@A@
@@ -70,6 +71,10 @@ LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \
${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
+NOSYMLIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCNOSYMLIBS} \
+ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
+
SUBDIRS = unix
TARGETS = named@EXEEXT@ lwresd@EXEEXT@
@@ -86,10 +91,12 @@ OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
UOBJS = unix/os.@O@
+SYMOBJS = symtbl.@O@
+
SRCS = builtin.c client.c config.c control.c \
controlconf.c interfacemgr.c \
listenlist.c log.c logconf.c main.c notify.c \
- query.c server.c sortlist.c statschannel.c \
+ query.c server.c sortlist.c statschannel.c symtbl.c symtbl-empty.c \
tkeyconf.c tsigconf.c update.c xfrout.c \
zoneconf.c \
lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
@@ -111,15 +118,20 @@ main.@O@: main.c
-DNS_LOCALSTATEDIR=\"${localstatedir}\" \
-DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c
-config.@O@: config.c
+bind.keys.h: ${top_srcdir}/bind.keys ${srcdir}/bindkeys.pl
+ ${PERL} ${srcdir}/bindkeys.pl < ${top_srcdir}/bind.keys > $@
+
+config.@O@: config.c bind.keys.h
${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
-DVERSION=\"${VERSION}\" \
-DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNS_SYSCONFDIR=\"${sysconfdir}\" \
-c ${srcdir}/config.c
named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
- ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
- ${OBJS} ${UOBJS} ${LIBS}
+ export MAKE_SYMTABLE="yes"; \
+ export BASEOBJS="${OBJS} ${UOBJS}"; \
+ ${FINALBUILDCMD}
lwresd@EXEEXT@: named@EXEEXT@
rm -f lwresd@EXEEXT@
@@ -133,7 +145,10 @@ docclean manclean maintainer-clean::
clean distclean maintainer-clean::
rm -f ${TARGETS} ${OBJS}
-bind9.xsl.h: bind9.xsl convertxsl.pl
+maintainer-clean::
+ rm -f bind.keys.h
+
+bind9.xsl.h: bind9.xsl ${srcdir}/convertxsl.pl
${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h
depend: bind9.xsl.h
diff --git a/contrib/bind9/bin/named/bind.keys.h b/contrib/bind9/bin/named/bind.keys.h
new file mode 100644
index 000000000000..0177214159e7
--- /dev/null
+++ b/contrib/bind9/bin/named/bind.keys.h
@@ -0,0 +1,99 @@
+/*
+ * Generated by bindkeys.pl 1.7 2011-01-04 23:47:13 tbox Exp
+ * From bind.keys 1.7 2011-01-03 23:45:07 each Exp
+ */
+#define TRUSTED_KEYS "\
+# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\
+# which are included as part of BIND 9. As of the current release, the only\n\
+# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\
+# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\
+# for any other zones MUST be configured elsewhere; if they are configured\n\
+# here, they will not be recognized or used by named.\n\
+#\n\
+# The built-in trust anchors are provided for convenience of configuration.\n\
+# They are not activated within named.conf unless specifically switched on.\n\
+# To use the built-in root key, set \"dnssec-validation auto;\" in\n\
+# named.conf options. To use the built-in DLV key, set\n\
+# \"dnssec-lookaside auto;\". Without these options being set,\n\
+# the keys in this file are ignored.\n\
+#\n\
+# This file is NOT expected to be user-configured.\n\
+#\n\
+# These keys are current as of January 2011. If any key fails to\n\
+# initialize correctly, it may have expired. In that event you should\n\
+# replace this file with a current version. The latest version of\n\
+# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\
+\n\
+trusted-keys {\n\
+ # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\
+ # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\
+ # in named.conf.\n\
+ dlv.isc.org. 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\
+ brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\
+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\
+ ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\
+ Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\
+ QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\
+ TDN0YUuWrBNh\";\n\
+\n\
+ # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\
+ # for current trust anchor information.\n\
+ # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\
+ # in named.conf.\n\
+ . 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\
+ QxA+Uk1ihz0=\";\n\
+};\n\
+"
+
+#define MANAGED_KEYS "\
+# The bind.keys file is used to override the built-in DNSSEC trust anchors\n\
+# which are included as part of BIND 9. As of the current release, the only\n\
+# trust anchors it contains are those for the DNS root zone (\".\"), and for\n\
+# the ISC DNSSEC Lookaside Validation zone (\"dlv.isc.org\"). Trust anchors\n\
+# for any other zones MUST be configured elsewhere; if they are configured\n\
+# here, they will not be recognized or used by named.\n\
+#\n\
+# The built-in trust anchors are provided for convenience of configuration.\n\
+# They are not activated within named.conf unless specifically switched on.\n\
+# To use the built-in root key, set \"dnssec-validation auto;\" in\n\
+# named.conf options. To use the built-in DLV key, set\n\
+# \"dnssec-lookaside auto;\". Without these options being set,\n\
+# the keys in this file are ignored.\n\
+#\n\
+# This file is NOT expected to be user-configured.\n\
+#\n\
+# These keys are current as of January 2011. If any key fails to\n\
+# initialize correctly, it may have expired. In that event you should\n\
+# replace this file with a current version. The latest version of\n\
+# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys.\n\
+\n\
+managed-keys {\n\
+ # ISC DLV: See https://www.isc.org/solutions/dlv for details.\n\
+ # NOTE: This key is activated by setting \"dnssec-lookaside auto;\"\n\
+ # in named.conf.\n\
+ dlv.isc.org. initial-key 257 3 5 \"BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2\n\
+ brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+\n\
+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5\n\
+ ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk\n\
+ Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM\n\
+ QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt\n\
+ TDN0YUuWrBNh\";\n\
+\n\
+ # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml\n\
+ # for current trust anchor information.\n\
+ # NOTE: This key is activated by setting \"dnssec-validation auto;\"\n\
+ # in named.conf.\n\
+ . initial-key 257 3 8 \"AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF\n\
+ FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX\n\
+ bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD\n\
+ X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz\n\
+ W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS\n\
+ Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq\n\
+ QxA+Uk1ihz0=\";\n\
+};\n\
+"
diff --git a/contrib/bind9/bin/named/bind9.xsl b/contrib/bind9/bin/named/bind9.xsl
index 71d2eba108d2..5913c1cc2000 100644
--- a/contrib/bind9/bin/named/bind9.xsl
+++ b/contrib/bind9/bin/named/bind9.xsl
@@ -15,7 +15,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: bind9.xsl,v 1.19.82.2 2009-01-29 23:47:43 tbox Exp $ -->
+<!-- $Id: bind9.xsl,v 1.21 2009-01-27 23:47:54 tbox Exp $ -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
diff --git a/contrib/bind9/bin/named/bind9.xsl.h b/contrib/bind9/bin/named/bind9.xsl.h
index d68675131eb9..b6f1f5491b95 100644
--- a/contrib/bind9/bin/named/bind9.xsl.h
+++ b/contrib/bind9/bin/named/bind9.xsl.h
@@ -1,6 +1,6 @@
/*
* Generated by convertxsl.pl 1.14 2008-07-17 23:43:26 jinmei Exp
- * From bind9.xsl 1.19.82.2 2009-01-29 23:47:43 tbox Exp
+ * From bind9.xsl 1.21 2009-01-27 23:47:54 tbox Exp
*/
static char xslmsg[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -20,7 +20,7 @@ static char xslmsg[] =
" - PERFORMANCE OF THIS SOFTWARE.\n"
"-->\n"
"\n"
- "<!-- \045Id: bind9.xsl,v 1.19.82.2 2009-01-29 23:47:43 tbox Exp \045 -->\n"
+ "<!-- \045Id: bind9.xsl,v 1.21 2009-01-27 23:47:54 tbox Exp \045 -->\n"
"\n"
"<xsl:stylesheet version=\"1.0\"\n"
" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n"
diff --git a/contrib/bind9/bin/named/builtin.c b/contrib/bind9/bin/named/builtin.c
index 60cb634fabd3..d7730e7afed0 100644
--- a/contrib/bind9/bin/named/builtin.c
+++ b/contrib/bind9/bin/named/builtin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: builtin.c,v 1.12.334.3 2010-08-03 23:45:47 tbox Exp $ */
+/* $Id: builtin.c,v 1.20 2011-01-07 23:47:07 tbox Exp $ */
/*! \file
* \brief
@@ -47,6 +47,7 @@ static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_dns64_lookup(dns_sdblookup_t *lookup);
/*
* We can't use function pointers as the db_data directly
@@ -65,9 +66,179 @@ static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
+static builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
static dns_sdbimplementation_t *builtin_impl;
+static const char hex[] = "0123456789abcdef";
+static const char HEX[] = "0123456789ABCDEF";
+
+static isc_result_t
+dns64_cname(const char *zone, const char *name, dns_sdblookup_t *lookup) {
+ size_t zlen, nlen, j;
+ const char *s;
+ unsigned char v[16];
+ unsigned int i;
+ char reverse[sizeof("123.123.123.123.in-addr.arpa.")];
+
+ /*
+ * The sum the length of the relative name and the length of the zone
+ * name for a IPv6 reverse lookup comes to 71.
+ *
+ * The reverse of 2001::10.0.0.1 (dns64 2001::/96) has a zone of
+ * "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2.ip6.arpa"
+ * and a name of "1.0.0.0.0.0.a.0". The sum of the lengths of these
+ * two strings is 71.
+ *
+ * The minimum length for a ip6.arpa zone name is 8.
+ *
+ * The length of name should always be odd as we are expecting
+ * a series of nibbles.
+ */
+ zlen = strlen(zone);
+ nlen = strlen(name);
+ if ((zlen + nlen) > 71U || zlen < 8U || (nlen % 2) != 1U)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * We assume the zone name is well formed.
+ */
+
+ /*
+ * XXXMPA We could check the dns64 suffix here if we need to.
+ */
+ /*
+ * Check that name is a series of nibbles.
+ * Compute the byte values that correspond to the nibbles as we go.
+ *
+ * Shift the final result 4 bits, by setting 'i' to 1, if we if we
+ * have a odd number of nibbles so that "must be zero" tests below
+ * are byte aligned and we correctly return ISC_R_NOTFOUND or
+ * ISC_R_SUCCESS. We will not generate a CNAME in this case.
+ */
+ i = (nlen % 4) == 1U ? 1 : 0;
+ j = nlen;
+ memset(v, 0, sizeof(v));
+ while (j >= 1U) {
+ INSIST((i/2) < sizeof(v));
+ if (j > 1U && name[1] != '.')
+ return (ISC_R_NOTFOUND);
+ v[i/2] >>= 4;
+ if ((s = strchr(hex, name[0])) != NULL)
+ v[i/2] |= (s - hex) << 4;
+ else if ((s = strchr(HEX, name[0])) != NULL)
+ v[i/2] |= (s - HEX) << 4;
+ else
+ return (ISC_R_NOTFOUND);
+ if (j > 1U)
+ j -= 2;
+ else
+ j -= 1;
+ name += 2;
+ i++;
+ }
+
+ /*
+ * If we get here then we know name only consisted of nibbles.
+ * Now we need to determine if the name exists or not and whether
+ * it corresponds to a empty node in the zone or there should be
+ * a CNAME.
+ */
+ switch (zlen) {
+ case 24: /* prefix len 32 */
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[8], v[9], v[10], v[11]);
+ break;
+ case 28: /* prefix len 40 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 11U && v[nlen/4 - 3] != 0)
+ return (ISC_R_NOTFOUND);
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[6], v[8], v[9], v[10]);
+ break;
+ case 32: /* prefix len 48 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 7U && v[nlen/4 - 2] != 0)
+ return (ISC_R_NOTFOUND);
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[5], v[6], v[8], v[9]);
+ break;
+ case 36: /* prefix len 56 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (nlen > 3U && v[nlen/4 - 1] != 0)
+ return (ISC_R_NOTFOUND);
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[4], v[5], v[6], v[8]);
+ break;
+ case 40: /* prefix len 64 */
+ /*
+ * The nibbles that map to this byte must be zero for 'name'
+ * to exist in the zone.
+ */
+ if (v[nlen/4] != 0)
+ return (ISC_R_NOTFOUND);
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[3], v[4], v[5], v[6]);
+ break;
+ case 56: /* prefix len 96 */
+ /*
+ * If the total length is not 71 then this is a empty node
+ * so return success.
+ */
+ if (nlen + zlen != 71U)
+ return (ISC_R_SUCCESS);
+ snprintf(reverse, sizeof(reverse), "%u.%u.%u.%u.in-addr.arpa.",
+ v[0], v[1], v[2], v[3]);
+ break;
+ default:
+ /*
+ * This should never be reached unless someone adds a
+ * zone declaration with this internal type to named.conf.
+ */
+ return (ISC_R_NOTFOUND);
+ }
+ return (dns_sdb_putrr(lookup, "CNAME", 600, reverse));
+}
+
static isc_result_t
builtin_lookup(const char *zone, const char *name, void *dbdata,
dns_sdblookup_t *lookup)
@@ -78,6 +249,8 @@ builtin_lookup(const char *zone, const char *name, void *dbdata,
if (strcmp(name, "@") == 0)
return (b->do_lookup(lookup));
+ else if (b->do_lookup == do_dns64_lookup)
+ return (dns64_cname(zone, name, lookup));
else
return (ISC_R_NOTFOUND);
}
@@ -132,11 +305,13 @@ do_authors_lookup(dns_sdblookup_t *lookup) {
"Michael Graff",
"Andreas Gustafsson",
"Bob Halley",
+ "Evan Hunt",
"JINMEI Tatuya",
"David Lawrence",
"Danny Mayer",
"Damien Neil",
"Matt Nelson",
+ "Jeremy C. Reed",
"Michael Sawyer",
"Brian Wellington",
NULL
@@ -174,6 +349,12 @@ do_id_lookup(dns_sdblookup_t *lookup) {
}
static isc_result_t
+do_dns64_lookup(dns_sdblookup_t *lookup) {
+ UNUSED(lookup);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
do_empty_lookup(dns_sdblookup_t *lookup) {
UNUSED(lookup);
@@ -220,7 +401,7 @@ builtin_create(const char *zone, int argc, char **argv,
UNUSED(zone);
UNUSED(driverdata);
- if (strcmp(argv[0], "empty") == 0) {
+ if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) {
if (argc != 3)
return (DNS_R_SYNTAX);
} else if (argc != 1)
@@ -234,7 +415,8 @@ builtin_create(const char *zone, int argc, char **argv,
*dbdata = &authors_builtin;
else if (strcmp(argv[0], "id") == 0)
*dbdata = &id_builtin;
- else if (strcmp(argv[0], "empty") == 0) {
+ else if (strcmp(argv[0], "empty") == 0 ||
+ strcmp(argv[0], "dns64") == 0) {
builtin_t *empty;
char *server;
char *contact;
@@ -246,7 +428,10 @@ builtin_create(const char *zone, int argc, char **argv,
server = isc_mem_strdup(ns_g_mctx, argv[1]);
contact = isc_mem_strdup(ns_g_mctx, argv[2]);
if (empty == NULL || server == NULL || contact == NULL) {
- *dbdata = &empty_builtin;
+ if (strcmp(argv[0], "empty") == 0)
+ *dbdata = &empty_builtin;
+ else
+ *dbdata = &dns64_builtin;
if (server != NULL)
isc_mem_free(ns_g_mctx, server);
if (contact != NULL)
@@ -254,7 +439,12 @@ builtin_create(const char *zone, int argc, char **argv,
if (empty != NULL)
isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
} else {
- memcpy(empty, &empty_builtin, sizeof (empty_builtin));
+ if (strcmp(argv[0], "empty") == 0)
+ memcpy(empty, &empty_builtin,
+ sizeof (empty_builtin));
+ else
+ memcpy(empty, &dns64_builtin,
+ sizeof (empty_builtin));
empty->server = server;
empty->contact = contact;
*dbdata = empty;
@@ -276,7 +466,7 @@ builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
*/
if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
*dbdata == &authors_builtin || *dbdata == &id_builtin ||
- *dbdata == &empty_builtin)
+ *dbdata == &empty_builtin || *dbdata == &dns64_builtin)
return;
isc_mem_free(ns_g_mctx, b->server);
@@ -306,3 +496,4 @@ void
ns_builtin_deinit(void) {
dns_sdb_unregister(&builtin_impl);
}
+
diff --git a/contrib/bind9/bin/named/client.c b/contrib/bind9/bin/named/client.c
index 6236d27f28a0..bc9cc878adbc 100644
--- a/contrib/bind9/bin/named/client.c
+++ b/contrib/bind9/bin/named/client.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: client.c,v 1.259.12.5 2010-09-24 08:30:27 tbox Exp $ */
+/* $Id: client.c,v 1.271 2011-01-11 23:47:12 tbox Exp $ */
#include <config.h>
@@ -918,7 +918,7 @@ ns_client_send(ns_client_t *client) {
dns_compress_t cctx;
isc_boolean_t cleanup_cctx = ISC_FALSE;
unsigned char sendbuf[SEND_BUFFER_SIZE];
- unsigned int dnssec_opts;
+ unsigned int render_opts;
unsigned int preferred_glue;
isc_boolean_t opt_included = ISC_FALSE;
@@ -930,10 +930,21 @@ ns_client_send(ns_client_t *client) {
client->message->flags |= DNS_MESSAGEFLAG_RA;
if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
- dnssec_opts = 0;
+ render_opts = 0;
else
- dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
-
+ render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ /*
+ * filter-aaaa-on-v4 yes or break-dnssec option to suppress
+ * AAAA records
+ * We already know that request came via IPv4,
+ * that we have both AAAA and A records,
+ * and that we either have no signatures that the client wants
+ * or we are supposed to break DNSSEC.
+ */
+ if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0)
+ render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
+#endif
preferred_glue = 0;
if (client->view != NULL) {
if (client->view->preferred_glue == dns_rdatatype_a)
@@ -977,7 +988,7 @@ ns_client_send(ns_client_t *client) {
result = dns_message_rendersection(client->message,
DNS_SECTION_ANSWER,
DNS_MESSAGERENDER_PARTIAL |
- dnssec_opts);
+ render_opts);
if (result == ISC_R_NOSPACE) {
client->message->flags |= DNS_MESSAGEFLAG_TC;
goto renderend;
@@ -987,7 +998,7 @@ ns_client_send(ns_client_t *client) {
result = dns_message_rendersection(client->message,
DNS_SECTION_AUTHORITY,
DNS_MESSAGERENDER_PARTIAL |
- dnssec_opts);
+ render_opts);
if (result == ISC_R_NOSPACE) {
client->message->flags |= DNS_MESSAGEFLAG_TC;
goto renderend;
@@ -996,7 +1007,7 @@ ns_client_send(ns_client_t *client) {
goto done;
result = dns_message_rendersection(client->message,
DNS_SECTION_ADDITIONAL,
- preferred_glue | dnssec_opts);
+ preferred_glue | render_opts);
if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
goto done;
renderend:
@@ -1355,7 +1366,6 @@ client_request(isc_task_t *task, isc_event_t *event) {
dns_name_t *signame;
isc_boolean_t ra; /* Recursion available. */
isc_netaddr_t netaddr;
- isc_netaddr_t destaddr;
int match;
dns_messageid_t id;
unsigned int flags;
@@ -1473,7 +1483,7 @@ client_request(isc_task_t *task, isc_event_t *event) {
/*
* Silently drop multicast requests for the present.
- * XXXMPA look at when/if mDNS spec stabilizes.
+ * XXXMPA revisit this as mDNS spec was published.
*/
if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
@@ -1647,24 +1657,20 @@ client_request(isc_task_t *task, isc_event_t *event) {
* etc), we regard this as an error for safety.
*/
if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
- isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
+ isc_netaddr_fromsockaddr(&client->destaddr,
+ &client->interface->addr);
else {
+ isc_sockaddr_t sockaddr;
result = ISC_R_FAILURE;
- if (TCP_CLIENT(client)) {
- isc_sockaddr_t destsockaddr;
-
+ if (TCP_CLIENT(client))
result = isc_socket_getsockname(client->tcpsocket,
- &destsockaddr);
- if (result == ISC_R_SUCCESS)
- isc_netaddr_fromsockaddr(&destaddr,
- &destsockaddr);
- }
+ &sockaddr);
+ if (result == ISC_R_SUCCESS)
+ isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
if (result != ISC_R_SUCCESS &&
client->interface->addr.type.sa.sa_family == AF_INET6 &&
(client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
- isc_uint32_t zone = 0;
-
/*
* XXXJT technically, we should convert the receiving
* interface ID to a proper scope zone ID. However,
@@ -1673,12 +1679,11 @@ client_request(isc_task_t *task, isc_event_t *event) {
* interface index as link ID. Despite the assumption,
* it should cover most typical cases.
*/
- if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
- zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex;
-
- isc_netaddr_fromin6(&destaddr,
+ isc_netaddr_fromin6(&client->destaddr,
&client->pktinfo.ipi6_addr);
- isc_netaddr_setzone(&destaddr, zone);
+ if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
+ isc_netaddr_setzone(&client->destaddr,
+ client->pktinfo.ipi6_ifindex);
result = ISC_R_SUCCESS;
}
if (result != ISC_R_SUCCESS) {
@@ -1708,7 +1713,8 @@ client_request(isc_task_t *task, isc_event_t *event) {
tsig = dns_tsigkey_identity(client->message->tsigkey);
if (allowed(&netaddr, tsig, view->matchclients) &&
- allowed(&destaddr, tsig, view->matchdestinations) &&
+ allowed(&client->destaddr, tsig,
+ view->matchdestinations) &&
!((client->message->flags & DNS_MESSAGEFLAG_RD)
== 0 && view->matchrecursiveonly))
{
@@ -1771,9 +1777,11 @@ client_request(isc_task_t *task, isc_event_t *event) {
}
if (result == ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(&client->signername, namebuf, sizeof(namebuf));
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
- "request has valid signature");
+ "request has valid signature: %s", namebuf);
client->signer = &client->signername;
} else if (result == ISC_R_NOTFOUND) {
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
@@ -1861,10 +1869,10 @@ client_request(isc_task_t *task, isc_event_t *event) {
ns_client_checkaclsilent(client, NULL,
client->view->cacheacl,
ISC_TRUE) == ISC_R_SUCCESS &&
- ns_client_checkaclsilent(client, &client->interface->addr,
+ ns_client_checkaclsilent(client, &client->destaddr,
client->view->recursiononacl,
ISC_TRUE) == ISC_R_SUCCESS &&
- ns_client_checkaclsilent(client, &client->interface->addr,
+ ns_client_checkaclsilent(client, &client->destaddr,
client->view->cacheonacl,
ISC_TRUE) == ISC_R_SUCCESS)
ra = ISC_TRUE;
@@ -2600,12 +2608,12 @@ ns_client_getsockaddr(ns_client_t *client) {
}
isc_result_t
-ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr,
+ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
dns_acl_t *acl, isc_boolean_t default_allow)
{
isc_result_t result;
+ isc_netaddr_t tmpnetaddr;
int match;
- isc_netaddr_t netaddr;
if (acl == NULL) {
if (default_allow)
@@ -2614,15 +2622,13 @@ ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr,
goto deny;
}
+ if (netaddr == NULL) {
+ isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
+ netaddr = &tmpnetaddr;
+ }
- if (sockaddr == NULL)
- isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
- else
- isc_netaddr_fromsockaddr(&netaddr, sockaddr);
-
- result = dns_acl_match(&netaddr, client->signer, acl,
- &ns_g_server->aclenv,
- &match, NULL);
+ result = dns_acl_match(netaddr, client->signer, acl,
+ &ns_g_server->aclenv, &match, NULL);
if (result != ISC_R_SUCCESS)
goto deny; /* Internal error, already logged. */
@@ -2642,8 +2648,14 @@ ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
const char *opname, dns_acl_t *acl,
isc_boolean_t default_allow, int log_level)
{
- isc_result_t result =
- ns_client_checkaclsilent(client, sockaddr, acl, default_allow);
+ isc_result_t result;
+ isc_netaddr_t netaddr;
+
+ if (sockaddr != NULL)
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+
+ result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
+ acl, default_allow);
if (result == ISC_R_SUCCESS)
ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
@@ -2753,9 +2765,14 @@ void
ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
ns_client_t *client;
char namebuf[DNS_NAME_FORMATSIZE];
+ char original[DNS_NAME_FORMATSIZE];
char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
const char *name;
const char *sep;
+ const char *origfor;
+ dns_rdataset_t *rdataset;
REQUIRE(VALID_MANAGER(manager));
@@ -2773,8 +2790,31 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
sep = "";
}
dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
- fprintf(f, "; client %s%s%s: '%s' requesttime %d\n",
- peerbuf, sep, name, namebuf, client->requesttime);
+ if (client->query.qname != client->query.origqname &&
+ client->query.origqname != NULL) {
+ origfor = " for ";
+ dns_name_format(client->query.origqname, original,
+ sizeof(original));
+ } else {
+ origfor = "";
+ original[0] = '\0';
+ }
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ if (rdataset == NULL && client->query.origqname != NULL)
+ rdataset = ISC_LIST_HEAD(client->query.origqname->list);
+ if (rdataset != NULL) {
+ dns_rdatatype_format(rdataset->type, typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass, classbuf,
+ sizeof(classbuf));
+ } else {
+ strcpy(typebuf, "-");
+ strcpy(classbuf, "-");
+ }
+ fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
+ "requesttime %d\n", peerbuf, sep, name,
+ client->message->id, namebuf, typebuf, classbuf,
+ origfor, original, client->requesttime);
client = ISC_LIST_NEXT(client, link);
}
UNLOCK(&manager->lock);
diff --git a/contrib/bind9/bin/named/config.c b/contrib/bind9/bin/named/config.c
index 43d0e5287d04..704d7ecc55ef 100644
--- a/contrib/bind9/bin/named/config.c
+++ b/contrib/bind9/bin/named/config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.c,v 1.93.14.2 2009-03-17 23:47:28 tbox Exp $ */
+/* $Id: config.c,v 1.113.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */
/*! \file */
@@ -42,9 +42,13 @@
#include <dns/tsig.h>
#include <dns/zone.h>
+#include <dst/dst.h>
+
#include <named/config.h>
#include <named/globals.h>
+#include "bind.keys.h"
+
/*% default configuration */
static char defaultconf[] = "\
options {\n\
@@ -55,7 +59,10 @@ options {\n\
files unlimited;\n\
stacksize default;\n"
#endif
-" deallocate-on-exit true;\n\
+"# session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\
+ session-keyname local-ddns;\n\
+ session-keyalg hmac-sha256;\n\
+ deallocate-on-exit true;\n\
# directory <none>\n\
dump-file \"named_dump.db\";\n\
fake-iquery no;\n\
@@ -70,8 +77,10 @@ options {\n\
multiple-cnames no;\n\
# named-xfer <obsolete>;\n\
# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
+ bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
port 53;\n\
recursing-file \"named.recursing\";\n\
+ secroots-file \"named.secroots\";\n\
"
#ifdef PATH_RANDOMDEV
"\
@@ -80,6 +89,7 @@ options {\n\
#endif
"\
recursive-clients 1000;\n\
+ resolver-query-timeout 30;\n\
rrset-order {type NS order random; order cyclic; };\n\
serial-queries 20;\n\
serial-query-rate 20;\n\
@@ -102,6 +112,9 @@ options {\n\
request-nsid false;\n\
reserved-sockets 512;\n\
\n\
+ /* DLV */\n\
+ dnssec-lookaside . trust-anchor dlv.isc.org;\n\
+\n\
/* view */\n\
allow-notify {none;};\n\
allow-update-forwarding {none;};\n\
@@ -135,6 +148,7 @@ options {\n\
check-names master fail;\n\
check-names slave warn;\n\
check-names response ignore;\n\
+ check-dup-records warn;\n\
check-mx warn;\n\
acache-enable no;\n\
acache-cleaning-interval 60;\n\
@@ -146,7 +160,13 @@ options {\n\
max-clients-per-query 100;\n\
zero-no-soa-ttl-cache no;\n\
nsec3-test-zone no;\n\
+ allow-new-zones no;\n\
+"
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+" filter-aaaa-on-v4 no;\n\
+ filter-aaaa { any; };\n\
"
+#endif
" /* zone */\n\
allow-query {any;};\n\
@@ -174,6 +194,7 @@ options {\n\
max-refresh-time 2419200; /* 4 weeks */\n\
min-refresh-time 300;\n\
multi-master no;\n\
+ dnssec-secure-to-insecure no;\n\
sig-validity-interval 30; /* days */\n\
sig-signing-nodes 100;\n\
sig-signing-signatures 10;\n\
@@ -188,6 +209,7 @@ options {\n\
check-srv-cname warn;\n\
zero-no-soa-ttl yes;\n\
update-check-ksk yes;\n\
+ dnssec-dnskey-kskonly no;\n\
try-tcp-refresh yes; /* BIND 8 compat */\n\
};\n\
"
@@ -198,6 +220,7 @@ options {\n\
view \"_bind\" chaos {\n\
recursion no;\n\
notify no;\n\
+ allow-new-zones no;\n\
\n\
zone \"version.bind\" chaos {\n\
type master;\n\
@@ -213,11 +236,24 @@ view \"_bind\" chaos {\n\
type master;\n\
database \"_builtin authors\";\n\
};\n\
+\n\
zone \"id.server\" chaos {\n\
type master;\n\
database \"_builtin id\";\n\
};\n\
};\n\
+"
+"#\n\
+# Default trusted key(s) for builtin DLV support\n\
+# (used if \"dnssec-lookaside auto;\" is set and\n\
+# sysconfdir/bind.keys doesn't exist).\n\
+#\n\
+# BEGIN MANAGED KEYS\n"
+
+/* Imported from bind.keys.h: */
+MANAGED_KEYS
+
+"# END MANAGED KEYS\n\
";
isc_result_t
@@ -339,6 +375,8 @@ ns_config_getzonetype(const cfg_obj_t *zonetypeobj) {
ztype = dns_zone_slave;
else if (strcasecmp(str, "stub") == 0)
ztype = dns_zone_stub;
+ else if (strcasecmp(str, "static-stub") == 0)
+ ztype = dns_zone_staticstub;
else
INSIST(0);
return (ztype);
@@ -615,7 +653,7 @@ ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
isc_buffer_add(&b, strlen(keystr));
dns_fixedname_init(&fname);
result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = dns_name_dup(dns_fixedname_name(&fname), mctx,
@@ -747,23 +785,31 @@ struct keyalgorithms {
const char *str;
enum { hmacnone, hmacmd5, hmacsha1, hmacsha224,
hmacsha256, hmacsha384, hmacsha512 } hmac;
+ unsigned int type;
isc_uint16_t size;
} algorithms[] = {
- { "hmac-md5", hmacmd5, 128 },
- { "hmac-md5.sig-alg.reg.int", hmacmd5, 0 },
- { "hmac-md5.sig-alg.reg.int.", hmacmd5, 0 },
- { "hmac-sha1", hmacsha1, 160 },
- { "hmac-sha224", hmacsha224, 224 },
- { "hmac-sha256", hmacsha256, 256 },
- { "hmac-sha384", hmacsha384, 384 },
- { "hmac-sha512", hmacsha512, 512 },
- { NULL, hmacnone, 0 }
+ { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 },
+ { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 },
+ { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 },
+ { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 },
+ { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 },
+ { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 },
+ { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 },
+ { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 },
+ { NULL, hmacnone, DST_ALG_UNKNOWN, 0 }
};
isc_result_t
ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
isc_uint16_t *digestbits)
{
+ return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits));
+}
+
+isc_result_t
+ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
+ unsigned int *typep, isc_uint16_t *digestbits)
+{
int i;
size_t len = 0;
isc_uint16_t bits;
@@ -801,6 +847,8 @@ ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
INSIST(0);
}
}
+ if (typep != NULL)
+ *typep = algorithms[i].type;
if (digestbits != NULL)
*digestbits = bits;
return (ISC_R_SUCCESS);
diff --git a/contrib/bind9/bin/named/control.c b/contrib/bind9/bin/named/control.c
index 38115d607bbb..3fc7bd3916f5 100644
--- a/contrib/bind9/bin/named/control.c
+++ b/contrib/bind9/bin/named/control.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: control.c,v 1.33.266.4 2010-12-03 23:45:46 tbox Exp $ */
+/* $Id: control.c,v 1.41 2010-12-03 22:05:19 each Exp $ */
/*! \file */
@@ -158,6 +158,8 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
} else if (command_compare(command, NS_COMMAND_DUMPDB)) {
ns_server_dumpdb(ns_g_server, command);
result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_SECROOTS)) {
+ result = ns_server_dumpsecroots(ns_g_server, command);
} else if (command_compare(command, NS_COMMAND_TRACE)) {
result = ns_server_setdebuglevel(ns_g_server, command);
} else if (command_compare(command, NS_COMMAND_NOTRACE)) {
@@ -192,6 +194,13 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
result = ns_server_notifycommand(ns_g_server, command, text);
} else if (command_compare(command, NS_COMMAND_VALIDATION)) {
result = ns_server_validation(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_SIGN) ||
+ command_compare(command, NS_COMMAND_LOADKEYS)) {
+ result = ns_server_rekey(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_ADDZONE)) {
+ result = ns_server_add_zone(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_DELZONE)) {
+ result = ns_server_del_zone(ns_g_server, command);
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
diff --git a/contrib/bind9/bin/named/include/named/client.h b/contrib/bind9/bin/named/include/named/client.h
index 5ad9c6bf5ff0..33f124d94c14 100644
--- a/contrib/bind9/bin/named/include/named/client.h
+++ b/contrib/bind9/bin/named/include/named/client.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: client.h,v 1.86.120.2 2009-01-18 23:47:34 tbox Exp $ */
+/* $Id: client.h,v 1.91 2009-10-26 23:14:53 each Exp $ */
#ifndef NAMED_CLIENT_H
#define NAMED_CLIENT_H 1
@@ -138,6 +138,7 @@ struct ns_client {
ns_interface_t *interface;
isc_sockaddr_t peeraddr;
isc_boolean_t peeraddr_valid;
+ isc_netaddr_t destaddr;
struct in6_pktinfo pktinfo;
isc_event_t ctlevent;
/*%
@@ -167,6 +168,10 @@ struct ns_client {
#define NS_CLIENTATTR_MULTICAST 0x08 /*%< recv'd from multicast */
#define NS_CLIENTATTR_WANTDNSSEC 0x10 /*%< include dnssec records */
#define NS_CLIENTATTR_WANTNSID 0x20 /*%< include nameserver ID */
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+#define NS_CLIENTATTR_FILTER_AAAA 0x40 /*%< suppress AAAAs */
+#define NS_CLIENTATTR_FILTER_AAAA_RC 0x80 /*%< recursing for A against AAAA */
+#endif
extern unsigned int ns_client_requests;
@@ -274,10 +279,8 @@ ns_client_getsockaddr(ns_client_t *client);
*/
isc_result_t
-ns_client_checkaclsilent(ns_client_t *client,
- isc_sockaddr_t *sockaddr,
- dns_acl_t *acl,
- isc_boolean_t default_allow);
+ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
+ dns_acl_t *acl, isc_boolean_t default_allow);
/*%
* Convenience function for client request ACL checking.
@@ -296,12 +299,12 @@ ns_client_checkaclsilent(ns_client_t *client,
*
* Requires:
*\li 'client' points to a valid client.
- *\li 'sockaddr' points to a valid address, or is NULL.
+ *\li 'netaddr' points to a valid address, or is NULL.
*\li 'acl' points to a valid ACL, or is NULL.
*
* Returns:
*\li ISC_R_SUCCESS if the request should be allowed
- * \li ISC_R_REFUSED if the request should be denied
+ * \li DNS_R_REFUSED if the request should be denied
*\li No other return values are possible.
*/
diff --git a/contrib/bind9/bin/named/include/named/config.h b/contrib/bind9/bin/named/include/named/config.h
index fa96d32947e3..d1570b0e5704 100644
--- a/contrib/bind9/bin/named/include/named/config.h
+++ b/contrib/bind9/bin/named/include/named/config.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001, 2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.h,v 1.14 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: config.h,v 1.16 2009-06-11 23:47:55 tbox Exp $ */
#ifndef NAMED_CONFIG_H
#define NAMED_CONFIG_H 1
@@ -75,5 +75,8 @@ ns_config_getport(const cfg_obj_t *config, in_port_t *portp);
isc_result_t
ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
isc_uint16_t *digestbits);
+isc_result_t
+ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
+ unsigned int *typep, isc_uint16_t *digestbits);
#endif /* NAMED_CONFIG_H */
diff --git a/contrib/bind9/bin/named/include/named/control.h b/contrib/bind9/bin/named/include/named/control.h
index 436fb19c7bf6..e699892ca4ce 100644
--- a/contrib/bind9/bin/named/include/named/control.h
+++ b/contrib/bind9/bin/named/include/named/control.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: control.h,v 1.25 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: control.h,v 1.31 2010-08-16 22:21:06 marka Exp $ */
#ifndef NAMED_CONTROL_H
#define NAMED_CONTROL_H 1
@@ -42,6 +42,7 @@
#define NS_COMMAND_DUMPSTATS "stats"
#define NS_COMMAND_QUERYLOG "querylog"
#define NS_COMMAND_DUMPDB "dumpdb"
+#define NS_COMMAND_SECROOTS "secroots"
#define NS_COMMAND_TRACE "trace"
#define NS_COMMAND_NOTRACE "notrace"
#define NS_COMMAND_FLUSH "flush"
@@ -57,6 +58,10 @@
#define NS_COMMAND_NULL "null"
#define NS_COMMAND_NOTIFY "notify"
#define NS_COMMAND_VALIDATION "validation"
+#define NS_COMMAND_SIGN "sign"
+#define NS_COMMAND_LOADKEYS "loadkeys"
+#define NS_COMMAND_ADDZONE "addzone"
+#define NS_COMMAND_DELZONE "delzone"
isc_result_t
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
diff --git a/contrib/bind9/bin/named/include/named/globals.h b/contrib/bind9/bin/named/include/named/globals.h
index 1d57a18f2008..f155c7f05ed5 100644
--- a/contrib/bind9/bin/named/include/named/globals.h
+++ b/contrib/bind9/bin/named/include/named/globals.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: globals.h,v 1.80.12.3 2010-09-15 12:16:50 marka Exp $ */
+/* $Id: globals.h,v 1.89 2010-09-15 12:07:55 marka Exp $ */
#ifndef NAMED_GLOBALS_H
#define NAMED_GLOBALS_H 1
@@ -30,6 +30,8 @@
#include <dns/zone.h>
+#include <dst/dst.h>
+
#include <named/types.h>
#undef EXTERN
@@ -86,8 +88,13 @@ EXTERN cfg_obj_t * ns_g_config INIT(NULL);
EXTERN const cfg_obj_t * ns_g_defaults INIT(NULL);
EXTERN const char * ns_g_conffile INIT(NS_SYSCONFDIR
"/named.conf");
+EXTERN cfg_obj_t * ns_g_bindkeys INIT(NULL);
EXTERN const char * ns_g_keyfile INIT(NS_SYSCONFDIR
"/rndc.key");
+
+EXTERN dns_tsigkey_t * ns_g_sessionkey INIT(NULL);
+EXTERN dns_name_t ns_g_sessionkeyname;
+
EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR
"/lwresd.conf");
EXTERN const char * lwresd_g_resolvconffile INIT("/etc"
@@ -112,6 +119,10 @@ EXTERN const char * ns_g_chrootdir INIT(NULL);
EXTERN isc_boolean_t ns_g_foreground INIT(ISC_FALSE);
EXTERN isc_boolean_t ns_g_logstderr INIT(ISC_FALSE);
+EXTERN const char * ns_g_defaultsessionkeyfile
+ INIT(NS_LOCALSTATEDIR "/run/named/"
+ "session.key");
+
#if NS_RUN_PID_DIR
EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
"/run/named/"
@@ -128,6 +139,12 @@ EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
EXTERN const char * ns_g_username INIT(NULL);
+#ifdef USE_PKCS11
+EXTERN const char * ns_g_engine INIT("pkcs11");
+#else
+EXTERN const char * ns_g_engine INIT(NULL);
+#endif
+
EXTERN int ns_g_listen INIT(3);
EXTERN isc_time_t ns_g_boottime;
EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE);
diff --git a/contrib/bind9/bin/named/include/named/log.h b/contrib/bind9/bin/named/include/named/log.h
index 0cfbee9ad396..1ce680f31e02 100644
--- a/contrib/bind9/bin/named/include/named/log.h
+++ b/contrib/bind9/bin/named/include/named/log.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.h,v 1.25.332.2 2009-01-07 23:47:16 tbox Exp $ */
+/* $Id: log.h,v 1.27 2009-01-07 23:47:46 tbox Exp $ */
#ifndef NAMED_LOG_H
#define NAMED_LOG_H 1
diff --git a/contrib/bind9/bin/named/include/named/lwdclient.h b/contrib/bind9/bin/named/include/named/lwdclient.h
index 44e1fa6e0878..5451b73675ab 100644
--- a/contrib/bind9/bin/named/include/named/lwdclient.h
+++ b/contrib/bind9/bin/named/include/named/lwdclient.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lwdclient.h,v 1.18.332.2 2009-01-18 23:47:34 tbox Exp $ */
+/* $Id: lwdclient.h,v 1.20 2009-01-17 23:47:42 tbox Exp $ */
#ifndef NAMED_LWDCLIENT_H
#define NAMED_LWDCLIENT_H 1
diff --git a/contrib/bind9/bin/named/include/named/main.h b/contrib/bind9/bin/named/include/named/main.h
index 96fb23edd80a..6116add55b85 100644
--- a/contrib/bind9/bin/named/include/named/main.h
+++ b/contrib/bind9/bin/named/include/named/main.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,15 +15,16 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: main.h,v 1.15 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: main.h,v 1.17 2009-09-29 23:48:03 tbox Exp $ */
#ifndef NAMED_MAIN_H
#define NAMED_MAIN_H 1
/*! \file */
-void
-ns_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+ISC_PLATFORM_NORETURN_PRE void
+ns_main_earlyfatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
void
ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
diff --git a/contrib/bind9/bin/named/include/named/notify.h b/contrib/bind9/bin/named/include/named/notify.h
index ac7fe2d3a9a6..34fabcd0620c 100644
--- a/contrib/bind9/bin/named/include/named/notify.h
+++ b/contrib/bind9/bin/named/include/named/notify.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: notify.h,v 1.14.332.2 2009-01-18 23:47:34 tbox Exp $ */
+/* $Id: notify.h,v 1.16 2009-01-17 23:47:42 tbox Exp $ */
#ifndef NAMED_NOTIFY_H
#define NAMED_NOTIFY_H 1
diff --git a/contrib/bind9/bin/named/include/named/query.h b/contrib/bind9/bin/named/include/named/query.h
index 2f00f1ea3843..37f771bd5960 100644
--- a/contrib/bind9/bin/named/include/named/query.h
+++ b/contrib/bind9/bin/named/include/named/query.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2010, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: query.h,v 1.40.332.2 2010-09-24 08:30:28 tbox Exp $ */
+/* $Id: query.h,v 1.45 2011-01-13 04:59:24 tbox Exp $ */
#ifndef NAMED_QUERY_H
#define NAMED_QUERY_H 1
@@ -26,6 +26,8 @@
#include <isc/buffer.h>
#include <isc/netaddr.h>
+#include <dns/rdataset.h>
+#include <dns/rpz.h>
#include <dns/types.h>
#include <named/types.h>
@@ -34,6 +36,7 @@
typedef struct ns_dbversion {
dns_db_t *db;
dns_dbversion_t *version;
+ isc_boolean_t acl_checked;
isc_boolean_t queryok;
ISC_LINK(struct ns_dbversion) link;
} ns_dbversion_t;
@@ -54,9 +57,16 @@ struct ns_query {
isc_boolean_t isreferral;
isc_mutex_t fetchlock;
dns_fetch_t * fetch;
+ dns_rpz_st_t * rpz_st;
isc_bufferlist_t namebufs;
ISC_LIST(ns_dbversion_t) activeversions;
ISC_LIST(ns_dbversion_t) freeversions;
+ dns_rdataset_t * dns64_aaaa;
+ dns_rdataset_t * dns64_sigaaaa;
+ isc_boolean_t * dns64_aaaaok;
+ unsigned int dns64_aaaaoklen;
+ unsigned int dns64_options;
+ unsigned int dns64_ttl;
};
#define NS_QUERYATTR_RECURSIONOK 0x0001
@@ -73,6 +83,9 @@ struct ns_query {
#define NS_QUERYATTR_NOADDITIONAL 0x0800
#define NS_QUERYATTR_CACHEACLOKVALID 0x1000
#define NS_QUERYATTR_CACHEACLOK 0x2000
+#define NS_QUERYATTR_DNS64 0x4000
+#define NS_QUERYATTR_DNS64EXCLUDE 0x8000
+
isc_result_t
ns_query_init(ns_client_t *client);
diff --git a/contrib/bind9/bin/named/include/named/server.h b/contrib/bind9/bin/named/include/named/server.h
index 3a4c5f7248e2..3c6426eecf61 100644
--- a/contrib/bind9/bin/named/include/named/server.h
+++ b/contrib/bind9/bin/named/include/named/server.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: server.h,v 1.93.120.3 2009-07-11 04:23:53 marka Exp $ */
+/* $Id: server.h,v 1.110 2010-08-16 23:46:52 tbox Exp $ */
#ifndef NAMED_SERVER_H
#define NAMED_SERVER_H 1
@@ -54,6 +54,8 @@ struct ns_server {
dns_acl_t *blackholeacl;
char * statsfile; /*%< Statistics file name */
char * dumpfile; /*%< Dump file name */
+ char * secrootsfile; /*%< Secroots file name */
+ char * bindkeysfile; /*%< bind.keys file name */
char * recfile; /*%< Recursive file name */
isc_boolean_t version_set; /*%< User has set version */
char * version; /*%< User-specified version */
@@ -91,13 +93,14 @@ struct ns_server {
isc_boolean_t flushonshutdown;
isc_boolean_t log_queries; /*%< For BIND 8 compatibility */
- isc_stats_t * nsstats; /*%< Server statistics */
- dns_stats_t * rcvquerystats; /*% Incoming query statistics */
- dns_stats_t * opcodestats; /*%< Incoming message statistics */
- isc_stats_t * zonestats; /*% Zone management statistics */
- isc_stats_t * resolverstats; /*% Resolver statistics */
+ ns_cachelist_t cachelist; /*%< Possibly shared caches */
+ isc_stats_t * nsstats; /*%< Server stats */
+ dns_stats_t * rcvquerystats; /*% Incoming query stats */
+ dns_stats_t * opcodestats; /*%< Incoming message stats */
+ isc_stats_t * zonestats; /*% Zone management stats */
+ isc_stats_t * resolverstats; /*% Resolver stats */
+ isc_stats_t * sockstats; /*%< Socket stats */
- isc_stats_t * sockstats; /*%< Socket statistics */
ns_controls_t * controls; /*%< Control channels */
unsigned int dispatchgen;
ns_dispatchlist_t dispatches;
@@ -105,6 +108,12 @@ struct ns_server {
dns_acache_t *acache;
ns_statschannellist_t statschannels;
+
+ dns_tsigkey_t *sessionkey;
+ char *session_keyfile;
+ dns_name_t *session_keyname;
+ unsigned int session_keyalg;
+ isc_uint16_t session_keybits;
};
#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
@@ -237,6 +246,12 @@ isc_result_t
ns_server_dumpdb(ns_server_t *server, char *args);
/*%
+ * Dump the current security roots to the secroots file.
+ */
+isc_result_t
+ns_server_dumpsecroots(ns_server_t *server, char *args);
+
+/*%
* Change or increment the server debug level.
*/
isc_result_t
@@ -280,6 +295,16 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
isc_buffer_t *text);
/*%
+ * Update a zone's DNSKEY set from the key repository. If
+ * the command that triggered the call to this function was "sign",
+ * then force a full signing of the zone. If it was "loadkeys",
+ * then don't sign the zone; any needed changes to signatures can
+ * take place incrementally.
+ */
+isc_result_t
+ns_server_rekey(ns_server_t *server, char *args);
+
+/*%
* Dump the current recursive queries.
*/
isc_result_t
@@ -297,4 +322,16 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr);
isc_result_t
ns_server_validation(ns_server_t *server, char *args);
+/*%
+ * Add a zone to a running process
+ */
+isc_result_t
+ns_server_add_zone(ns_server_t *server, char *args);
+
+/*%
+ * Deletes a zone from a running process
+ */
+isc_result_t
+ns_server_del_zone(ns_server_t *server, char *args);
+
#endif /* NAMED_SERVER_H */
diff --git a/contrib/bind9/bin/named/include/named/tsigconf.h b/contrib/bind9/bin/named/include/named/tsigconf.h
index a4841bad9df9..4a59ec2c0ff7 100644
--- a/contrib/bind9/bin/named/include/named/tsigconf.h
+++ b/contrib/bind9/bin/named/include/named/tsigconf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsigconf.h,v 1.16 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: tsigconf.h,v 1.18 2009-06-11 23:47:55 tbox Exp $ */
#ifndef NS_TSIGCONF_H
#define NS_TSIGCONF_H 1
@@ -36,8 +36,9 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
*
* Requires:
* \li 'config' is not NULL.
+ * \li 'vconfig' is not NULL.
* \li 'mctx' is not NULL
- * \li 'ring' is not NULL, and '*ring' is NULL
+ * \li 'ringp' is not NULL, and '*ringp' is NULL
*
* Returns:
* \li ISC_R_SUCCESS
diff --git a/contrib/bind9/bin/named/include/named/types.h b/contrib/bind9/bin/named/include/named/types.h
index b0729a787ba7..96c4c012b71f 100644
--- a/contrib/bind9/bin/named/include/named/types.h
+++ b/contrib/bind9/bin/named/include/named/types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.29 2008-01-17 23:46:59 tbox Exp $ */
+/* $Id: types.h,v 1.31 2009-01-09 23:47:45 tbox Exp $ */
#ifndef NAMED_TYPES_H
#define NAMED_TYPES_H 1
@@ -24,6 +24,8 @@
#include <dns/types.h>
+typedef struct ns_cache ns_cache_t;
+typedef ISC_LIST(ns_cache_t) ns_cachelist_t;
typedef struct ns_client ns_client_t;
typedef struct ns_clientmgr ns_clientmgr_t;
typedef struct ns_query ns_query_t;
diff --git a/contrib/bind9/bin/named/include/named/zoneconf.h b/contrib/bind9/bin/named/include/named/zoneconf.h
index ab84c84515bf..65cf72f9f3ac 100644
--- a/contrib/bind9/bin/named/include/named/zoneconf.h
+++ b/contrib/bind9/bin/named/include/named/zoneconf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zoneconf.h,v 1.26 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: zoneconf.h,v 1.28 2010-12-20 23:47:20 tbox Exp $ */
#ifndef NS_ZONECONF_H
#define NS_ZONECONF_H 1
@@ -58,6 +58,21 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig);
* and recreated, return ISC_FALSE.
*/
+
+isc_result_t
+ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
+ dns_rdataclass_t rdclass, dns_name_t *name);
+/*%>
+ * configure a DLZ zone, setting up the database methods and calling
+ * postload to load the origin values
+ *
+ * Require:
+ * \li 'dlzdatabase' to be a valid dlz database
+ * \li 'zone' to be initialized.
+ * \li 'rdclass' to be a valid rdataclass
+ * \li 'name' to be a valid zone origin name
+ */
+
ISC_LANG_ENDDECLS
#endif /* NS_ZONECONF_H */
diff --git a/contrib/bind9/bin/named/interfacemgr.c b/contrib/bind9/bin/named/interfacemgr.c
index fad32137f6df..e99d3b9cfe38 100644
--- a/contrib/bind9/bin/named/interfacemgr.c
+++ b/contrib/bind9/bin/named/interfacemgr.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: interfacemgr.c,v 1.93.70.2 2009-01-18 23:47:34 tbox Exp $ */
+/* $Id: interfacemgr.c,v 1.95 2009-01-17 23:47:42 tbox Exp $ */
/*! \file */
diff --git a/contrib/bind9/bin/named/log.c b/contrib/bind9/bin/named/log.c
index 867ad56b8c51..5d1c942074ca 100644
--- a/contrib/bind9/bin/named/log.c
+++ b/contrib/bind9/bin/named/log.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: log.c,v 1.46.334.3 2009-01-07 01:50:14 jinmei Exp $ */
+/* $Id: log.c,v 1.49 2009-01-07 01:46:40 jinmei Exp $ */
/*! \file */
diff --git a/contrib/bind9/bin/named/lwdgabn.c b/contrib/bind9/bin/named/lwdgabn.c
index 66d724624a5c..6a609c9acc4f 100644
--- a/contrib/bind9/bin/named/lwdgabn.c
+++ b/contrib/bind9/bin/named/lwdgabn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lwdgabn.c,v 1.22 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: lwdgabn.c,v 1.24 2009-09-02 23:48:01 tbox Exp $ */
/*! \file */
@@ -619,7 +619,7 @@ ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
dns_fixedname_init(&client->target_name);
dns_fixedname_init(&client->query_name);
result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
- &namebuf, NULL, ISC_FALSE, NULL);
+ &namebuf, NULL, 0, NULL);
if (result != ISC_R_SUCCESS)
goto out;
ns_lwsearchctx_init(&client->searchctx,
diff --git a/contrib/bind9/bin/named/lwdgrbn.c b/contrib/bind9/bin/named/lwdgrbn.c
index bf29a481c488..22b62c625c12 100644
--- a/contrib/bind9/bin/named/lwdgrbn.c
+++ b/contrib/bind9/bin/named/lwdgrbn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lwdgrbn.c,v 1.20 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: lwdgrbn.c,v 1.22 2009-09-02 23:48:01 tbox Exp $ */
/*! \file */
@@ -472,7 +472,7 @@ ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) {
dns_fixedname_init(&client->query_name);
result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
- &namebuf, NULL, ISC_FALSE, NULL);
+ &namebuf, NULL, 0, NULL);
if (result != ISC_R_SUCCESS)
goto out;
ns_lwsearchctx_init(&client->searchctx,
diff --git a/contrib/bind9/bin/named/lwresd.8 b/contrib/bind9/bin/named/lwresd.8
index d1e760d10887..30dfbd55e783 100644
--- a/contrib/bind9/bin/named/lwresd.8
+++ b/contrib/bind9/bin/named/lwresd.8
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: lwresd.8,v 1.29.14.2 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: lwresd.8,v 1.31 2009-07-11 01:12:45 tbox Exp $
.\"
.hy 0
.ad l
diff --git a/contrib/bind9/bin/named/lwresd.c b/contrib/bind9/bin/named/lwresd.c
index b7dc0af1038f..ad3670960cb1 100644
--- a/contrib/bind9/bin/named/lwresd.c
+++ b/contrib/bind9/bin/named/lwresd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lwresd.c,v 1.58 2008-07-23 23:27:54 marka Exp $ */
+/* $Id: lwresd.c,v 1.60 2009-09-02 23:48:01 tbox Exp $ */
/*! \file
* \brief
@@ -372,8 +372,7 @@ ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
strlen(searchstr));
isc_buffer_add(&namebuf, strlen(searchstr));
result = dns_name_fromtext(name, &namebuf,
- dns_rootname, ISC_FALSE,
- NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx,
NS_LOGCATEGORY_GENERAL,
diff --git a/contrib/bind9/bin/named/lwresd.docbook b/contrib/bind9/bin/named/lwresd.docbook
index f8e1500d0479..934b5da21dcc 100644
--- a/contrib/bind9/bin/named/lwresd.docbook
+++ b/contrib/bind9/bin/named/lwresd.docbook
@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwresd.docbook,v 1.18.14.2 2009-01-22 23:47:05 tbox Exp $ -->
+<!-- $Id: lwresd.docbook,v 1.20 2009-01-20 23:47:56 tbox Exp $ -->
<refentry>
<refentryinfo>
<date>June 30, 2000</date>
diff --git a/contrib/bind9/bin/named/lwresd.html b/contrib/bind9/bin/named/lwresd.html
index dec47caa2b86..223b1c2c5250 100644
--- a/contrib/bind9/bin/named/lwresd.html
+++ b/contrib/bind9/bin/named/lwresd.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: lwresd.html,v 1.25.14.2 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: lwresd.html,v 1.27 2009-07-11 01:12:45 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
diff --git a/contrib/bind9/bin/named/main.c b/contrib/bind9/bin/named/main.c
index a1d94fff80d5..84d86b146f4c 100644
--- a/contrib/bind9/bin/named/main.c
+++ b/contrib/bind9/bin/named/main.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: main.c,v 1.166.34.7 2010-09-15 12:16:49 marka Exp $ */
+/* $Id: main.c,v 1.180 2010-12-22 03:59:02 marka Exp $ */
/*! \file */
@@ -26,6 +26,7 @@
#include <string.h>
#include <isc/app.h>
+#include <isc/backtrace.h>
#include <isc/commandline.h>
#include <isc/dir.h>
#include <isc/entropy.h>
@@ -69,6 +70,12 @@
#include <named/ns_smf_globals.h>
#endif
+#ifdef OPENSSL
+#include <openssl/opensslv.h>
+#endif
+#ifdef HAVE_LIBXML2
+#include <libxml/xmlversion.h>
+#endif
/*
* Include header files for database drivers here.
*/
@@ -81,12 +88,20 @@
#include <dlz/dlz_drivers.h>
#endif
+/*
+ * The maximum number of stack frames to dump on assertion failure.
+ */
+#ifndef BACKTRACE_MAXFRAME
+#define BACKTRACE_MAXFRAME 128
+#endif
+
static isc_boolean_t want_stats = ISC_FALSE;
static char program_name[ISC_DIR_NAMEMAX] = "named";
static char absolute_conffile[ISC_DIR_PATHMAX];
static char saved_command_line[512];
static char version[512];
static unsigned int maxsocks = 0;
+static int maxudp = 0;
void
ns_main_earlywarning(const char *format, ...) {
@@ -129,10 +144,20 @@ ns_main_earlyfatal(const char *format, ...) {
exit(1);
}
+ISC_PLATFORM_NORETURN_PRE static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond) ISC_PLATFORM_NORETURN_POST;
+
static void
assertion_failed(const char *file, int line, isc_assertiontype_t type,
const char *cond)
{
+ void *tracebuf[BACKTRACE_MAXFRAME];
+ int i, nframes;
+ isc_result_t result;
+ const char *logsuffix = "";
+ const char *fname;
+
/*
* Handle assertion failures.
*/
@@ -144,10 +169,40 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
*/
isc_assertion_setcallback(NULL);
+ result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME,
+ &nframes);
+ if (result == ISC_R_SUCCESS && nframes > 0)
+ logsuffix = ", back trace";
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
- "%s:%d: %s(%s) failed", file, line,
- isc_assertion_typetotext(type), cond);
+ "%s:%d: %s(%s) failed%s", file, line,
+ isc_assertion_typetotext(type), cond, logsuffix);
+ if (result == ISC_R_SUCCESS) {
+ for (i = 0; i < nframes; i++) {
+ unsigned long offset;
+
+ fname = NULL;
+ result = isc_backtrace_getsymbol(tracebuf[i],
+ &fname,
+ &offset);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN,
+ ISC_LOG_CRITICAL,
+ "#%d %p in %s()+0x%lx", i,
+ tracebuf[i], fname,
+ offset);
+ } else {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN,
+ ISC_LOG_CRITICAL,
+ "#%d %p in ??", i,
+ tracebuf[i]);
+ }
+ }
+ }
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
"exiting (due to assertion failure)");
@@ -162,9 +217,10 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
exit(1);
}
-static void
+ISC_PLATFORM_NORETURN_PRE static void
library_fatal_error(const char *file, int line, const char *format,
- va_list args) ISC_FORMAT_PRINTF(3, 0);
+ va_list args)
+ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST;
static void
library_fatal_error(const char *file, int line, const char *format,
@@ -248,8 +304,9 @@ usage(void) {
}
fprintf(stderr,
"usage: named [-4|-6] [-c conffile] [-d debuglevel] "
- "[-f|-g] [-n number_of_cpus]\n"
- " [-p port] [-s] [-t chrootdir] [-u username]\n"
+ "[-E engine] [-f|-g]\n"
+ " [-n number_of_cpus] [-p port] [-s] "
+ "[-t chrootdir] [-u username]\n"
" [-m {usage|trace|record|size|mctx}]\n");
}
@@ -358,7 +415,7 @@ parse_command_line(int argc, char *argv[]) {
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv,
- "46c:C:d:fgi:lm:n:N:p:P:"
+ "46c:C:d:E:fFgi:lm:n:N:p:P:"
"sS:t:T:u:vVx:")) != -1) {
switch (ch) {
case '4':
@@ -394,6 +451,9 @@ parse_command_line(int argc, char *argv[]) {
ns_g_debuglevel = parse_int(isc_commandline_argument,
"debug level");
break;
+ case 'E':
+ ns_g_engine = isc_commandline_argument;
+ break;
case 'f':
ns_g_foreground = ISC_TRUE;
break;
@@ -451,12 +511,16 @@ parse_command_line(int argc, char *argv[]) {
* clienttest: make clients single shot with their
* own memory context.
*/
- if (strcmp(isc_commandline_argument, "clienttest") == 0)
+ if (!strcmp(isc_commandline_argument, "clienttest"))
ns_g_clienttest = ISC_TRUE;
else if (!strcmp(isc_commandline_argument, "nosoa"))
ns_g_nosoa = ISC_TRUE;
else if (!strcmp(isc_commandline_argument, "noaa"))
ns_g_noaa = ISC_TRUE;
+ else if (!strcmp(isc_commandline_argument, "maxudp512"))
+ maxudp = 512;
+ else if (!strcmp(isc_commandline_argument, "maxudp1460"))
+ maxudp = 1460;
else
fprintf(stderr, "unknown -T flag '%s\n",
isc_commandline_argument);
@@ -470,13 +534,25 @@ parse_command_line(int argc, char *argv[]) {
case 'V':
printf("BIND %s built with %s\n", ns_g_version,
ns_g_configargs);
+#ifdef OPENSSL
+ printf("using OpenSSL version: %s\n",
+ OPENSSL_VERSION_TEXT);
+#endif
+#ifdef HAVE_LIBXML2
+ printf("using libxml2 version: %s\n",
+ LIBXML_DOTTED_VERSION);
+#endif
exit(0);
+ case 'F':
+ /* Reserved for FIPS mode */
+ /* FALLTHROUGH */
case '?':
usage();
if (isc_commandline_option == '?')
exit(0);
ns_main_earlyfatal("unknown option '-%c'",
isc_commandline_option);
+ /* FALLTHROUGH */
default:
ns_main_earlyfatal("parsing options returned %d", ch);
}
@@ -529,6 +605,7 @@ create_managers(void) {
isc_result_totext(result));
return (ISC_R_UNEXPECTED);
}
+ isc__socketmgr_maxudp(ns_g_socketmgr, maxudp);
result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
if (result == ISC_R_SUCCESS) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
@@ -579,6 +656,34 @@ destroy_managers(void) {
}
static void
+dump_symboltable() {
+ int i;
+ isc_result_t result;
+ const char *fname;
+ const void *addr;
+
+ if (isc__backtrace_nsymbols == 0)
+ return;
+
+ if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99)))
+ return;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_DEBUG(99), "Symbol table:");
+
+ for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) {
+ addr = NULL;
+ fname = NULL;
+ result = isc_backtrace_getsymbolfromindex(i, &addr, &fname);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99),
+ "[%d] %p %s", i, addr, fname);
+ }
+ }
+}
+
+static void
setup(void) {
isc_result_t result;
isc_resourcevalue_t old_openfiles;
@@ -685,6 +790,8 @@ setup(void) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
ISC_LOG_NOTICE, "built with %s", ns_g_configargs);
+ dump_symboltable();
+
/*
* Get the initial resource limits.
*/
@@ -723,8 +830,8 @@ setup(void) {
absolute_conffile,
sizeof(absolute_conffile));
if (result != ISC_R_SUCCESS)
- ns_main_earlyfatal("could not construct absolute path of "
- "configuration file: %s",
+ ns_main_earlyfatal("could not construct absolute path "
+ "of configuration file: %s",
isc_result_totext(result));
ns_g_conffile = absolute_conffile;
}
@@ -896,6 +1003,9 @@ main(int argc, char *argv[]) {
if (strcmp(program_name, "lwresd") == 0)
ns_g_lwresdonly = ISC_TRUE;
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("failed to build internal symbol table");
+
isc_assertion_setcallback(assertion_failed);
isc_error_setfatal(library_fatal_error);
isc_error_setunexpected(library_unexpected_error);
diff --git a/contrib/bind9/bin/named/named.8 b/contrib/bind9/bin/named/named.8
index 90782ed8171e..23805b04a935 100644
--- a/contrib/bind9/bin/named/named.8
+++ b/contrib/bind9/bin/named/named.8
@@ -13,7 +13,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: named.8,v 1.38.14.2 2009-12-03 05:06:38 tbox Exp $
+.\" $Id: named.8,v 1.41 2009-10-06 01:14:41 tbox Exp $
.\"
.hy 0
.ad l
@@ -33,7 +33,7 @@
named \- Internet domain name server
.SH "SYNOPSIS"
.HP 6
-\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR]
+\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-E\ \fR\fB\fIengine\-name\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-S\ \fR\fB\fI#max\-socks\fR\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR]
.SH "DESCRIPTION"
.PP
\fBnamed\fR
@@ -83,6 +83,13 @@ Set the daemon's debug level to
become more verbose as the debug level increases.
.RE
.PP
+\-E \fIengine\-name\fR
+.RS 4
+Use a crypto hardware (OpenSSL engine) for the crypto operations it supports, for instance re\-signing with private keys from a secure key store. When compiled with PKCS#11 support
+\fIengine\-name\fR
+defaults to pkcs11, the empty name resets it to no engine.
+.RE
+.PP
\-f
.RS 4
Run the server in the foreground (i.e. do not daemonize).
diff --git a/contrib/bind9/bin/named/named.conf.5 b/contrib/bind9/bin/named/named.conf.5
index cd0d4ad75543..9dc7002b09c9 100644
--- a/contrib/bind9/bin/named/named.conf.5
+++ b/contrib/bind9/bin/named/named.conf.5
@@ -1,4 +1,4 @@
-.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2004-2011 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
@@ -12,7 +12,7 @@
.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.\" $Id: named.conf.5,v 1.36.48.1 2009-07-11 01:55:21 tbox Exp $
+.\" $Id: named.conf.5,v 1.44.12.1 2011-02-03 12:29:12 tbox Exp $
.\"
.hy 0
.ad l
@@ -102,6 +102,15 @@ trusted\-keys {
};
.fi
.RE
+.SH "MANAGED\-KEYS"
+.sp
+.RS 4
+.nf
+managed\-keys {
+ \fIdomain_name\fR \fBinitial\-key\fR \fIflags\fR \fIprotocol\fR \fIalgorithm\fR \fIkey\fR; ...
+};
+.fi
+.RE
.SH "CONTROLS"
.sp
.RS 4
@@ -186,6 +195,7 @@ options {
tcp\-listen\-queue \fIinteger\fR;
tkey\-dhkey \fIquoted_string\fR \fIinteger\fR;
tkey\-gssapi\-credential \fIquoted_string\fR;
+ tkey\-gssapi\-keytab \fIquoted_string\fR;
tkey\-domain \fIquoted_string\fR;
transfers\-per\-ns \fIinteger\fR;
transfers\-in \fIinteger\fR;
@@ -214,6 +224,7 @@ options {
queryport\-pool\-ports \fIinteger\fR;
queryport\-pool\-updateinterval \fIinteger\fR;
cleaning\-interval \fIinteger\fR;
+ resolver\-query\-timeout \fIinteger\fR;
min\-roots \fIinteger\fR; // not implemented
lame\-ttl \fIinteger\fR;
max\-ncache\-ttl \fIinteger\fR;
@@ -244,8 +255,19 @@ options {
dnssec\-enable \fIboolean\fR;
dnssec\-validation \fIboolean\fR;
dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR;
+ dnssec\-lookaside ( \fIauto\fR | \fIdomain\fR trust\-anchor \fIdomain\fR );
dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
dnssec\-accept\-expired \fIboolean\fR;
+ dns64\-server \fIstring\fR;
+ dns64\-contact \fIstring\fR;
+ dns64 \fIprefix\fR {
+ clients { <replacable>acl</replacable>; };
+ exclude { <replacable>acl</replacable>; };
+ mapped { <replacable>acl</replacable>; };
+ break\-dnssec \fIboolean\fR;
+ recursive\-only \fIboolean\fR;
+ suffix \fIipv6_address\fR;
+ };
empty\-server \fIstring\fR;
empty\-contact \fIstring\fR;
empty\-zones\-enable \fIboolean\fR;
@@ -260,6 +282,7 @@ options {
allow\-update { \fIaddress_match_element\fR; ... };
allow\-update\-forwarding { \fIaddress_match_element\fR; ... };
update\-check\-ksk \fIboolean\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
masterfile\-format ( text | raw );
notify \fInotifytype\fR;
notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
@@ -299,9 +322,18 @@ options {
use\-alt\-transfer\-source \fIboolean\fR;
zone\-statistics \fIboolean\fR;
key\-directory \fIquoted_string\fR;
+ managed\-keys\-directory \fIquoted_string\fR;
+ auto\-dnssec \fBallow\fR|\fBmaintain\fR|\fBcreate\fR|\fBoff\fR;
try\-tcp\-refresh \fIboolean\fR;
zero\-no\-soa\-ttl \fIboolean\fR;
zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
+ deny\-answer\-addresses {
+ \fIaddress_match_list\fR
+ } [ except\-from { \fInamelist\fR } ];
+ deny\-answer\-aliases {
+ \fInamelist\fR
+ } [ except\-from { \fInamelist\fR } ];
nsec3\-test\-zone \fIboolean\fR; // testing only
allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete
deallocate\-on\-exit \fIboolean\fR; // obsolete
@@ -337,7 +369,8 @@ view \fIstring\fR \fIoptional_class\fR {
...
};
trusted\-keys {
- \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; ...
+ \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR;
+ [...]
};
allow\-recursion { \fIaddress_match_element\fR; ... };
allow\-recursion\-on { \fIaddress_match_element\fR; ... };
@@ -361,6 +394,7 @@ view \fIstring\fR \fIoptional_class\fR {
queryport\-pool\-ports \fIinteger\fR;
queryport\-pool\-updateinterval \fIinteger\fR;
cleaning\-interval \fIinteger\fR;
+ resolver\-query\-timeout \fIinteger\fR;
min\-roots \fIinteger\fR; // not implemented
lame\-ttl \fIinteger\fR;
max\-ncache\-ttl \fIinteger\fR;
@@ -393,6 +427,16 @@ view \fIstring\fR \fIoptional_class\fR {
dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR;
dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
dnssec\-accept\-expired \fIboolean\fR;
+ dns64\-server \fIstring\fR;
+ dns64\-contact \fIstring\fR;
+ dns64 \fIprefix\fR {
+ clients { <replacable>acl</replacable>; };
+ exclude { <replacable>acl</replacable>; };
+ mapped { <replacable>acl</replacable>; };
+ break\-dnssec \fIboolean\fR;
+ recursive\-only \fIboolean\fR;
+ suffix \fIipv6_address\fR;
+ };
empty\-server \fIstring\fR;
empty\-contact \fIstring\fR;
empty\-zones\-enable \fIboolean\fR;
@@ -407,6 +451,7 @@ view \fIstring\fR \fIoptional_class\fR {
allow\-update { \fIaddress_match_element\fR; ... };
allow\-update\-forwarding { \fIaddress_match_element\fR; ... };
update\-check\-ksk \fIboolean\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
masterfile\-format ( text | raw );
notify \fInotifytype\fR;
notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
@@ -445,6 +490,7 @@ view \fIstring\fR \fIoptional_class\fR {
key\-directory \fIquoted_string\fR;
zero\-no\-soa\-ttl \fIboolean\fR;
zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete
fetch\-glue \fIboolean\fR; // obsolete
maintain\-ixfr\-base \fIboolean\fR; // obsolete
@@ -476,19 +522,22 @@ zone \fIstring\fR \fIoptional_class\fR {
ixfr\-from\-differences \fIboolean\fR;
journal \fIquoted_string\fR;
zero\-no\-soa\-ttl \fIboolean\fR;
+ dnssec\-secure\-to\-insecure \fIboolean\fR;
allow\-query { \fIaddress_match_element\fR; ... };
allow\-query\-on { \fIaddress_match_element\fR; ... };
allow\-transfer { \fIaddress_match_element\fR; ... };
allow\-update { \fIaddress_match_element\fR; ... };
allow\-update\-forwarding { \fIaddress_match_element\fR; ... };
- update\-policy {
- ( grant | deny ) \fIstring\fR
+ update\-policy \fIlocal\fR | \fI {
+ ( grant | deny ) \fR\fI\fIstring\fR\fR\fI
( name | subdomain | wildcard | self | selfsub | selfwild |
krb5\-self | ms\-self | krb5\-subdomain | ms\-subdomain |
- tcp\-self | 6to4\-self ) \fIstring\fR
- \fIrrtypelist\fR; ...
- };
+ tcp\-self | zonesub | 6to4\-self ) \fR\fI\fIstring\fR\fR\fI
+ \fR\fI\fIrrtypelist\fR\fR\fI;
+ \fR\fI[...]\fR\fI
+ }\fR;
update\-check\-ksk \fIboolean\fR;
+ dnssec\-dnskey\-kskonly \fIboolean\fR;
masterfile\-format ( text | raw );
notify \fInotifytype\fR;
notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
@@ -544,5 +593,5 @@ zone \fIstring\fR \fIoptional_class\fR {
\fBrndc\fR(8),
BIND 9 Administrator Reference Manual.
.SH "COPYRIGHT"
-Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+Copyright \(co 2004\-2011 Internet Systems Consortium, Inc. ("ISC")
.br
diff --git a/contrib/bind9/bin/named/named.conf.docbook b/contrib/bind9/bin/named/named.conf.docbook
index d98e2899295a..962eaaa0e2bd 100644
--- a/contrib/bind9/bin/named/named.conf.docbook
+++ b/contrib/bind9/bin/named/named.conf.docbook
@@ -2,7 +2,7 @@
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
[<!ENTITY mdash "&#8212;">]>
<!--
- - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2004-2011 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
@@ -17,7 +17,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: named.conf.docbook,v 1.39 2008-09-24 02:46:21 marka Exp $ -->
+<!-- $Id: named.conf.docbook,v 1.49.14.1 2011-02-03 05:50:05 marka Exp $ -->
<refentry>
<refentryinfo>
<date>Aug 13, 2004</date>
@@ -41,6 +41,9 @@
<year>2006</year>
<year>2007</year>
<year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
<holder>Internet Systems Consortium, Inc. ("ISC")</holder>
</copyright>
</docinfo>
@@ -132,6 +135,15 @@ trusted-keys {
</refsect1>
<refsect1>
+ <title>MANAGED-KEYS</title>
+ <literallayout>
+managed-keys {
+ <replaceable>domain_name</replaceable> <constant>initial-key</constant> <replaceable>flags</replaceable> <replaceable>protocol</replaceable> <replaceable>algorithm</replaceable> <replaceable>key</replaceable>; ...
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
<title>CONTROLS</title>
<literallayout>
controls {
@@ -214,6 +226,7 @@ options {
tcp-listen-queue <replaceable>integer</replaceable>;
tkey-dhkey <replaceable>quoted_string</replaceable> <replaceable>integer</replaceable>;
tkey-gssapi-credential <replaceable>quoted_string</replaceable>;
+ tkey-gssapi-keytab <replaceable>quoted_string</replaceable>;
tkey-domain <replaceable>quoted_string</replaceable>;
transfers-per-ns <replaceable>integer</replaceable>;
transfers-in <replaceable>integer</replaceable>;
@@ -242,6 +255,7 @@ options {
queryport-pool-ports <replaceable>integer</replaceable>;
queryport-pool-updateinterval <replaceable>integer</replaceable>;
cleaning-interval <replaceable>integer</replaceable>;
+ resolver-query-timeout <replaceable>integer</replaceable>;
min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>;
max-ncache-ttl <replaceable>integer</replaceable>;
@@ -272,9 +286,21 @@ options {
dnssec-enable <replaceable>boolean</replaceable>;
dnssec-validation <replaceable>boolean</replaceable>;
dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>;
+ dnssec-lookaside ( <replaceable>auto</replaceable> | <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> );
dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
dnssec-accept-expired <replaceable>boolean</replaceable>;
+ dns64-server <replaceable>string</replaceable>;
+ dns64-contact <replaceable>string</replaceable>;
+ dns64 <replaceable>prefix</replaceable> {
+ clients { <replacable>acl</replacable>; };
+ exclude { <replacable>acl</replacable>; };
+ mapped { <replacable>acl</replacable>; };
+ break-dnssec <replaceable>boolean</replaceable>;
+ recursive-only <replaceable>boolean</replaceable>;
+ suffix <replaceable>ipv6_address</replaceable>;
+ };
+
empty-server <replaceable>string</replaceable>;
empty-contact <replaceable>string</replaceable>;
empty-zones-enable <replaceable>boolean</replaceable>;
@@ -291,6 +317,7 @@ options {
allow-update { <replaceable>address_match_element</replaceable>; ... };
allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
update-check-ksk <replaceable>boolean</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
@@ -337,9 +364,18 @@ options {
zone-statistics <replaceable>boolean</replaceable>;
key-directory <replaceable>quoted_string</replaceable>;
+ managed-keys-directory <replaceable>quoted_string</replaceable>;
+ auto-dnssec <constant>allow</constant>|<constant>maintain</constant>|<constant>create</constant>|<constant>off</constant>;
try-tcp-refresh <replaceable>boolean</replaceable>;
zero-no-soa-ttl <replaceable>boolean</replaceable>;
zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
+ deny-answer-addresses {
+ <replaceable>address_match_list</replaceable>
+ } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;
+ deny-answer-aliases {
+ <replaceable>namelist</replaceable>
+ } <optional> except-from { <replaceable>namelist</replaceable> } </optional>;
nsec3-test-zone <replaceable>boolean</replaceable>; // testing only
@@ -381,7 +417,8 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
};
trusted-keys {
- <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ...
+ <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>;
+ <optional>...</optional>
};
allow-recursion { <replaceable>address_match_element</replaceable>; ... };
@@ -406,6 +443,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
queryport-pool-ports <replaceable>integer</replaceable>;
queryport-pool-updateinterval <replaceable>integer</replaceable>;
cleaning-interval <replaceable>integer</replaceable>;
+ resolver-query-timeout <replaceable>integer</replaceable>;
min-roots <replaceable>integer</replaceable>; // not implemented
lame-ttl <replaceable>integer</replaceable>;
max-ncache-ttl <replaceable>integer</replaceable>;
@@ -439,6 +477,17 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
dnssec-accept-expired <replaceable>boolean</replaceable>;
+ dns64-server <replaceable>string</replaceable>;
+ dns64-contact <replaceable>string</replaceable>;
+ dns64 <replaceable>prefix</replaceable> {
+ clients { <replacable>acl</replacable>; };
+ exclude { <replacable>acl</replacable>; };
+ mapped { <replacable>acl</replacable>; };
+ break-dnssec <replaceable>boolean</replaceable>;
+ recursive-only <replaceable>boolean</replaceable>;
+ suffix <replaceable>ipv6_address</replaceable>;
+ };
+
empty-server <replaceable>string</replaceable>;
empty-contact <replaceable>string</replaceable>;
empty-zones-enable <replaceable>boolean</replaceable>;
@@ -455,6 +504,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
allow-update { <replaceable>address_match_element</replaceable>; ... };
allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
update-check-ksk <replaceable>boolean</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
@@ -499,6 +549,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
key-directory <replaceable>quoted_string</replaceable>;
zero-no-soa-ttl <replaceable>boolean</replaceable>;
zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
allow-v6-synthesis { <replaceable>address_match_element</replaceable>; ... }; // obsolete
fetch-glue <replaceable>boolean</replaceable>; // obsolete
@@ -533,20 +584,23 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
ixfr-from-differences <replaceable>boolean</replaceable>;
journal <replaceable>quoted_string</replaceable>;
zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
allow-query { <replaceable>address_match_element</replaceable>; ... };
allow-query-on { <replaceable>address_match_element</replaceable>; ... };
allow-transfer { <replaceable>address_match_element</replaceable>; ... };
allow-update { <replaceable>address_match_element</replaceable>; ... };
allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
- update-policy {
+ update-policy <replaceable>local</replaceable> | <replaceable> {
( grant | deny ) <replaceable>string</replaceable>
( name | subdomain | wildcard | self | selfsub | selfwild |
krb5-self | ms-self | krb5-subdomain | ms-subdomain |
- tcp-self | 6to4-self ) <replaceable>string</replaceable>
- <replaceable>rrtypelist</replaceable>; ...
- };
+ tcp-self | zonesub | 6to4-self ) <replaceable>string</replaceable>
+ <replaceable>rrtypelist</replaceable>;
+ <optional>...</optional>
+ }</replaceable>;
update-check-ksk <replaceable>boolean</replaceable>;
+ dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
diff --git a/contrib/bind9/bin/named/named.conf.html b/contrib/bind9/bin/named/named.conf.html
index fccad183f9e6..f20e411f45b0 100644
--- a/contrib/bind9/bin/named/named.conf.html
+++ b/contrib/bind9/bin/named/named.conf.html
@@ -1,5 +1,5 @@
<!--
- - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2004-2011 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
@@ -13,7 +13,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: named.conf.html,v 1.45.48.1 2009-07-11 01:55:21 tbox Exp $ -->
+<!-- $Id: named.conf.html,v 1.53.12.1 2011-02-03 12:29:12 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -31,7 +31,7 @@
<div class="cmdsynopsis"><p><code class="command">named.conf</code> </p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543342"></a><h2>DESCRIPTION</h2>
+<a name="id2543352"></a><h2>DESCRIPTION</h2>
<p><code class="filename">named.conf</code> is the configuration file
for
<span><strong class="command">named</strong></span>. Statements are enclosed
@@ -50,14 +50,14 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543370"></a><h2>ACL</h2>
+<a name="id2543380"></a><h2>ACL</h2>
<div class="literallayout"><p><br>
acl <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543386"></a><h2>KEY</h2>
+<a name="id2543396"></a><h2>KEY</h2>
<div class="literallayout"><p><br>
key <em class="replaceable"><code>domain_name</code></em> {<br>
algorithm <em class="replaceable"><code>string</code></em>;<br>
@@ -66,7 +66,7 @@ key <em class="replaceable"><code>domain_name</code></em> {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543405"></a><h2>MASTERS</h2>
+<a name="id2543415"></a><h2>MASTERS</h2>
<div class="literallayout"><p><br>
masters <em class="replaceable"><code>string</code></em> [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
@@ -75,7 +75,7 @@ masters <em class="replaceable"><code>string</code></em> [<span class="optional"
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543451"></a><h2>SERVER</h2>
+<a name="id2543461"></a><h2>SERVER</h2>
<div class="literallayout"><p><br>
server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/prefixlen</span>]</code></em> | <em class="replaceable"><code>ipv6_address[<span class="optional">/prefixlen</span>]</code></em> ) {<br>
bogus <em class="replaceable"><code>boolean</code></em>;<br>
@@ -97,7 +97,7 @@ server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/pref
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543520"></a><h2>TRUSTED-KEYS</h2>
+<a name="id2543529"></a><h2>TRUSTED-KEYS</h2>
<div class="literallayout"><p><br>
trusted-keys {<br>
<em class="replaceable"><code>domain_name</code></em> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br>
@@ -105,7 +105,15 @@ trusted-keys {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543545"></a><h2>CONTROLS</h2>
+<a name="id2543555"></a><h2>MANAGED-KEYS</h2>
+<div class="literallayout"><p><br>
+managed-keys {<br>
+ <em class="replaceable"><code>domain_name</code></em> <code class="constant">initial-key</code> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543584"></a><h2>CONTROLS</h2>
<div class="literallayout"><p><br>
controls {<br>
inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
@@ -117,7 +125,7 @@ controls {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543580"></a><h2>LOGGING</h2>
+<a name="id2543619"></a><h2>LOGGING</h2>
<div class="literallayout"><p><br>
logging {<br>
channel <em class="replaceable"><code>string</code></em> {<br>
@@ -135,7 +143,7 @@ logging {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543619"></a><h2>LWRES</h2>
+<a name="id2543657"></a><h2>LWRES</h2>
<div class="literallayout"><p><br>
lwres {<br>
listen-on [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
@@ -148,7 +156,7 @@ lwres {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543660"></a><h2>OPTIONS</h2>
+<a name="id2543699"></a><h2>OPTIONS</h2>
<div class="literallayout"><p><br>
options {<br>
avoid-v4-udp-ports { <em class="replaceable"><code>port</code></em>; ... };<br>
@@ -184,6 +192,7 @@ options {<br>
tcp-listen-queue <em class="replaceable"><code>integer</code></em>;<br>
tkey-dhkey <em class="replaceable"><code>quoted_string</code></em> <em class="replaceable"><code>integer</code></em>;<br>
tkey-gssapi-credential <em class="replaceable"><code>quoted_string</code></em>;<br>
+ tkey-gssapi-keytab <em class="replaceable"><code>quoted_string</code></em>;<br>
tkey-domain <em class="replaceable"><code>quoted_string</code></em>;<br>
transfers-per-ns <em class="replaceable"><code>integer</code></em>;<br>
transfers-in <em class="replaceable"><code>integer</code></em>;<br>
@@ -212,6 +221,7 @@ options {<br>
queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br>
queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br>
cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br>
min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br>
lame-ttl <em class="replaceable"><code>integer</code></em>;<br>
max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
@@ -242,9 +252,21 @@ options {<br>
dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br>
dnssec-validation <em class="replaceable"><code>boolean</code></em>;<br>
dnssec-lookaside <em class="replaceable"><code>string</code></em> trust-anchor <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-lookaside ( <em class="replaceable"><code>auto</code></em> | <em class="replaceable"><code>domain</code></em> trust-anchor <em class="replaceable"><code>domain</code></em> );<br>
dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
<br>
+ dns64-server <em class="replaceable"><code>string</code></em>;<br>
+ dns64-contact <em class="replaceable"><code>string</code></em>;<br>
+ dns64 <em class="replaceable"><code>prefix</code></em> {<br>
+ clients { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ exclude { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ mapped { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ break-dnssec <em class="replaceable"><code>boolean</code></em>;<br>
+ recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+ suffix <em class="replaceable"><code>ipv6_address</code></em>;<br>
+ };<br>
+<br>
empty-server <em class="replaceable"><code>string</code></em>;<br>
empty-contact <em class="replaceable"><code>string</code></em>;<br>
empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
@@ -261,6 +283,7 @@ options {<br>
allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
<br>
masterfile-format ( text | raw );<br>
notify <em class="replaceable"><code>notifytype</code></em>;<br>
@@ -307,9 +330,18 @@ options {<br>
<br>
zone-statistics <em class="replaceable"><code>boolean</code></em>;<br>
key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ managed-keys-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ auto-dnssec <code class="constant">allow</code>|<code class="constant">maintain</code>|<code class="constant">create</code>|<code class="constant">off</code>;<br>
try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
+ deny-answer-addresses {<br>
+ <em class="replaceable"><code>address_match_list</code></em><br>
+ } [<span class="optional"> except-from { <em class="replaceable"><code>namelist</code></em> } </span>];<br>
+ deny-answer-aliases {<br>
+ <em class="replaceable"><code>namelist</code></em><br>
+ } [<span class="optional"> except-from { <em class="replaceable"><code>namelist</code></em> } </span>];<br>
<br>
nsec3-test-zone <em class="replaceable"><code>boolean</code></em>;  // testing only<br>
<br>
@@ -329,7 +361,7 @@ options {<br>
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2544452"></a><h2>VIEW</h2>
+<a name="id2544577"></a><h2>VIEW</h2>
<div class="literallayout"><p><br>
view <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br>
match-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
@@ -350,7 +382,8 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
};<br>
<br>
trusted-keys {<br>
- <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; ...<br>
+ <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>;<br>
+ [<span class="optional">...</span>]<br>
};<br>
<br>
allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
@@ -375,6 +408,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br>
queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br>
cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ resolver-query-timeout <em class="replaceable"><code>integer</code></em>;<br>
min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br>
lame-ttl <em class="replaceable"><code>integer</code></em>;<br>
max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
@@ -408,6 +442,17 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
<br>
+ dns64-server <em class="replaceable"><code>string</code></em>;<br>
+ dns64-contact <em class="replaceable"><code>string</code></em>;<br>
+ dns64 <em class="replaceable"><code>prefix</code></em> {<br>
+ clients { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ exclude { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ mapped { <font color="red">&lt;replacable&gt;acl&lt;/replacable&gt;</font>; };<br>
+ break-dnssec <em class="replaceable"><code>boolean</code></em>;<br>
+ recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+ suffix <em class="replaceable"><code>ipv6_address</code></em>;<br>
+ };<br>
+<br>
empty-server <em class="replaceable"><code>string</code></em>;<br>
empty-contact <em class="replaceable"><code>string</code></em>;<br>
empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
@@ -424,6 +469,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
<br>
masterfile-format ( text | raw );<br>
notify <em class="replaceable"><code>notifytype</code></em>;<br>
@@ -468,6 +514,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
<br>
allow-v6-synthesis { <em class="replaceable"><code>address_match_element</code></em>; ... }; // obsolete<br>
fetch-glue <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
@@ -477,7 +524,7 @@ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2545113"></a><h2>ZONE</h2>
+<a name="id2545280"></a><h2>ZONE</h2>
<div class="literallayout"><p><br>
zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br>
type ( master | slave | stub | hint |<br>
@@ -501,20 +548,23 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
ixfr-from-differences <em class="replaceable"><code>boolean</code></em>;<br>
journal <em class="replaceable"><code>quoted_string</code></em>;<br>
zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-secure-to-insecure <em class="replaceable"><code>boolean</code></em>;<br>
<br>
allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
- update-policy {<br>
+ update-policy <em class="replaceable"><code>local</code></em> | <em class="replaceable"><code> {<br>
( grant | deny ) <em class="replaceable"><code>string</code></em><br>
( name | subdomain | wildcard | self | selfsub | selfwild |<br>
                  krb5-self | ms-self | krb5-subdomain | ms-subdomain |<br>
-   tcp-self | 6to4-self ) <em class="replaceable"><code>string</code></em><br>
- <em class="replaceable"><code>rrtypelist</code></em>; ...<br>
- };<br>
+   tcp-self | zonesub | 6to4-self ) <em class="replaceable"><code>string</code></em><br>
+ <em class="replaceable"><code>rrtypelist</code></em>;<br>
+ [<span class="optional">...</span>]<br>
+ }</code></em>;<br>
update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-dnskey-kskonly <em class="replaceable"><code>boolean</code></em>;<br>
<br>
masterfile-format ( text | raw );<br>
notify <em class="replaceable"><code>notifytype</code></em>;<br>
@@ -569,12 +619,12 @@ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><c
</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2545410"></a><h2>FILES</h2>
+<a name="id2545659"></a><h2>FILES</h2>
<p><code class="filename">/etc/named.conf</code>
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2545421"></a><h2>SEE ALSO</h2>
+<a name="id2545671"></a><h2>SEE ALSO</h2>
<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
<span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
<span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
diff --git a/contrib/bind9/bin/named/named.docbook b/contrib/bind9/bin/named/named.docbook
index 808e998eb8a5..214f8ac6e9d7 100644
--- a/contrib/bind9/bin/named/named.docbook
+++ b/contrib/bind9/bin/named/named.docbook
@@ -18,7 +18,7 @@
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: named.docbook,v 1.23.14.2 2009-12-03 04:49:32 tbox Exp $ -->
+<!-- $Id: named.docbook,v 1.26 2009-10-05 17:30:49 fdupont Exp $ -->
<refentry id="man.named">
<refentryinfo>
<date>May 21, 2009</date>
@@ -60,6 +60,7 @@
<arg><option>-6</option></arg>
<arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
<arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
+ <arg><option>-E <replaceable class="parameter">engine-name</replaceable></option></arg>
<arg><option>-f</option></arg>
<arg><option>-g</option></arg>
<arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
@@ -116,6 +117,7 @@
</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>-c <replaceable class="parameter">config-file</replaceable></term>
<listitem>
@@ -145,6 +147,19 @@
</varlistentry>
<varlistentry>
+ <term>-E <replaceable class="parameter">engine-name</replaceable></term>
+ <listitem>
+ <para>
+ Use a crypto hardware (OpenSSL engine) for the crypto operations
+ it supports, for instance re-signing with private keys from
+ a secure key store. When compiled with PKCS#11 support
+ <replaceable class="parameter">engine-name</replaceable>
+ defaults to pkcs11, the empty name resets it to no engine.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>-f</term>
<listitem>
<para>
diff --git a/contrib/bind9/bin/named/named.html b/contrib/bind9/bin/named/named.html
index 031b4921ff4e..fa869c4c6d10 100644
--- a/contrib/bind9/bin/named/named.html
+++ b/contrib/bind9/bin/named/named.html
@@ -14,7 +14,7 @@
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: named.html,v 1.30.14.2 2009-12-03 05:06:38 tbox Exp $ -->
+<!-- $Id: named.html,v 1.33 2009-10-06 01:14:41 tbox Exp $ -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -29,10 +29,10 @@
</div>
<div class="refsynopsisdiv">
<h2>Synopsis</h2>
-<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div>
+<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-E <em class="replaceable"><code>engine-name</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543472"></a><h2>DESCRIPTION</h2>
+<a name="id2543480"></a><h2>DESCRIPTION</h2>
<p><span><strong class="command">named</strong></span>
is a Domain Name System (DNS) server,
part of the BIND 9 distribution from ISC. For more
@@ -47,7 +47,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543496"></a><h2>OPTIONS</h2>
+<a name="id2543505"></a><h2>OPTIONS</h2>
<div class="variablelist"><dl>
<dt><span class="term">-4</span></dt>
<dd><p>
@@ -79,6 +79,14 @@
Debugging traces from <span><strong class="command">named</strong></span> become
more verbose as the debug level increases.
</p></dd>
+<dt><span class="term">-E <em class="replaceable"><code>engine-name</code></em></span></dt>
+<dd><p>
+ Use a crypto hardware (OpenSSL engine) for the crypto operations
+ it supports, for instance re-signing with private keys from
+ a secure key store. When compiled with PKCS#11 support
+ <em class="replaceable"><code>engine-name</code></em>
+ defaults to pkcs11, the empty name resets it to no engine.
+ </p></dd>
<dt><span class="term">-f</span></dt>
<dd><p>
Run the server in the foreground (i.e. do not daemonize).
@@ -220,7 +228,7 @@
</dl></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2543931"></a><h2>SIGNALS</h2>
+<a name="id2543962"></a><h2>SIGNALS</h2>
<p>
In routine operation, signals should not be used to control
the nameserver; <span><strong class="command">rndc</strong></span> should be used
@@ -241,7 +249,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2543979"></a><h2>CONFIGURATION</h2>
+<a name="id2544010"></a><h2>CONFIGURATION</h2>
<p>
The <span><strong class="command">named</strong></span> configuration file is too complex
to describe in detail here. A complete description is provided
@@ -258,7 +266,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2544016"></a><h2>FILES</h2>
+<a name="id2544046"></a><h2>FILES</h2>
<div class="variablelist"><dl>
<dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt>
<dd><p>
@@ -271,7 +279,7 @@
</dl></div>
</div>
<div class="refsect1" lang="en">
-<a name="id2544123"></a><h2>SEE ALSO</h2>
+<a name="id2544086"></a><h2>SEE ALSO</h2>
<p><em class="citetitle">RFC 1033</em>,
<em class="citetitle">RFC 1034</em>,
<em class="citetitle">RFC 1035</em>,
@@ -284,7 +292,7 @@
</p>
</div>
<div class="refsect1" lang="en">
-<a name="id2544194"></a><h2>AUTHOR</h2>
+<a name="id2544293"></a><h2>AUTHOR</h2>
<p><span class="corpauthor">Internet Systems Consortium</span>
</p>
</div>
diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c
index fa34da6e28c0..1950257dca2c 100644
--- a/contrib/bind9/bin/named/query.c
+++ b/contrib/bind9/bin/named/query.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: query.c,v 1.313.20.24 2010-09-24 08:09:07 marka Exp $ */
+/* $Id: query.c,v 1.353.8.2.2.5 2011-06-09 03:17:10 marka Exp $ */
/*! \file */
@@ -34,6 +34,7 @@
#ifdef DLZ
#include <dns/dlz.h>
#endif
+#include <dns/dns64.h>
#include <dns/dnssec.h>
#include <dns/events.h>
#include <dns/message.h>
@@ -62,6 +63,17 @@
#include <named/sortlist.h>
#include <named/xfrout.h>
+#if 0
+/*
+ * It has been recommended that DNS64 be changed to return excluded
+ * AAAA addresses if DNS64 synthesis does not occur. This minimises
+ * the impact on the lookup results. While most DNS AAAA lookups are
+ * done to send IP packets to a host, not all of them are and filtering
+ * excluded addresses has a negative impact on those uses.
+ */
+#define dns64_bis_return_excluded_addresses 1
+#endif
+
/*% Partial answer? */
#define PARTIALANSWER(c) (((c)->query.attributes & \
NS_QUERYATTR_PARTIALANSWER) != 0)
@@ -92,6 +104,12 @@
/*% Secure? */
#define SECURE(c) (((c)->query.attributes & \
NS_QUERYATTR_SECURE) != 0)
+/*% DNS64 A lookup? */
+#define DNS64(c) (((c)->query.attributes & \
+ NS_QUERYATTR_DNS64) != 0)
+
+#define DNS64EXCLUDE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_DNS64EXCLUDE) != 0)
/*% No QNAME Proof? */
#define NOQNAME(r) (((r)->attributes & \
@@ -116,6 +134,7 @@
#define DNS_GETDB_NOEXACT 0x01U
#define DNS_GETDB_NOLOG 0x02U
#define DNS_GETDB_PARTIAL 0x04U
+#define DNS_GETDB_IGNOREACL 0x08U
#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
@@ -141,6 +160,9 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
static inline void
log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
+static void
+rpz_st_clear(ns_client_t *client);
+
/*%
* Increment query statistics counters.
*/
@@ -252,6 +274,19 @@ ns_query_cancel(ns_client_t *client) {
}
static inline void
+query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
+ dns_rdataset_t *rdataset = *rdatasetp;
+
+ CTRACE("query_putrdataset");
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, rdatasetp);
+ }
+ CTRACE("query_putrdataset: done");
+}
+
+static inline void
query_reset(ns_client_t *client, isc_boolean_t everything) {
isc_buffer_t *dbuf, *dbuf_next;
ns_dbversion_t *dbversion, *dbversion_next;
@@ -285,6 +320,18 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
if (client->query.authzone != NULL)
dns_zone_detach(&client->query.authzone);
+ if (client->query.dns64_aaaa != NULL)
+ query_putrdataset(client, &client->query.dns64_aaaa);
+ if (client->query.dns64_sigaaaa != NULL)
+ query_putrdataset(client, &client->query.dns64_sigaaaa);
+ if (client->query.dns64_aaaaok != NULL) {
+ isc_mem_put(client->mctx, client->query.dns64_aaaaok,
+ client->query.dns64_aaaaoklen *
+ sizeof(isc_boolean_t));
+ client->query.dns64_aaaaok = NULL;
+ client->query.dns64_aaaaoklen = 0;
+ }
+
query_freefreeversions(client, everything);
for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
@@ -310,13 +357,22 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
NS_QUERYATTR_SECURE);
client->query.restarts = 0;
client->query.timerset = ISC_FALSE;
+ if (client->query.rpz_st != NULL) {
+ rpz_st_clear(client);
+ if (everything) {
+ isc_mem_put(client->mctx, client->query.rpz_st,
+ sizeof(*client->query.rpz_st));
+ client->query.rpz_st = NULL;
+ }
+ }
client->query.origqname = NULL;
- client->query.qname = NULL;
client->query.dboptions = 0;
client->query.fetchoptions = 0;
client->query.gluedb = NULL;
client->query.authdbset = ISC_FALSE;
client->query.isreferral = ISC_FALSE;
+ client->query.dns64_options = 0;
+ client->query.dns64_ttl = ISC_UINT32_MAX;
}
static void
@@ -473,20 +529,6 @@ query_newrdataset(ns_client_t *client) {
return (rdataset);
}
-static inline void
-query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
- dns_rdataset_t *rdataset = *rdatasetp;
-
- CTRACE("query_putrdataset");
- if (rdataset != NULL) {
- if (dns_rdataset_isassociated(rdataset))
- dns_rdataset_disassociate(rdataset);
- dns_message_puttemprdataset(client->message, rdatasetp);
- }
- CTRACE("query_putrdataset: done");
-}
-
-
static inline isc_result_t
query_newdbversion(ns_client_t *client, unsigned int n) {
unsigned int i;
@@ -540,6 +582,7 @@ ns_query_init(ns_client_t *client) {
ISC_LIST_INIT(client->query.freeversions);
client->query.restarts = 0;
client->query.timerset = ISC_FALSE;
+ client->query.rpz_st = NULL;
client->query.qname = NULL;
result = isc_mutex_init(&client->query.fetchlock);
if (result != ISC_R_SUCCESS)
@@ -549,6 +592,10 @@ ns_query_init(ns_client_t *client) {
client->query.authzone = NULL;
client->query.authdbset = ISC_FALSE;
client->query.isreferral = ISC_FALSE;
+ client->query.dns64_aaaa = NULL;
+ client->query.dns64_sigaaaa = NULL;
+ client->query.dns64_aaaaok = NULL;
+ client->query.dns64_aaaaoklen = 0;
query_reset(client, ISC_FALSE);
result = query_newdbversion(client, 3);
if (result != ISC_R_SUCCESS) {
@@ -563,8 +610,7 @@ ns_query_init(ns_client_t *client) {
}
static inline ns_dbversion_t *
-query_findversion(ns_client_t *client, dns_db_t *db,
- isc_boolean_t *newzonep)
+query_findversion(ns_client_t *client, dns_db_t *db)
{
ns_dbversion_t *dbversion;
@@ -590,12 +636,11 @@ query_findversion(ns_client_t *client, dns_db_t *db,
return (NULL);
dns_db_attach(db, &dbversion->db);
dns_db_currentversion(db, &dbversion->version);
+ dbversion->acl_checked = ISC_FALSE;
dbversion->queryok = ISC_FALSE;
ISC_LIST_APPEND(client->query.activeversions,
dbversion, link);
- *newzonep = ISC_TRUE;
- } else
- *newzonep = ISC_FALSE;
+ }
return (dbversion);
}
@@ -607,7 +652,6 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
dns_dbversion_t **versionp)
{
isc_result_t result;
- isc_boolean_t check_acl, new_zone;
dns_acl_t *queryacl;
ns_dbversion_t *dbversion;
@@ -623,7 +667,17 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
if (!client->view->additionalfromauth &&
client->query.authdbset &&
db != client->query.authdb)
- goto refuse;
+ return (DNS_R_REFUSED);
+
+ /*
+ * Non recursive query to a static-stub zone is prohibited; its
+ * zone content is not public data, but a part of local configuration
+ * and should not be disclosed.
+ */
+ if (dns_zone_gettype(zone) == dns_zone_staticstub &&
+ !RECURSIONOK(client)) {
+ return (DNS_R_REFUSED);
+ }
/*
* If the zone has an ACL, we'll check it, otherwise
@@ -633,23 +687,19 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
* Also, get the database version to use.
*/
- check_acl = ISC_TRUE; /* Keep compiler happy. */
- queryacl = NULL;
-
/*
* Get the current version of this database.
*/
- dbversion = query_findversion(client, db, &new_zone);
- if (dbversion == NULL) {
- result = DNS_R_SERVFAIL;
- goto fail;
- }
- if (new_zone) {
- check_acl = ISC_TRUE;
- } else if (!dbversion->queryok) {
- goto refuse;
- } else {
- check_acl = ISC_FALSE;
+ dbversion = query_findversion(client, db);
+ if (dbversion == NULL)
+ return (DNS_R_SERVFAIL);
+
+ if ((options & DNS_GETDB_IGNOREACL) != 0)
+ goto approved;
+ if (dbversion->acl_checked) {
+ if (!dbversion->queryok)
+ return (DNS_R_REFUSED);
+ goto approved;
}
queryacl = dns_zone_getqueryacl(zone);
@@ -663,88 +713,69 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name,
* allowed to make queries, otherwise the query should
* be refused.
*/
- check_acl = ISC_FALSE;
+ dbversion->acl_checked = ISC_TRUE;
if ((client->query.attributes &
- NS_QUERYATTR_QUERYOK) == 0)
- goto refuse;
- } else {
- /*
- * We haven't evaluated the view's queryacl yet.
- */
- check_acl = ISC_TRUE;
+ NS_QUERYATTR_QUERYOK) == 0) {
+ dbversion->queryok = ISC_FALSE;
+ return (DNS_R_REFUSED);
+ }
+ dbversion->queryok = ISC_TRUE;
+ goto approved;
}
}
- if (check_acl) {
- isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
-
- result = ns_client_checkaclsilent(client, NULL, queryacl,
- ISC_TRUE);
- if (log) {
- char msg[NS_CLIENT_ACLMSGSIZE("query")];
- if (result == ISC_R_SUCCESS) {
- if (isc_log_wouldlog(ns_g_lctx,
- ISC_LOG_DEBUG(3)))
- {
- ns_client_aclmsg("query", name, qtype,
- client->view->rdclass,
- msg, sizeof(msg));
- ns_client_log(client,
- DNS_LOGCATEGORY_SECURITY,
- NS_LOGMODULE_QUERY,
- ISC_LOG_DEBUG(3),
- "%s approved", msg);
- }
- } else {
+ result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
+ if ((options & DNS_GETDB_NOLOG) == 0) {
+ char msg[NS_CLIENT_ACLMSGSIZE("query")];
+ if (result == ISC_R_SUCCESS) {
+ if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) {
ns_client_aclmsg("query", name, qtype,
client->view->rdclass,
msg, sizeof(msg));
- ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
- NS_LOGMODULE_QUERY, ISC_LOG_INFO,
- "%s denied", msg);
+ ns_client_log(client,
+ DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_DEBUG(3),
+ "%s approved", msg);
}
+ } else {
+ ns_client_aclmsg("query", name, qtype,
+ client->view->rdclass,
+ msg, sizeof(msg));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "%s denied", msg);
}
+ }
- if (queryacl == client->view->queryacl) {
- if (result == ISC_R_SUCCESS) {
- /*
- * We were allowed by the default
- * "allow-query" ACL. Remember this so we
- * don't have to check again.
- */
- client->query.attributes |=
- NS_QUERYATTR_QUERYOK;
- }
+ if (queryacl == client->view->queryacl) {
+ if (result == ISC_R_SUCCESS) {
/*
- * We've now evaluated the view's query ACL, and
- * the NS_QUERYATTR_QUERYOK attribute is now valid.
+ * We were allowed by the default
+ * "allow-query" ACL. Remember this so we
+ * don't have to check again.
*/
- client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
+ client->query.attributes |= NS_QUERYATTR_QUERYOK;
}
-
- if (result != ISC_R_SUCCESS)
- goto refuse;
+ /*
+ * We've now evaluated the view's query ACL, and
+ * the NS_QUERYATTR_QUERYOK attribute is now valid.
+ */
+ client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
}
- /* Approved. */
-
- /*
- * Remember the result of the ACL check so we
- * don't have to check again.
- */
+ dbversion->acl_checked = ISC_TRUE;
+ if (result != ISC_R_SUCCESS) {
+ dbversion->queryok = ISC_FALSE;
+ return (DNS_R_REFUSED);
+ }
dbversion->queryok = ISC_TRUE;
+ approved:
/* Transfer ownership, if necessary. */
if (versionp != NULL)
*versionp = dbversion->version;
-
return (ISC_R_SUCCESS);
-
- refuse:
- return (DNS_R_REFUSED);
-
- fail:
- return (result);
}
static inline isc_result_t
@@ -800,6 +831,97 @@ query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
return (result);
}
+static void
+rpz_log(ns_client_t *client) {
+ char namebuf1[DNS_NAME_FORMATSIZE];
+ char namebuf2[DNS_NAME_FORMATSIZE];
+ dns_rpz_st_t *st;
+ const char *pat;
+
+ if (!ns_g_server->log_queries ||
+ !isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL))
+ return;
+
+ st = client->query.rpz_st;
+ dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1));
+ dns_name_format(st->qname, namebuf2, sizeof(namebuf2));
+
+ switch (st->m.policy) {
+ case DNS_RPZ_POLICY_NO_OP:
+ pat ="response policy %s rewrite %s NO-OP using %s";
+ break;
+ case DNS_RPZ_POLICY_NXDOMAIN:
+ pat = "response policy %s rewrite %s to NXDOMAIN using %s";
+ break;
+ case DNS_RPZ_POLICY_NODATA:
+ pat = "response policy %s rewrite %s to NODATA using %s";
+ break;
+ case DNS_RPZ_POLICY_RECORD:
+ case DNS_RPZ_POLICY_CNAME:
+ pat = "response policy %s rewrite %s using %s";
+ break;
+ default:
+ INSIST(0);
+ }
+ ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
+ DNS_RPZ_INFO_LEVEL, pat, dns_rpz_type2str(st->m.type),
+ namebuf1, namebuf2);
+}
+
+static void
+rpz_fail_log(ns_client_t *client, int level, dns_rpz_type_t rpz_type,
+ dns_name_t *name, const char *str, isc_result_t result)
+{
+ char namebuf1[DNS_NAME_FORMATSIZE];
+ char namebuf2[DNS_NAME_FORMATSIZE];
+
+ if (!ns_g_server->log_queries || !isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1));
+ dns_name_format(name, namebuf2, sizeof(namebuf2));
+ ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS,
+ NS_LOGMODULE_QUERY, level,
+ "response policy %s rewrite %s via %s %sfailed: %s",
+ dns_rpz_type2str(rpz_type),
+ namebuf1, namebuf2, str, 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, dns_zone_t **zonep,
+ dns_db_t **dbp, dns_dbversion_t **versionp)
+{
+ char namebuf1[DNS_NAME_FORMATSIZE];
+ char namebuf2[DNS_NAME_FORMATSIZE];
+ dns_dbversion_t *rpz_version = NULL;
+ isc_result_t result;
+
+ result = query_getzonedb(client, rpz_qname, dns_rdatatype_any,
+ DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
+ if (result == ISC_R_SUCCESS) {
+ if (ns_g_server->log_queries &&
+ 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));
+ ns_client_log(client, NS_LOGCATEGORY_QUERIES,
+ NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
+ "try rpz %s rewrite %s via %s",
+ dns_rpz_type2str(rpz_type),
+ namebuf1, namebuf2);
+ }
+ *versionp = rpz_version;
+ return (ISC_R_SUCCESS);
+ }
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname,
+ "query_getzonedb() ", result);
+ return (result);
+}
+
static inline isc_result_t
query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
dns_db_t **dbp, unsigned int options)
@@ -1958,6 +2080,323 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
CTRACE("query_addrdataset: done");
}
+static isc_result_t
+query_dns64(ns_client_t *client, dns_name_t **namep, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset, isc_buffer_t *dbuf,
+ dns_section_t section)
+{
+ dns_name_t *name, *mname;
+ dns_rdata_t *dns64_rdata;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t *dns64_rdatalist;
+ dns_rdataset_t *dns64_rdataset;
+ dns_rdataset_t *mrdataset;
+ isc_buffer_t *buffer;
+ isc_region_t r;
+ isc_result_t result;
+ dns_view_t *view = client->view;
+ isc_netaddr_t netaddr;
+ dns_dns64_t *dns64;
+ unsigned int flags = 0;
+
+ /*%
+ * To the current response for 'client', add the answer RRset
+ * '*rdatasetp' and an optional signature set '*sigrdatasetp', with
+ * owner name '*namep', to section 'section', unless they are
+ * already there. Also add any pertinent additional data.
+ *
+ * If 'dbuf' is not NULL, then '*namep' is the name whose data is
+ * stored in 'dbuf'. In this case, query_addrrset() guarantees that
+ * when it returns the name will either have been kept or released.
+ */
+ CTRACE("query_dns64");
+ name = *namep;
+ mname = NULL;
+ mrdataset = NULL;
+ buffer = NULL;
+ dns64_rdata = NULL;
+ dns64_rdataset = NULL;
+ dns64_rdatalist = NULL;
+ result = dns_message_findname(client->message, section,
+ name, dns_rdatatype_aaaa,
+ rdataset->covers,
+ &mname, &mrdataset);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got an RRset of the given name and type.
+ * There's nothing else to do;
+ */
+ CTRACE("query_dns64: dns_message_findname succeeded: done");
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ return (ISC_R_SUCCESS);
+ } else if (result == DNS_R_NXDOMAIN) {
+ /*
+ * The name doesn't exist.
+ */
+ if (dbuf != NULL)
+ query_keepname(client, name, dbuf);
+ dns_message_addname(client->message, name, section);
+ *namep = NULL;
+ mname = name;
+ } else {
+ RUNTIME_CHECK(result == DNS_R_NXRRSET);
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ }
+
+ if (rdataset->trust != dns_trust_secure &&
+ (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY))
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ result = isc_buffer_allocate(client->mctx, &buffer, view->dns64cnt *
+ 16 * dns_rdataset_count(rdataset));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdataset(client->message, &dns64_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdatalist(client->message,
+ &dns64_rdatalist);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdataset_init(dns64_rdataset);
+ dns_rdatalist_init(dns64_rdatalist);
+ dns64_rdatalist->rdclass = dns_rdataclass_in;
+ dns64_rdatalist->type = dns_rdatatype_aaaa;
+ if (client->query.dns64_ttl != ISC_UINT32_MAX)
+ dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl,
+ client->query.dns64_ttl);
+ else
+ dns64_rdatalist->ttl = ISC_MIN(rdataset->ttl, 600);
+
+ if (RECURSIONOK(client))
+ flags |= DNS_DNS64_RECURSIVE;
+
+ /*
+ * We use the signatures from the A lookup to set DNS_DNS64_DNSSEC
+ * as this provides a easy way to see if the answer was signed.
+ */
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ flags |= DNS_DNS64_DNSSEC;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ for (dns64 = ISC_LIST_HEAD(client->view->dns64);
+ dns64 != NULL; dns64 = dns_dns64_next(dns64)) {
+
+ dns_rdataset_current(rdataset, &rdata);
+ isc__buffer_availableregion(buffer, &r);
+ INSIST(r.length >= 16);
+ result = dns_dns64_aaaafroma(dns64, &netaddr,
+ client->signer,
+ &ns_g_server->aclenv,
+ flags, rdata.data, r.base);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+ isc_buffer_add(buffer, 16);
+ isc_buffer_remainingregion(buffer, &r);
+ isc_buffer_forward(buffer, 16);
+ result = dns_message_gettemprdata(client->message,
+ &dns64_rdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdata_init(dns64_rdata);
+ dns_rdata_fromregion(dns64_rdata, dns_rdataclass_in,
+ dns_rdatatype_aaaa, &r);
+ ISC_LIST_APPEND(dns64_rdatalist->rdata, dns64_rdata,
+ link);
+ dns64_rdata = NULL;
+ dns_rdata_reset(&rdata);
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup;
+
+ if (ISC_LIST_EMPTY(dns64_rdatalist->rdata))
+ goto cleanup;
+
+ result = dns_rdatalist_tordataset(dns64_rdatalist, dns64_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
+ dns64_rdataset->trust = rdataset->trust;
+ query_addrdataset(client, mname, dns64_rdataset);
+ dns64_rdataset = NULL;
+ dns64_rdatalist = NULL;
+ dns_message_takebuffer(client->message, &buffer);
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (buffer != NULL)
+ isc_buffer_free(&buffer);
+
+ if (dns64_rdata != NULL)
+ dns_message_puttemprdata(client->message, &dns64_rdata);
+
+ if (dns64_rdataset != NULL)
+ dns_message_puttemprdataset(client->message, &dns64_rdataset);
+
+ if (dns64_rdatalist != NULL) {
+ for (dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata);
+ dns64_rdata != NULL;
+ dns64_rdata = ISC_LIST_HEAD(dns64_rdatalist->rdata))
+ {
+ ISC_LIST_UNLINK(dns64_rdatalist->rdata,
+ dns64_rdata, link);
+ dns_message_puttemprdata(client->message, &dns64_rdata);
+ }
+ dns_message_puttemprdatalist(client->message, &dns64_rdatalist);
+ }
+
+ CTRACE("query_dns64: done");
+ return (result);
+}
+
+static void
+query_filter64(ns_client_t *client, dns_name_t **namep,
+ dns_rdataset_t *rdataset, isc_buffer_t *dbuf,
+ dns_section_t section)
+{
+ dns_name_t *name, *mname;
+ dns_rdata_t *myrdata;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatalist_t *myrdatalist;
+ dns_rdataset_t *myrdataset;
+ isc_buffer_t *buffer;
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int i;
+
+ CTRACE("query_filter64");
+
+ INSIST(client->query.dns64_aaaaok != NULL);
+ INSIST(client->query.dns64_aaaaoklen == dns_rdataset_count(rdataset));
+
+ name = *namep;
+ mname = NULL;
+ buffer = NULL;
+ myrdata = NULL;
+ myrdataset = NULL;
+ myrdatalist = NULL;
+ result = dns_message_findname(client->message, section,
+ name, dns_rdatatype_aaaa,
+ rdataset->covers,
+ &mname, &myrdataset);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got an RRset of the given name and type.
+ * There's nothing else to do;
+ */
+ CTRACE("query_filter64: dns_message_findname succeeded: done");
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ return;
+ } else if (result == DNS_R_NXDOMAIN) {
+ mname = name;
+ *namep = NULL;
+ } else {
+ RUNTIME_CHECK(result == DNS_R_NXRRSET);
+ if (dbuf != NULL)
+ query_releasename(client, namep);
+ dbuf = NULL;
+ }
+
+ if (rdataset->trust != dns_trust_secure &&
+ (section == DNS_SECTION_ANSWER ||
+ section == DNS_SECTION_AUTHORITY))
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ result = isc_buffer_allocate(client->mctx, &buffer,
+ 16 * dns_rdataset_count(rdataset));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdataset(client->message, &myrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdatalist(client->message, &myrdatalist);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdataset_init(myrdataset);
+ dns_rdatalist_init(myrdatalist);
+ myrdatalist->rdclass = dns_rdataclass_in;
+ myrdatalist->type = dns_rdatatype_aaaa;
+ myrdatalist->ttl = rdataset->ttl;
+
+ i = 0;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ if (!client->query.dns64_aaaaok[i++])
+ continue;
+ dns_rdataset_current(rdataset, &rdata);
+ INSIST(rdata.length == 16);
+ isc_buffer_putmem(buffer, rdata.data, rdata.length);
+ isc_buffer_remainingregion(buffer, &r);
+ isc_buffer_forward(buffer, rdata.length);
+ result = dns_message_gettemprdata(client->message, &myrdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdata_init(myrdata);
+ dns_rdata_fromregion(myrdata, dns_rdataclass_in,
+ dns_rdatatype_aaaa, &r);
+ ISC_LIST_APPEND(myrdatalist->rdata, myrdata, link);
+ myrdata = NULL;
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup;
+
+ result = dns_rdatalist_tordataset(myrdatalist, myrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ client->query.attributes |= NS_QUERYATTR_NOADDITIONAL;
+ if (mname == name) {
+ if (dbuf != NULL)
+ query_keepname(client, name, dbuf);
+ dns_message_addname(client->message, name, section);
+ dbuf = NULL;
+ }
+ myrdataset->trust = rdataset->trust;
+ query_addrdataset(client, mname, myrdataset);
+ myrdataset = NULL;
+ myrdatalist = NULL;
+ dns_message_takebuffer(client->message, &buffer);
+
+ cleanup:
+ if (buffer != NULL)
+ isc_buffer_free(&buffer);
+
+ if (myrdata != NULL)
+ dns_message_puttemprdata(client->message, &myrdata);
+
+ if (myrdataset != NULL)
+ dns_message_puttemprdataset(client->message, &myrdataset);
+
+ if (myrdatalist != NULL) {
+ for (myrdata = ISC_LIST_HEAD(myrdatalist->rdata);
+ myrdata != NULL;
+ myrdata = ISC_LIST_HEAD(myrdatalist->rdata))
+ {
+ ISC_LIST_UNLINK(myrdatalist->rdata, myrdata, link);
+ dns_message_puttemprdata(client->message, &myrdata);
+ }
+ dns_message_puttemprdatalist(client->message, &myrdatalist);
+ }
+ if (dbuf != NULL)
+ query_releasename(client, &name);
+
+ CTRACE("query_filter64: done");
+}
+
static void
query_addrrset(ns_client_t *client, dns_name_t **namep,
dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp,
@@ -2036,7 +2475,7 @@ query_addrrset(ns_client_t *client, dns_name_t **namep,
static inline isc_result_t
query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
- isc_boolean_t zero_ttl, isc_boolean_t isassociated)
+ unsigned int override_ttl, isc_boolean_t isassociated)
{
dns_name_t *name;
dns_dbnode_t *node;
@@ -2119,10 +2558,11 @@ query_addsoa(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version,
if (result != ISC_R_SUCCESS)
goto cleanup;
- if (zero_ttl) {
- rdataset->ttl = 0;
+ if (override_ttl != ISC_UINT32_MAX &&
+ override_ttl < rdataset->ttl) {
+ rdataset->ttl = override_ttl;
if (sigrdataset != NULL)
- sigrdataset->ttl = 0;
+ sigrdataset->ttl = override_ttl;
}
/*
@@ -2246,67 +2686,79 @@ query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
return (eresult);
}
-static inline isc_result_t
-query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
- dns_rdataset_t *dname, dns_name_t **anamep,
- dns_rdatatype_t type)
+static isc_result_t
+query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
+ dns_trust_t trust, dns_ttl_t ttl)
{
dns_rdataset_t *rdataset;
dns_rdatalist_t *rdatalist;
dns_rdata_t *rdata;
- isc_result_t result;
isc_region_t r;
+ dns_name_t *aname;
+ isc_result_t result;
/*
* We assume the name data referred to by tname won't go away.
*/
- REQUIRE(anamep != NULL);
+ aname = NULL;
+ result = dns_message_gettempname(client->message, &aname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_name_dup(qname, client->mctx, aname);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ return (result);
+ }
rdatalist = NULL;
result = dns_message_gettemprdatalist(client->message, &rdatalist);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
return (result);
+ }
rdata = NULL;
result = dns_message_gettemprdata(client->message, &rdata);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &aname);
+ dns_message_puttemprdatalist(client->message, &rdatalist);
return (result);
+ }
rdataset = NULL;
result = dns_message_gettemprdataset(client->message, &rdataset);
- if (result != ISC_R_SUCCESS)
- return (result);
- dns_rdataset_init(rdataset);
- result = dns_name_dup(qname, client->mctx, *anamep);
if (result != ISC_R_SUCCESS) {
- dns_message_puttemprdataset(client->message, &rdataset);
+ dns_message_puttempname(client->message, &aname);
+ dns_message_puttemprdatalist(client->message, &rdatalist);
+ dns_message_puttemprdata(client->message, &rdata);
return (result);
}
-
- rdatalist->type = type;
+ dns_rdataset_init(rdataset);
+ rdatalist->type = dns_rdatatype_cname;
rdatalist->covers = 0;
rdatalist->rdclass = client->message->rdclass;
- rdatalist->ttl = dname->ttl;
+ rdatalist->ttl = ttl;
dns_name_toregion(tname, &r);
rdata->data = r.base;
rdata->length = r.length;
rdata->rdclass = client->message->rdclass;
- rdata->type = type;
+ rdata->type = dns_rdatatype_cname;
ISC_LIST_INIT(rdatalist->rdata);
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
== ISC_R_SUCCESS);
- rdataset->trust = dname->trust;
+ rdataset->trust = trust;
- query_addrrset(client, anamep, &rdataset, NULL, NULL,
+ query_addrrset(client, &aname, &rdataset, NULL, NULL,
DNS_SECTION_ANSWER);
-
if (rdataset != NULL) {
if (dns_rdataset_isassociated(rdataset))
dns_rdataset_disassociate(rdataset);
dns_message_puttemprdataset(client->message, &rdataset);
}
+ if (aname != NULL)
+ dns_message_puttempname(client->message, &aname);
return (ISC_R_SUCCESS);
}
@@ -2860,7 +3312,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
* j.example -> z.i.example NSEC example
* owner common example
* next common example
- * wild *.f.example
+ * wild *.example
*/
options = client->query.dboptions | DNS_DBFIND_NOWILD;
dns_fixedname_init(&wfixed);
@@ -3196,8 +3648,9 @@ query_resume(isc_task_t *task, isc_event_t *event) {
}
static isc_result_t
-query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
- dns_rdataset_t *nameservers, isc_boolean_t resuming)
+query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
+ dns_name_t *qdomain, dns_rdataset_t *nameservers,
+ isc_boolean_t resuming)
{
isc_result_t result;
dns_rdataset_t *rdataset, *sigrdataset;
@@ -3229,7 +3682,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
NS_LOGMODULE_QUERY,
ISC_LOG_WARNING,
"recursive-clients soft limit "
- "exceeded, aborting oldest query");
+ "exceeded (%d/%d/%d), "
+ "aborting oldest query",
+ client->recursionquota->used,
+ client->recursionquota->soft,
+ client->recursionquota->max);
}
ns_client_killoldestquery(client);
result = ISC_R_SUCCESS;
@@ -3242,7 +3699,11 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
ns_client_log(client, NS_LOGCATEGORY_CLIENT,
NS_LOGMODULE_QUERY,
ISC_LOG_WARNING,
- "no more recursive clients: %s",
+ "no more recursive clients "
+ "(%d/%d/%d): %s",
+ ns_g_server->recursionquota.used,
+ ns_g_server->recursionquota.soft,
+ ns_g_server->recursionquota.max,
isc_result_totext(result));
}
ns_client_killoldestquery(client);
@@ -3289,8 +3750,7 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
else
peeraddr = NULL;
result = dns_resolver_createfetch2(client->view->resolver,
- client->query.qname,
- qtype, qdomain, nameservers,
+ qname, qtype, qdomain, nameservers,
NULL, peeraddr, client->message->id,
client->query.fetchoptions,
client->task,
@@ -3313,6 +3773,696 @@ query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
return (result);
}
+static inline void
+rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
+ dns_rdataset_t **rdatasetp)
+{
+ if (nodep != NULL && *nodep != NULL) {
+ REQUIRE(dbp != NULL && *dbp != NULL);
+ dns_db_detachnode(*dbp, nodep);
+ }
+ if (dbp != NULL && *dbp != NULL)
+ dns_db_detach(dbp);
+ if (zonep != NULL && *zonep != NULL)
+ dns_zone_detach(zonep);
+ if (rdatasetp != NULL && *rdatasetp != NULL &&
+ dns_rdataset_isassociated(*rdatasetp))
+ dns_rdataset_disassociate(*rdatasetp);
+}
+
+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)
+{
+ REQUIRE(rdatasetp != NULL);
+
+ rpz_clean(zonep, dbp, nodep, rdatasetp);
+ if (*rdatasetp == NULL) {
+ *rdatasetp = query_newrdataset(client);
+ if (*rdatasetp == NULL)
+ return (DNS_R_SERVFAIL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rpz_st_clear(ns_client_t *client) {
+ dns_rpz_st_t *st = client->query.rpz_st;
+
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL);
+ if (st->m.rdataset != NULL)
+ query_putrdataset(client, &st->m.rdataset);
+
+ rpz_clean(NULL, &st->ns.db, NULL, NULL);
+ if (st->ns.ns_rdataset != NULL)
+ query_putrdataset(client, &st->ns.ns_rdataset);
+ if (st->ns.r_rdataset != NULL)
+ query_putrdataset(client, &st->ns.r_rdataset);
+
+ rpz_clean(&st->q.zone, &st->q.db, &st->q.node, NULL);
+ if (st->q.rdataset != NULL)
+ query_putrdataset(client, &st->q.rdataset);
+ if (st->q.sigrdataset != NULL)
+ query_putrdataset(client, &st->q.sigrdataset);
+ st->state = 0;
+}
+
+/*
+ * Get NS, A, or AAAA rrset for rpz nsdname or nsip checking.
+ */
+static isc_result_t
+rpz_ns_find(ns_client_t *client, dns_name_t *name, dns_rdatatype_t type,
+ dns_db_t **dbp, dns_dbversion_t *version,
+ dns_rdataset_t **rdatasetp, isc_boolean_t resuming)
+{
+ dns_rpz_st_t *st;
+ isc_boolean_t is_zone;
+ dns_dbnode_t *node;
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ isc_result_t result;
+
+ st = client->query.rpz_st;
+ if ((st->state & DNS_RPZ_RECURSING) != 0) {
+ INSIST(st->ns.r_type == type);
+ INSIST(dns_name_equal(name, st->r_name));
+ INSIST(*rdatasetp == NULL ||
+ !dns_rdataset_isassociated(*rdatasetp));
+ st->state &= ~DNS_RPZ_RECURSING;
+ *dbp = st->ns.db;
+ st->ns.db = NULL;
+ if (*rdatasetp != NULL)
+ query_putrdataset(client, rdatasetp);
+ *rdatasetp = st->ns.r_rdataset;
+ st->ns.r_rdataset = NULL;
+ result = st->ns.r_result;
+ if (result == DNS_R_DELEGATION) {
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL,
+ DNS_RPZ_TYPE_NSIP, name,
+ "rpz_ns_find() ", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ result = DNS_R_SERVFAIL;
+ }
+ return (result);
+ }
+
+ result = rpz_ready(client, NULL, NULL, NULL, rdatasetp);
+ if (result != ISC_R_SUCCESS) {
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ return (result);
+ }
+ if (*dbp != NULL) {
+ is_zone = ISC_FALSE;
+ } else {
+ dns_zone_t *zone;
+
+ version = NULL;
+ zone = NULL;
+ result = query_getdb(client, name, type, 0, &zone, dbp,
+ &version, &is_zone);
+ if (result != ISC_R_SUCCESS) {
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL,
+ DNS_RPZ_TYPE_NSIP, name, "NS getdb() ",
+ result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ return (result);
+ }
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ }
+
+ node = NULL;
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
+ result = dns_db_find(*dbp, name, version, type, 0, client->now, &node,
+ found, *rdatasetp, NULL);
+ if (result == DNS_R_DELEGATION && is_zone && USECACHE(client)) {
+ /*
+ * Try the cache if we're authoritative for an
+ * ancestor but not the domain itself.
+ */
+ rpz_clean(NULL, dbp, &node, rdatasetp);
+ version = NULL;
+ dns_db_attach(client->view->cachedb, dbp);
+ result = dns_db_find(*dbp, name, version, dns_rdatatype_ns,
+ 0, client->now, &node, found,
+ *rdatasetp, NULL);
+ }
+ rpz_clean(NULL, dbp, &node, NULL);
+ if (result == DNS_R_DELEGATION) {
+ /*
+ * Recurse to get NS rrset or A or AAAA rrset for an NS name.
+ */
+ rpz_clean(NULL, NULL, NULL, rdatasetp);
+ dns_name_copy(name, st->r_name, NULL);
+ result = query_recurse(client, type, st->r_name, NULL, NULL,
+ resuming);
+ if (result == ISC_R_SUCCESS) {
+ st->state |= DNS_RPZ_RECURSING;
+ result = DNS_R_DELEGATION;
+ }
+ }
+ return (result);
+}
+
+/*
+ * Check the IP address in an A or AAAA rdataset against
+ * the IP or NSIP response policy rules of a view.
+ */
+static isc_result_t
+rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
+ dns_rpz_type_t rpz_type)
+{
+ dns_rpz_st_t *st;
+ dns_dbversion_t *version;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ dns_rpz_zone_t *new_rpz;
+ 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 (new_rpz = ISC_LIST_HEAD(client->view->rpz_zones);
+ new_rpz != NULL;
+ new_rpz = ISC_LIST_NEXT(new_rpz, link)) {
+ version = NULL;
+
+ /*
+ * Find the database for this policy zone to get its
+ * radix tree.
+ */
+ result = rpz_getdb(client, rpz_type, &new_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.
+ */
+ result = dns_db_rpz_findips(new_rpz, rpz_type, zone, db,
+ version, rdataset, st);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ rpz_clean(&zone, &db, NULL, NULL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rpz_rewrite_nsip(ns_client_t *client, 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_ns_find(client, name, type, dbp, version, rdatasetp,
+ resuming);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ result = rpz_rewrite_ip(client, *rdatasetp, DNS_RPZ_TYPE_NSIP);
+ 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:
+ result = ISC_R_SUCCESS;
+ break;
+ case DNS_R_DELEGATION:
+ case DNS_R_DUPLICATE:
+ case DNS_R_DROP:
+ break;
+ default:
+ if (client->query.rpz_st->m.policy != DNS_RPZ_POLICY_ERROR) {
+ client->query.rpz_st->m.policy = DNS_RPZ_POLICY_ERROR;
+ rpz_fail_log(client, ISC_LOG_WARNING, DNS_RPZ_TYPE_NSIP,
+ name, "NS address rewrite nsip ", result);
+ }
+ break;
+ }
+ return (result);
+}
+
+/*
+ * Get the rrset from a response policy zone.
+ */
+static isc_result_t
+rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
+ dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep,
+ dns_db_t **dbp, dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
+ dns_rpz_policy_t *policyp)
+{
+ dns_dbversion_t *version;
+ dns_rpz_policy_t policy;
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ isc_result_t result;
+
+ 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
+ * request from the policy zone.
+ */
+ version = NULL;
+ result = rpz_getdb(client, rpz_type, qnamef, zonep, dbp, &version);
+ if (result != ISC_R_SUCCESS) {
+ *policyp = DNS_RPZ_POLICY_MISS;
+ return (DNS_R_NXDOMAIN);
+ }
+
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
+ result = dns_db_find(*dbp, qnamef, version, dns_rdatatype_any, 0,
+ client->now, nodep, found, *rdatasetp, NULL);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_t *rdsiter;
+
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(*dbp, *nodep, version, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(*dbp, nodep);
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
+ qnamef, "allrdatasets()", result);
+ *policyp = DNS_RPZ_POLICY_ERROR;
+ return (DNS_R_SERVFAIL);
+ }
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, *rdatasetp);
+ if ((*rdatasetp)->type == dns_rdatatype_cname ||
+ (*rdatasetp)->type == qtype)
+ break;
+ dns_rdataset_disassociate(*rdatasetp);
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ if (result != ISC_R_NOMORE) {
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL,
+ rpz_type, qnamef, "rdatasetiter",
+ result);
+ *policyp = DNS_RPZ_POLICY_ERROR;
+ return (DNS_R_SERVFAIL);
+ }
+ /*
+ * Ask again to get the right DNS_R_DNAME/NXRRSET/...
+ * result if there is neither a CNAME nor target type.
+ */
+ if (dns_rdataset_isassociated(*rdatasetp))
+ dns_rdataset_disassociate(*rdatasetp);
+ dns_db_detachnode(*dbp, nodep);
+
+ if (qtype == dns_rdatatype_rrsig ||
+ qtype == dns_rdatatype_sig)
+ result = DNS_R_NXRRSET;
+ else
+ result = dns_db_find(*dbp, qnamef, version,
+ qtype, 0, client->now,
+ nodep, found, *rdatasetp,
+ NULL);
+ }
+ }
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if ((*rdatasetp)->type != dns_rdatatype_cname) {
+ policy = DNS_RPZ_POLICY_RECORD;
+ } else {
+ policy = dns_rpz_decode_cname(*rdatasetp, sname);
+ if (policy == DNS_RPZ_POLICY_RECORD &&
+ qtype != dns_rdatatype_cname &&
+ qtype != dns_rdatatype_any)
+ result = DNS_R_CNAME;
+ }
+ break;
+ 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
+ * require complications to get the number of labels matched
+ * in the name or the found name itself to the main DNS_R_DNAME
+ * case in query_find(). So fall through to treat them as NODATA.
+ */
+ case DNS_R_NXRRSET:
+ policy = DNS_RPZ_POLICY_NODATA;
+ break;
+ 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.
+ */
+ dns_db_rpz_enabled(*dbp, client->query.rpz_st);
+ dns_db_detach(dbp);
+ dns_zone_detach(zonep);
+ policy = DNS_RPZ_POLICY_MISS;
+ break;
+ default:
+ dns_db_detach(dbp);
+ dns_zone_detach(zonep);
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL, rpz_type, qnamef,
+ "", result);
+ policy = DNS_RPZ_POLICY_ERROR;
+ result = DNS_R_SERVFAIL;
+ break;
+ }
+
+ *policyp = policy;
+ return (result);
+}
+
+/*
+ * Build and look for a QNAME or NSDNAME owner name in a response 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)
+{
+ 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_dbnode_t *node;
+ dns_rpz_policy_t policy;
+ unsigned int labels;
+ isc_result_t result;
+
+ st = client->query.rpz_st;
+ zone = NULL;
+ db = NULL;
+ node = NULL;
+
+ for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
+ rpz != NULL;
+ rpz = ISC_LIST_NEXT(rpz, link)) {
+ /*
+ * Construct the rule's owner name.
+ */
+ 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);
+ labels = dns_name_countlabels(prefix);
+ if (labels < 2) {
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL,
+ rpz_type, suffix,
+ "concatentate() ", result);
+ return (ISC_R_SUCCESS);
+ }
+ if (labels+1 == dns_name_countlabels(qname)) {
+ rpz_fail_log(client, DNS_RPZ_DEBUG_LEVEL1,
+ rpz_type, suffix,
+ "concatentate() ", result);
+ }
+ dns_name_split(prefix, labels - 1, NULL, prefix);
+ }
+
+ /*
+ * See if the qname rule (or RR) exists.
+ */
+ result = rpz_find(client, qtype, rpz_qname, qname, rpz_type,
+ &zone, &db, &node, rdatasetp, &policy);
+ switch (result) {
+ case DNS_R_NXDOMAIN:
+ case DNS_R_EMPTYNAME:
+ break;
+ case DNS_R_SERVFAIL:
+ rpz_clean(&zone, &db, &node, rdatasetp);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ return (DNS_R_SERVFAIL);
+ default:
+ /*
+ * when more than one name or address hits a rule,
+ * prefer the first set of names (qname or NS),
+ * the first policy zone, and the smallest name
+ */
+ if (st->m.type == rpz_type &&
+ rpz->num > st->m.rpz->num &&
+ 0 <= dns_name_compare(rpz_qname, st->qname))
+ continue;
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node,
+ &st->m.rdataset);
+ 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 (dns_rdataset_isassociated(*rdatasetp)) {
+ dns_rdataset_t *trdataset;
+
+ trdataset = st->m.rdataset;
+ st->m.rdataset = *rdatasetp;
+ *rdatasetp = trdataset;
+ st->m.ttl = st->m.rdataset->ttl;
+ } else {
+ st->m.ttl = DNS_RPZ_TTL_DEFAULT;
+ }
+ st->m.node = node;
+ node = NULL;
+ st->m.db = db;
+ db = NULL;
+ st->m.zone = zone;
+ zone = NULL;
+ }
+ }
+
+ rpz_clean(&zone, &db, &node, rdatasetp);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Look for response policy zone NSIP and NSDNAME rewriting.
+ */
+static isc_result_t
+rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype,
+ isc_boolean_t resuming)
+{
+ dns_rpz_st_t *st;
+ dns_db_t *ipdb;
+ dns_rdataset_t *rdataset;
+ dns_fixedname_t nsnamef;
+ dns_name_t *nsname;
+ dns_dbversion_t *version;
+ isc_result_t result;
+
+ ipdb = NULL;
+ rdataset = NULL;
+
+ st = client->query.rpz_st;
+ if (st == NULL) {
+ st = isc_mem_get(client->mctx, sizeof(*st));
+ if (st == NULL)
+ return (ISC_R_NOMEMORY);
+ st->state = 0;
+ memset(&st->m, 0, sizeof(st->m));
+ memset(&st->ns, 0, sizeof(st->ns));
+ memset(&st->q, 0, sizeof(st->q));
+ dns_fixedname_init(&st->_qnamef);
+ dns_fixedname_init(&st->_r_namef);
+ dns_fixedname_init(&st->_fnamef);
+ st->qname = dns_fixedname_name(&st->_qnamef);
+ st->r_name = dns_fixedname_name(&st->_r_namef);
+ st->fname = dns_fixedname_name(&st->_fnamef);
+ client->query.rpz_st = st;
+ }
+ if ((st->state & DNS_RPZ_DONE_QNAME) == 0) {
+ st->state = DNS_RPZ_DONE_QNAME;
+ st->m.type = DNS_RPZ_TYPE_BAD;
+ st->m.policy = DNS_RPZ_POLICY_MISS;
+
+ /*
+ * Check rules for the name if this it the first time,
+ * i.e. we've not been recursing.
+ */
+ result = DNS_R_SERVFAIL;
+ st->state &= ~(DNS_RPZ_HAVE_IP | DNS_RPZ_HAVE_NSIPv4 |
+ DNS_RPZ_HAVE_NSIPv6 | DNS_RPZ_HAD_NSDNAME);
+ result = rpz_rewrite_name(client, qtype, client->query.qname,
+ DNS_RPZ_TYPE_QNAME, &rdataset);
+ if (st->m.policy != DNS_RPZ_POLICY_MISS)
+ goto cleanup;
+ if ((st->state & (DNS_RPZ_HAVE_NSIPv4 | DNS_RPZ_HAVE_NSIPv6 |
+ DNS_RPZ_HAD_NSDNAME)) == 0)
+ goto cleanup;
+ st->ns.label = dns_name_countlabels(client->query.qname);
+ }
+
+ dns_fixedname_init(&nsnamef);
+ dns_name_clone(client->query.qname, dns_fixedname_name(&nsnamef));
+ while (st->ns.label > 1 && st->m.policy == DNS_RPZ_POLICY_MISS) {
+ if (st->ns.label == dns_name_countlabels(client->query.qname)) {
+ nsname = client->query.qname;
+ } else {
+ nsname = dns_fixedname_name(&nsnamef);
+ dns_name_split(client->query.qname, st->ns.label,
+ NULL, nsname);
+ }
+ if (st->ns.ns_rdataset == NULL ||
+ !dns_rdataset_isassociated(st->ns.ns_rdataset)) {
+ dns_db_t *db = NULL;
+ result = rpz_ns_find(client, nsname, dns_rdatatype_ns,
+ &db, NULL, &st->ns.ns_rdataset,
+ resuming);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_DELEGATION)
+ goto cleanup;
+ if (result == DNS_R_EMPTYNAME ||
+ result == DNS_R_NXRRSET ||
+ result == DNS_R_EMPTYWILD ||
+ result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_CNAME ||
+ result == DNS_R_DNAME) {
+ rpz_fail_log(client,
+ DNS_RPZ_DEBUG_LEVEL2,
+ DNS_RPZ_TYPE_NSIP, nsname,
+ "NS db_find() ", result);
+ dns_rdataset_disassociate(st->ns.
+ ns_rdataset);
+ st->ns.label--;
+ continue;
+ }
+ if (st->m.policy != DNS_RPZ_POLICY_ERROR) {
+ rpz_fail_log(client, DNS_RPZ_INFO_LEVEL,
+ DNS_RPZ_TYPE_NSIP, nsname,
+ "NS db_find() ", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ }
+ goto cleanup;
+ }
+ result = dns_rdataset_first(st->ns.ns_rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ /*
+ * Check all NS names.
+ */
+ do {
+ dns_rdata_ns_t ns;
+ dns_rdata_t nsrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(st->ns.ns_rdataset, &nsrdata);
+ result = dns_rdata_tostruct(&nsrdata, &ns, NULL);
+ dns_rdata_reset(&nsrdata);
+ if (result != ISC_R_SUCCESS) {
+ rpz_fail_log(client, DNS_RPZ_ERROR_LEVEL,
+ DNS_RPZ_TYPE_NSIP, nsname,
+ "rdata_tostruct() ", result);
+ st->m.policy = DNS_RPZ_POLICY_ERROR;
+ goto cleanup;
+ }
+ if ((st->state & DNS_RPZ_HAD_NSDNAME) != 0) {
+ result = rpz_rewrite_name(client, qtype,
+ &ns.name,
+ DNS_RPZ_TYPE_NSDNAME,
+ &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_freestruct(&ns);
+ goto cleanup;
+ }
+ }
+ /*
+ * Check all IP addresses for this NS name, but don't
+ * bother without NSIP rules or with a NSDNAME hit.
+ */
+ version = NULL;
+ if ((st->state & DNS_RPZ_HAVE_NSIPv4) != 0 &&
+ st->m.type != DNS_RPZ_TYPE_NSDNAME &&
+ (st->state & DNS_RPZ_DONE_A) == 0) {
+ result = rpz_rewrite_nsip(client,
+ dns_rdatatype_a,
+ &ns.name, &ipdb,
+ version, &rdataset,
+ resuming);
+ if (result == ISC_R_SUCCESS)
+ st->state |= DNS_RPZ_DONE_A;
+ }
+ if (result == ISC_R_SUCCESS &&
+ (st->state & DNS_RPZ_HAVE_NSIPv6) != 0 &&
+ st->m.type != DNS_RPZ_TYPE_NSDNAME) {
+ result = rpz_rewrite_nsip(client,
+ dns_rdatatype_aaaa,
+ &ns.name, &ipdb, version,
+ &rdataset, resuming);
+ }
+ dns_rdata_freestruct(&ns);
+ if (ipdb != NULL)
+ dns_db_detach(&ipdb);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ st->state &= ~DNS_RPZ_DONE_A;
+ result = dns_rdataset_next(st->ns.ns_rdataset);
+ } while (result == ISC_R_SUCCESS);
+ dns_rdataset_disassociate(st->ns.ns_rdataset);
+ st->ns.label--;
+ }
+
+ /*
+ * Use the best, if any, hit.
+ */
+ result = ISC_R_SUCCESS;
+
+cleanup:
+ if (st->m.policy != DNS_RPZ_POLICY_MISS &&
+ st->m.policy != DNS_RPZ_POLICY_NO_OP &&
+ st->m.policy != DNS_RPZ_POLICY_ERROR &&
+ st->m.rpz->policy != DNS_RPZ_POLICY_GIVEN)
+ st->m.policy = st->m.rpz->policy;
+ if (st->m.policy == DNS_RPZ_POLICY_NO_OP)
+ rpz_log(client);
+ if (st->m.policy == DNS_RPZ_POLICY_MISS ||
+ st->m.policy == DNS_RPZ_POLICY_NO_OP ||
+ st->m.policy == DNS_RPZ_POLICY_ERROR)
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ if (st->m.policy != DNS_RPZ_POLICY_MISS)
+ st->state |= DNS_RPZ_REWRITTEN;
+ if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
+ st->m.type = DNS_RPZ_TYPE_BAD;
+ result = DNS_R_SERVFAIL;
+ }
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if ((st->state & DNS_RPZ_RECURSING) == 0) {
+ rpz_clean(NULL, &st->ns.db, NULL, &st->ns.ns_rdataset);
+ }
+
+ return (result);
+}
+
#define MAX_RESTARTS 16
#define QUERY_ERROR(r) \
@@ -3698,6 +4848,99 @@ query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
return;
}
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+static isc_boolean_t
+is_v4_client(ns_client_t *client) {
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
+ return (ISC_TRUE);
+ if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+#endif
+
+static isc_uint32_t
+dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_soa_t soa;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ isc_uint32_t ttl = ISC_UINT32_MAX;
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ ttl = ISC_MIN(rdataset.ttl, soa.minimum);
+
+cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (ttl);
+}
+
+static isc_boolean_t
+dns64_aaaaok(ns_client_t *client, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ isc_netaddr_t netaddr;
+ dns_dns64_t *dns64 = ISC_LIST_HEAD(client->view->dns64);
+ unsigned int flags = 0;
+ unsigned int i, count;
+ isc_boolean_t *aaaaok;
+
+ INSIST(client->query.dns64_aaaaok == NULL);
+ INSIST(client->query.dns64_aaaaoklen == 0);
+ INSIST(client->query.dns64_aaaa == NULL);
+ INSIST(client->query.dns64_sigaaaa == NULL);
+
+ if (dns64 == NULL)
+ return (ISC_TRUE);
+
+ if (RECURSIONOK(client))
+ flags |= DNS_DNS64_RECURSIVE;
+
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ flags |= DNS_DNS64_DNSSEC;
+
+ count = dns_rdataset_count(rdataset);
+ aaaaok = isc_mem_get(client->mctx, sizeof(isc_boolean_t) * count);
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ if (dns_dns64_aaaaok(dns64, &netaddr, client->signer,
+ &ns_g_server->aclenv, flags, rdataset,
+ aaaaok, count)) {
+ for (i = 0; i < count; i++) {
+ if (aaaaok != NULL && !aaaaok[i]) {
+ client->query.dns64_aaaaok = aaaaok;
+ client->query.dns64_aaaaoklen = count;
+ break;
+ }
+ }
+ if (i == count)
+ isc_mem_put(client->mctx, aaaaok,
+ sizeof(isc_boolean_t) * count);
+ return (ISC_TRUE);
+ }
+ isc_mem_put(client->mctx, aaaaok, sizeof(isc_boolean_t) * count);
+ return (ISC_FALSE);
+}
+
/*
* Do the bulk of query processing for the current query of 'client'.
* If 'event' is non-NULL, we are returning from recursion and 'qtype'
@@ -3716,6 +4959,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdatasetiter_t *rdsiter;
isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
+ isc_boolean_t is_staticstub_zone;
unsigned int n, nlabels;
dns_namereln_t namereln;
int order;
@@ -3731,8 +4975,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
unsigned int options;
isc_boolean_t empty_wild;
dns_rdataset_t *noqname;
+ dns_rpz_st_t *rpz_st;
isc_boolean_t resuming;
int line = -1;
+ isc_boolean_t dns64_exclude, dns64;
CTRACE("query_find");
@@ -3758,28 +5004,67 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
zone = NULL;
need_wildcardproof = ISC_FALSE;
empty_wild = ISC_FALSE;
+ dns64_exclude = dns64 = ISC_FALSE;
options = 0;
resuming = ISC_FALSE;
is_zone = ISC_FALSE;
+ is_staticstub_zone = ISC_FALSE;
if (event != NULL) {
/*
* We're returning from recursion. Restore the query context
* and resume.
*/
-
want_restart = ISC_FALSE;
- authoritative = ISC_FALSE;
- qtype = event->qtype;
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
+ is_zone = rpz_st->q.is_zone;
+ authoritative = rpz_st->q.authoritative;
+ zone = rpz_st->q.zone;
+ rpz_st->q.zone = NULL;
+ node = rpz_st->q.node;
+ rpz_st->q.node = NULL;
+ db = rpz_st->q.db;
+ rpz_st->q.db = NULL;
+ rdataset = rpz_st->q.rdataset;
+ rpz_st->q.rdataset = NULL;
+ sigrdataset = rpz_st->q.sigrdataset;
+ rpz_st->q.sigrdataset = NULL;
+ qtype = rpz_st->q.qtype;
+
+ if (event->node != NULL)
+ dns_db_detachnode(db, &event->node);
+ rpz_st->ns.db = event->db;
+ rpz_st->ns.r_type = event->qtype;
+ rpz_st->ns.r_rdataset = event->rdataset;
+ if (event->sigrdataset != NULL &&
+ dns_rdataset_isassociated(event->sigrdataset))
+ dns_rdataset_disassociate(event->sigrdataset);
+ } else {
+ authoritative = ISC_FALSE;
+
+ qtype = event->qtype;
+ db = event->db;
+ node = event->node;
+ rdataset = event->rdataset;
+ sigrdataset = event->sigrdataset;
+ }
+
if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
type = dns_rdatatype_any;
else
type = qtype;
- db = event->db;
- node = event->node;
- rdataset = event->rdataset;
- sigrdataset = event->sigrdataset;
+
+ if (DNS64(client)) {
+ client->query.attributes &= ~NS_QUERYATTR_DNS64;
+ dns64 = ISC_TRUE;
+ }
+ if (DNS64EXCLUDE(client)) {
+ client->query.attributes &= ~NS_QUERYATTR_DNS64EXCLUDE;
+ dns64_exclude = ISC_TRUE;
+ }
/*
* We'll need some resources...
@@ -3794,16 +5079,26 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
- tname = dns_fixedname_name(&event->foundname);
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
+ tname = rpz_st->fname;
+ } else {
+ tname = dns_fixedname_name(&event->foundname);
+ }
result = dns_name_copy(tname, fname, NULL);
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
-
- result = event->result;
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_RECURSING) != 0) {
+ rpz_st->ns.r_result = event->result;
+ result = rpz_st->q.result;
+ isc_event_free(ISC_EVENT_PTR(&event));
+ } else {
+ result = event->result;
+ }
resuming = ISC_TRUE;
-
goto resume;
}
@@ -3902,8 +5197,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
goto cleanup;
}
- if (is_zone)
+ is_staticstub_zone = ISC_FALSE;
+ if (is_zone && zone != NULL) {
authoritative = ISC_TRUE;
+ if (dns_zone_gettype(zone) == dns_zone_staticstub)
+ is_staticstub_zone = ISC_TRUE;
+ }
if (event == NULL && client->query.restarts == 0) {
if (is_zone) {
@@ -3956,6 +5255,119 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
resume:
CTRACE("query_find: resume");
+
+ if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
+ RECURSIONOK(client) && !RECURSING(client) &&
+ result != DNS_R_DELEGATION && result != ISC_R_NOTFOUND &&
+ (client->query.rpz_st == NULL ||
+ (client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
+ !dns_name_equal(client->query.qname, dns_rootname)) {
+ isc_result_t rresult;
+
+ rresult = rpz_rewrite(client, qtype, resuming);
+ rpz_st = client->query.rpz_st;
+ switch (rresult) {
+ case ISC_R_SUCCESS:
+ break;
+ case DNS_R_DELEGATION:
+ /*
+ * recursing for NS names or addresses,
+ * so save the main query state
+ */
+ rpz_st->q.qtype = qtype;
+ rpz_st->q.is_zone = is_zone;
+ rpz_st->q.authoritative = authoritative;
+ rpz_st->q.zone = zone;
+ zone = NULL;
+ rpz_st->q.db = db;
+ db = NULL;
+ rpz_st->q.node = node;
+ node = NULL;
+ rpz_st->q.rdataset = rdataset;
+ rdataset = NULL;
+ rpz_st->q.sigrdataset = sigrdataset;
+ sigrdataset = NULL;
+ dns_name_copy(fname, rpz_st->fname, NULL);
+ rpz_st->q.result = result;
+ client->query.attributes |= NS_QUERYATTR_RECURSING;
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ default:
+ RECURSE_ERROR(rresult);
+ goto cleanup;
+ }
+ if (rpz_st->m.policy != DNS_RPZ_POLICY_MISS &&
+ rpz_st->m.policy != DNS_RPZ_POLICY_NO_OP) {
+ result = dns_name_copy(client->query.qname, fname,
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ finish_rewrite:
+ rpz_clean(&zone, &db, &node, NULL);
+ if (rpz_st->m.rdataset != NULL) {
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ rdataset = rpz_st->m.rdataset;
+ rpz_st->m.rdataset = NULL;
+ } else if (rdataset != NULL &&
+ dns_rdataset_isassociated(rdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ }
+ node = rpz_st->m.node;
+ rpz_st->m.node = NULL;
+ db = rpz_st->m.db;
+ rpz_st->m.db = NULL;
+ zone = rpz_st->m.zone;
+ rpz_st->m.zone = NULL;
+
+ result = rpz_st->m.result;
+ switch (rpz_st->m.policy) {
+ case DNS_RPZ_POLICY_NXDOMAIN:
+ result = DNS_R_NXDOMAIN;
+ break;
+ case DNS_RPZ_POLICY_NODATA:
+ result = DNS_R_NXRRSET;
+ break;
+ case DNS_RPZ_POLICY_RECORD:
+ if (type == dns_rdatatype_any &&
+ result != DNS_R_CNAME &&
+ dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ break;
+ case DNS_RPZ_POLICY_CNAME:
+ result = dns_name_copy(&rpz_st->m.rpz->cname,
+ fname, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ query_keepname(client, fname, dbuf);
+ result = query_add_cname(client,
+ client->query.qname,
+ fname,
+ dns_trust_authanswer,
+ rpz_st->m.ttl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_client_qnamereplace(client, fname);
+ fname = NULL;
+ client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ rpz_log(client);
+ want_restart = ISC_TRUE;
+ goto cleanup;
+ default:
+ INSIST(0);
+ }
+
+ /*
+ * Turn off DNSSEC because the results of a
+ * response policy zone cannot verify.
+ */
+ client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ is_zone = ISC_TRUE;
+ rpz_log(client);
+ }
+ }
+
switch (result) {
case ISC_R_SUCCESS:
/*
@@ -4008,11 +5420,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
*/
if (RECURSIONOK(client)) {
result = query_recurse(client, qtype,
+ client->query.qname,
NULL, NULL, resuming);
- if (result == ISC_R_SUCCESS)
+ if (result == ISC_R_SUCCESS) {
client->query.attributes |=
NS_QUERYATTR_RECURSING;
- else
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else
RECURSE_ERROR(result);
goto cleanup;
} else {
@@ -4143,12 +5562,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
} else {
if (zfname != NULL &&
- !dns_name_issubdomain(fname, zfname)) {
+ (!dns_name_issubdomain(fname, zfname) ||
+ (is_staticstub_zone &&
+ dns_name_equal(fname, zfname)))) {
/*
- * We've already got a delegation from
- * authoritative data, and it is better
- * than what we found in the cache. Use
- * it instead of the cache delegation.
+ * In the following cases use "authoritative"
+ * data instead of the cache delegation:
+ * 1. We've already got a delegation from
+ * authoritative data, and it is better
+ * than what we found in the cache.
+ * 2. The query name matches the origin name
+ * of a static-stub zone. This needs to be
+ * considered for the case where the NS of
+ * the static-stub zone and the cached NS
+ * are different. We still need to contact
+ * the nameservers configured in the
+ * static-stub zone.
*/
query_releasename(client, &fname);
fname = zfname;
@@ -4183,15 +5612,31 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
*/
if (dns_rdatatype_atparent(type))
result = query_recurse(client, qtype,
- NULL, NULL,
- resuming);
+ client->query.qname,
+ NULL, NULL, resuming);
+ else if (dns64)
+ result = query_recurse(client,
+ dns_rdatatype_a,
+ client->query.qname,
+ NULL, NULL, resuming);
else
result = query_recurse(client, qtype,
- fname, rdataset,
- resuming);
- if (result == ISC_R_SUCCESS)
+ client->query.qname,
+ fname, rdataset,
+ resuming);
+
+ if (result == ISC_R_SUCCESS) {
client->query.attributes |=
NS_QUERYATTR_RECURSING;
+ if (dns64)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64;
+ if (dns64_exclude)
+ client->query.attributes |=
+ NS_QUERYATTR_DNS64EXCLUDE;
+ } else if (result == DNS_R_DUPLICATE ||
+ result == DNS_R_DROP)
+ QUERY_ERROR(result);
else
RECURSE_ERROR(result);
} else {
@@ -4231,11 +5676,75 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
}
goto cleanup;
+
case DNS_R_EMPTYNAME:
- result = DNS_R_NXRRSET;
- /* FALLTHROUGH */
case DNS_R_NXRRSET:
+ nxrrset:
INSIST(is_zone);
+
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64)
+#else
+ if (dns64 && !dns64_exclude)
+#endif
+ {
+ /*
+ * Restore the answers from the previous AAAA lookup.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ rdataset = client->query.dns64_aaaa;
+ sigrdataset = client->query.dns64_sigaaaa;
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ dns_name_copy(client->query.qname, fname, NULL);
+ client->query.dns64_aaaa = NULL;
+ client->query.dns64_sigaaaa = NULL;
+ dns64 = ISC_FALSE;
+#ifdef dns64_bis_return_excluded_addresses
+ /*
+ * Resume the diverted processing of the AAAA response?
+ */
+ if (dns64_excluded)
+ break;
+#endif
+ } else if (result == DNS_R_NXRRSET &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ qtype == dns_rdatatype_aaaa)
+ {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+ INSIST(client->query.dns64_aaaa == NULL);
+ INSIST(client->query.dns64_sigaaaa == NULL);
+ client->query.dns64_aaaa = rdataset;
+ client->query.dns64_sigaaaa = sigrdataset;
+ client->query.dns64_ttl = dns64_ttl(db, version);
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ rdataset = NULL;
+ sigrdataset = NULL;
+ type = qtype = dns_rdatatype_a;
+ dns64 = ISC_TRUE;
+ goto db_find;
+ }
+
+ result = DNS_R_NXRRSET;
+
/*
* Look for a NSEC3 record if we don't have a NSEC record.
*/
@@ -4258,10 +5767,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* instead? If so add the nearest to the
* closest provable encloser.
*/
- if (found &&
- dns_rdataset_isassociated(rdataset) &&
- !dns_name_equal(qname, found))
- {
+ if (dns_rdataset_isassociated(rdataset) &&
+ !dns_name_equal(qname, found)) {
unsigned int count;
unsigned int skip;
@@ -4328,7 +5835,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Add SOA.
*/
- result = query_addsoa(client, db, version, ISC_FALSE,
+ result = query_addsoa(client, db, version, ISC_UINT32_MAX,
dns_rdataset_isassociated(rdataset));
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(result);
@@ -4377,10 +5884,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
zone != NULL &&
#endif
dns_zone_getzeronosoattl(zone))
- result = query_addsoa(client, db, version, ISC_TRUE,
+ result = query_addsoa(client, db, version, 0,
dns_rdataset_isassociated(rdataset));
else
- result = query_addsoa(client, db, version, ISC_FALSE,
+ result = query_addsoa(client, db, version,
+ ISC_UINT32_MAX,
dns_rdataset_isassociated(rdataset));
if (result != ISC_R_SUCCESS) {
QUERY_ERROR(result);
@@ -4411,6 +5919,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
+ ncache_nxrrset:
INSIST(!is_zone);
authoritative = ISC_FALSE;
/*
@@ -4426,6 +5935,74 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
client->message->rdclass == dns_rdataclass_in &&
dns_name_countlabels(fname) == 7)
warn_rfc1918(client, fname, rdataset);
+
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64)
+#else
+ if (dns64 && !dns64_exclude)
+#endif
+ {
+ /*
+ * Restore the answers from the previous AAAA lookup.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ rdataset = client->query.dns64_aaaa;
+ sigrdataset = client->query.dns64_sigaaaa;
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ dns_name_copy(client->query.qname, fname, NULL);
+ client->query.dns64_aaaa = NULL;
+ client->query.dns64_sigaaaa = NULL;
+ dns64 = ISC_FALSE;
+#ifdef dns64_bis_return_excluded_addresses
+ if (dns64_excluded)
+ break;
+#endif
+ } else if (result == DNS_R_NCACHENXRRSET &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ qtype == dns_rdatatype_aaaa)
+ {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+ INSIST(client->query.dns64_aaaa == NULL);
+ INSIST(client->query.dns64_sigaaaa == NULL);
+ client->query.dns64_aaaa = rdataset;
+ client->query.dns64_sigaaaa = sigrdataset;
+ /*
+ * If the ttl is zero we need to workout if we have just
+ * decremented to zero or if there was no negative cache
+ * ttl in the answer.
+ */
+ if (rdataset->ttl != 0)
+ client->query.dns64_ttl = rdataset->ttl;
+ else if (dns_rdataset_first(rdataset) == ISC_R_SUCCESS)
+ client->query.dns64_ttl = 0;
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ rdataset = NULL;
+ sigrdataset = NULL;
+ fname = NULL;
+ type = qtype = dns_rdatatype_a;
+ dns64 = ISC_TRUE;
+ goto db_find;
+ }
+
/*
* We don't call query_addrrset() because we don't need any
* of its extra features (and things would probably break!).
@@ -4562,11 +6139,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_message_puttempname(client->message, &tname);
goto cleanup;
}
- dns_name_init(tname, NULL);
dns_name_clone(&dname.dname, tname);
dns_rdata_freestruct(&dname);
/*
- * Construct the new qname.
+ * Construct the new qname consisting of
+ * <found name prefix>.<dname target>
*/
dns_fixedname_init(&fixed);
prefix = dns_fixedname_name(&fixed);
@@ -4583,8 +6160,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
goto cleanup;
}
result = dns_name_concatenate(prefix, tname, fname, NULL);
+ dns_message_puttempname(client->message, &tname);
if (result != ISC_R_SUCCESS) {
- dns_message_puttempname(client->message, &tname);
if (result == ISC_R_NOSPACE) {
/*
* RFC2672, section 4.1, subsection 3c says
@@ -4597,11 +6174,12 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
query_keepname(client, fname, dbuf);
/*
- * Synthesize a CNAME for this DNAME.
+ * Synthesize a CNAME consisting of
+ * <old qname> <dname ttl> CNAME <new qname>
+ * with <dname trust value>
*
- * We want to synthesize a CNAME since if we don't
- * then older software that doesn't understand DNAME
- * will not chain like it should.
+ * Synthesize a CNAME so old old clients that don't understand
+ * DNAME can chain.
*
* We do not try to synthesize a signature because we hope
* that security aware servers will understand DNAME. Also,
@@ -4609,12 +6187,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* on-the-fly is costly, and not really legitimate anyway
* since the synthesized CNAME is NOT in the zone.
*/
- dns_name_init(tname, NULL);
- (void)query_addcnamelike(client, client->query.qname, fname,
- trdataset, &tname,
- dns_rdatatype_cname);
- if (tname != NULL)
- dns_message_puttempname(client->message, &tname);
+ result = query_add_cname(client, client->query.qname, fname,
+ trdataset->trust, trdataset->ttl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
/*
* Switch to the new qname and restart.
*/
@@ -4641,6 +6217,28 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
if (type == dns_rdatatype_any) {
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ isc_boolean_t have_aaaa, have_a, have_sig, filter_aaaa;
+
+ /*
+ * The filter-aaaa-on-v4 option should
+ * suppress AAAAs for IPv4 clients if there is an A.
+ * If we are not authoritative, assume there is a A
+ * even in if it is not in our cache. This assumption could
+ * be wrong but it is a good bet.
+ */
+ have_aaaa = ISC_FALSE;
+ have_a = !authoritative;
+ have_sig = ISC_FALSE;
+ if (client->view->v4_aaaa != dns_v4_aaaa_ok &&
+ is_v4_client(client) &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->v4_aaaa_acl,
+ ISC_TRUE) == ISC_R_SUCCESS)
+ filter_aaaa = ISC_TRUE;
+ else
+ filter_aaaa = ISC_FALSE;
+#endif
/*
* XXXRTH Need to handle zonecuts with special case
* code.
@@ -4652,6 +6250,54 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
QUERY_ERROR(DNS_R_SERVFAIL);
goto cleanup;
}
+
+ /*
+ * Check all A and AAAA records in all response policy
+ * IP address zones
+ */
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 &&
+ (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 &&
+ RECURSIONOK(client) && !RECURSING(client) &&
+ (rpz_st->state & DNS_RPZ_HAVE_IP) != 0) {
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, rdataset);
+ if (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa)
+ result = rpz_rewrite_ip(client,
+ rdataset,
+ DNS_RPZ_TYPE_IP);
+ dns_rdataset_disassociate(rdataset);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ if (result != ISC_R_NOMORE) {
+ dns_rdatasetiter_destroy(&rdsiter);
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ switch (rpz_st->m.policy) {
+ case DNS_RPZ_POLICY_MISS:
+ break;
+ case DNS_RPZ_POLICY_NO_OP:
+ rpz_log(client);
+ rpz_st->state |= DNS_RPZ_REWRITTEN;
+ break;
+ case DNS_RPZ_POLICY_NXDOMAIN:
+ case DNS_RPZ_POLICY_NODATA:
+ case DNS_RPZ_POLICY_RECORD:
+ case DNS_RPZ_POLICY_CNAME:
+ dns_rdatasetiter_destroy(&rdsiter);
+ rpz_st->state |= DNS_RPZ_REWRITTEN;
+ goto finish_rewrite;
+ default:
+ INSIST(0);
+ }
+ }
+
/*
* Calling query_addrrset() with a non-NULL dbuf is going
* to either keep or release the name. We don't want it to
@@ -4668,6 +6314,18 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
result = dns_rdatasetiter_first(rdsiter);
while (result == ISC_R_SUCCESS) {
dns_rdatasetiter_current(rdsiter, rdataset);
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ /*
+ * Notice the presence of A and AAAAs so
+ * that AAAAs can be hidden from IPv4 clients.
+ */
+ if (filter_aaaa) {
+ if (rdataset->type == dns_rdatatype_aaaa)
+ have_aaaa = ISC_TRUE;
+ else if (rdataset->type == dns_rdatatype_a)
+ have_a = ISC_TRUE;
+ }
+#endif
if (is_zone && qtype == dns_rdatatype_any &&
!dns_db_issecure(db) &&
dns_rdatatype_isdnssec(rdataset->type)) {
@@ -4679,6 +6337,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdataset_disassociate(rdataset);
} else if ((qtype == dns_rdatatype_any ||
rdataset->type == qtype) && rdataset->type != 0) {
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ if (dns_rdatatype_isdnssec(rdataset->type))
+ have_sig = ISC_TRUE;
+#endif
if (NOQNAME(rdataset) && WANTDNSSEC(client))
noqname = rdataset;
else
@@ -4709,6 +6371,16 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
result = dns_rdatasetiter_next(rdsiter);
}
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ /*
+ * Filter AAAAs if there is an A and there is no signature
+ * or we are supposed to break DNSSEC.
+ */
+ if (filter_aaaa && have_aaaa && have_a &&
+ (!have_sig || !WANTDNSSEC(client) ||
+ client->view->v4_aaaa == dns_v4_aaaa_break_dnssec))
+ client->attributes |= NS_CLIENTATTR_FILTER_AAAA;
+#endif
if (fname != NULL)
dns_message_puttempname(client->message, &fname);
@@ -4742,10 +6414,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdatasetiter_destroy(&rdsiter);
if (RECURSIONOK(client)) {
result = query_recurse(client,
- qtype,
- NULL,
- NULL,
- resuming);
+ qtype,
+ client->query.qname,
+ NULL, NULL,
+ resuming);
if (result == ISC_R_SUCCESS)
client->query.attributes |=
NS_QUERYATTR_RECURSING;
@@ -4763,7 +6435,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* Add SOA.
*/
result = query_addsoa(client, db, version,
- ISC_FALSE, ISC_FALSE);
+ ISC_UINT32_MAX,
+ ISC_FALSE);
if (result == ISC_R_SUCCESS)
result = ISC_R_NOMORE;
} else {
@@ -4783,6 +6456,162 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* This is the "normal" case -- an ordinary question to which
* we know the answer.
*/
+
+ /*
+ * Check all A and AAAA records in all response policy
+ * IP address zones
+ */
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL &&
+ (rpz_st->state & DNS_RPZ_DONE_QNAME) != 0 &&
+ (rpz_st->state & DNS_RPZ_REWRITTEN) == 0 &&
+ RECURSIONOK(client) && !RECURSING(client) &&
+ (rpz_st->state & DNS_RPZ_HAVE_IP) != 0 &&
+ (qtype == dns_rdatatype_aaaa || qtype == dns_rdatatype_a)) {
+ result = rpz_rewrite_ip(client, rdataset,
+ DNS_RPZ_TYPE_IP);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ /*
+ * After a hit in the radix tree for the policy domain,
+ * either stop trying to rewrite (DNS_RPZ_POLICY_NO_OP)
+ * or restart to ask the ordinary database of the
+ * policy zone for the DNS record corresponding to the
+ * record in the radix tree.
+ */
+ switch (rpz_st->m.policy) {
+ case DNS_RPZ_POLICY_MISS:
+ break;
+ case DNS_RPZ_POLICY_NO_OP:
+ rpz_log(client);
+ rpz_st->state |= DNS_RPZ_REWRITTEN;
+ break;
+ case DNS_RPZ_POLICY_NXDOMAIN:
+ case DNS_RPZ_POLICY_NODATA:
+ case DNS_RPZ_POLICY_RECORD:
+ case DNS_RPZ_POLICY_CNAME:
+ rpz_st->state |= DNS_RPZ_REWRITTEN;
+ goto finish_rewrite;
+ default:
+ INSIST(0);
+ }
+ }
+
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ /*
+ * Optionally hide AAAAs from IPv4 clients if there is an A.
+ * We add the AAAAs now, but might refuse to render them later
+ * after DNSSEC is figured out.
+ * This could be more efficient, but the whole idea is
+ * so fundamentally wrong, unavoidably inaccurate, and
+ * unneeded that it is best to keep it as short as possible.
+ */
+ if (client->view->v4_aaaa != dns_v4_aaaa_ok &&
+ is_v4_client(client) &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->v4_aaaa_acl,
+ ISC_TRUE) == ISC_R_SUCCESS &&
+ (!WANTDNSSEC(client) ||
+ sigrdataset == NULL ||
+ !dns_rdataset_isassociated(sigrdataset) ||
+ client->view->v4_aaaa == dns_v4_aaaa_break_dnssec)) {
+ if (qtype == dns_rdatatype_aaaa) {
+ trdataset = query_newrdataset(client);
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_a, 0,
+ client->now,
+ trdataset, NULL);
+ if (dns_rdataset_isassociated(trdataset))
+ dns_rdataset_disassociate(trdataset);
+ query_putrdataset(client, &trdataset);
+
+ /*
+ * We have an AAAA but the A is not in our cache.
+ * Assume any result other than DNS_R_DELEGATION
+ * or ISC_R_NOTFOUND means there is no A and
+ * so AAAAs are ok.
+ * Assume there is no A if we can't recurse
+ * for this client, although that could be
+ * the wrong answer. What else can we do?
+ * Besides, that we have the AAAA and are using
+ * this mechanism suggests that we care more
+ * about As than AAAAs and would have cached
+ * the A if it existed.
+ */
+ if (result == ISC_R_SUCCESS) {
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA;
+
+ } else if (authoritative ||
+ !RECURSIONOK(client) ||
+ (result != DNS_R_DELEGATION &&
+ result != ISC_R_NOTFOUND)) {
+ client->attributes &=
+ ~NS_CLIENTATTR_FILTER_AAAA;
+ } else {
+ /*
+ * This is an ugly kludge to recurse
+ * for the A and discard the result.
+ *
+ * Continue to add the AAAA now.
+ * We'll make a note to not render it
+ * if the recursion for the A succeeds.
+ */
+ result = query_recurse(client,
+ dns_rdatatype_a,
+ client->query.qname,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS) {
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA_RC;
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ }
+ }
+
+ } else if (qtype == dns_rdatatype_a &&
+ (client->attributes &
+ NS_CLIENTATTR_FILTER_AAAA_RC) != 0) {
+ client->attributes &=
+ ~NS_CLIENTATTR_FILTER_AAAA_RC;
+ client->attributes |=
+ NS_CLIENTATTR_FILTER_AAAA;
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ goto cleanup;
+ }
+ }
+#endif
+ /*
+ * Check to see if the AAAA RRset has non-excluded addresses
+ * in it. If not look for a A RRset.
+ */
+ INSIST(client->query.dns64_aaaaok == NULL);
+
+ if (qtype == dns_rdatatype_aaaa && !dns64_exclude &&
+ !ISC_LIST_EMPTY(client->view->dns64) &&
+ client->message->rdclass == dns_rdataclass_in &&
+ !dns64_aaaaok(client, rdataset, sigrdataset)) {
+ /*
+ * Look to see if there are A records for this
+ * name.
+ */
+ client->query.dns64_aaaa = rdataset;
+ client->query.dns64_sigaaaa = sigrdataset;
+ client->query.dns64_ttl = rdataset->ttl;
+ query_releasename(client, &fname);
+ dns_db_detachnode(db, &node);
+ rdataset = NULL;
+ sigrdataset = NULL;
+ type = qtype = dns_rdatatype_a;
+ dns64_exclude = dns64 = ISC_TRUE;
+ goto db_find;
+ }
+
if (sigrdataset != NULL)
sigrdatasetp = &sigrdataset;
else
@@ -4798,8 +6627,43 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_name_equal(client->query.qname, dns_rootname))
client->query.attributes &= ~NS_QUERYATTR_NOADDITIONAL;
- query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
- DNS_SECTION_ANSWER);
+ if (dns64) {
+ qtype = type = dns_rdatatype_aaaa;
+ result = query_dns64(client, &fname, rdataset,
+ sigrdataset, dbuf,
+ DNS_SECTION_ANSWER);
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, &rdataset);
+ if (result == ISC_R_NOMORE) {
+#ifndef dns64_bis_return_excluded_addresses
+ if (dns64_exclude) {
+ if (!is_zone)
+ goto cleanup;
+ /*
+ * Add a fake SOA record.
+ */
+ result = query_addsoa(client, db,
+ version, 600,
+ ISC_FALSE);
+ goto cleanup;
+ }
+#endif
+ if (is_zone)
+ goto nxrrset;
+ else
+ goto ncache_nxrrset;
+ } else if (result != ISC_R_SUCCESS) {
+ eresult = result;
+ goto cleanup;
+ }
+ } else if (client->query.dns64_aaaaok != NULL) {
+ query_filter64(client, &fname, rdataset, dbuf,
+ DNS_SECTION_ANSWER);
+ query_putrdataset(client, &rdataset);
+ } else
+ query_addrrset(client, &fname, &rdataset,
+ sigrdatasetp, dbuf, DNS_SECTION_ANSWER);
+
if (noqname != NULL)
query_addnoqnameproof(client, noqname);
/*
@@ -4842,6 +6706,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* General cleanup.
*/
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0)
+ rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node,
+ &rpz_st->m.rdataset);
if (rdataset != NULL)
query_putrdataset(client, &rdataset);
if (sigrdataset != NULL)
@@ -4949,6 +6817,7 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
char namebuf[DNS_NAME_FORMATSIZE];
char typename[DNS_RDATATYPE_FORMATSIZE];
char classname[DNS_RDATACLASS_FORMATSIZE];
+ char onbuf[ISC_NETADDR_FORMATSIZE];
dns_rdataset_t *rdataset;
int level = ISC_LOG_INFO;
@@ -4960,14 +6829,18 @@ log_query(ns_client_t *client, unsigned int flags, unsigned int extflags) {
dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
dns_rdataclass_format(rdataset->rdclass, classname, sizeof(classname));
dns_rdatatype_format(rdataset->type, typename, sizeof(typename));
+ isc_netaddr_format(&client->destaddr, onbuf, sizeof(onbuf));
ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
- level, "query: %s %s %s %s%s%s%s%s", namebuf, classname,
- typename, WANTRECURSION(client) ? "+" : "-",
+ level, "query: %s %s %s %s%s%s%s%s%s (%s)", namebuf,
+ classname, typename, WANTRECURSION(client) ? "+" : "-",
(client->signer != NULL) ? "S": "",
(client->opt != NULL) ? "E" : "",
+ ((client->attributes & NS_CLIENTATTR_TCP) != 0) ?
+ "T" : "",
((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
- ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "");
+ ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
+ onbuf);
}
static inline void
diff --git a/contrib/bind9/bin/named/server.c b/contrib/bind9/bin/named/server.c
index bc7fc17c3296..5bbf94b9b604 100644
--- a/contrib/bind9/bin/named/server.c
+++ b/contrib/bind9/bin/named/server.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: server.c,v 1.520.12.21 2011-01-14 23:45:49 tbox Exp $ */
+/* $Id: server.c,v 1.599.8.4 2011-02-16 19:46:12 each Exp $ */
/*! \file */
@@ -23,6 +23,10 @@
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <isc/app.h>
#include <isc/base64.h>
@@ -36,7 +40,9 @@
#include <isc/portset.h>
#include <isc/print.h>
#include <isc/resource.h>
+#include <isc/sha2.h>
#include <isc/socket.h>
+#include <isc/stat.h>
#include <isc/stats.h>
#include <isc/stdio.h>
#include <isc/string.h>
@@ -57,9 +63,11 @@
#ifdef DLZ
#include <dns/dlz.h>
#endif
+#include <dns/dns64.h>
#include <dns/forward.h>
#include <dns/journal.h>
#include <dns/keytable.h>
+#include <dns/keyvalues.h>
#include <dns/lib.h>
#include <dns/master.h>
#include <dns/masterdump.h>
@@ -102,6 +110,10 @@
#include <stdlib.h>
#endif
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
/*%
* Check an operation for failure. Assumes that the function
* using it has a 'result' variable and a 'cleanup' label.
@@ -143,6 +155,14 @@
fatal(msg, result); \
} while (0) \
+/*%
+ * Maximum ADB size for views that share a cache. Use this limit to suppress
+ * the total of memory footprint, which should be the main reason for sharing
+ * a cache. Only effective when a finite max-cache-size is specified.
+ * This is currently defined to be 8MB.
+ */
+#define MAX_ADB_SIZE_FOR_CACHESHARE 8388608
+
struct ns_dispatch {
isc_sockaddr_t addr;
unsigned int dispatchgen;
@@ -150,6 +170,14 @@ struct ns_dispatch {
ISC_LINK(struct ns_dispatch) link;
};
+struct ns_cache {
+ dns_cache_t *cache;
+ dns_view_t *primaryview;
+ isc_boolean_t needflush;
+ isc_boolean_t adbsizeadjusted;
+ ISC_LINK(ns_cache_t) link;
+};
+
struct dumpcontext {
isc_mem_t *mctx;
isc_boolean_t dumpcache;
@@ -176,6 +204,17 @@ struct zonelistentry {
ISC_LINK(struct zonelistentry) link;
};
+/*%
+ * Configuration context to retain for each view that allows
+ * new zones to be added at runtime
+ */
+struct cfg_context {
+ isc_mem_t * mctx;
+ cfg_obj_t * config;
+ cfg_parser_t * parser;
+ cfg_aclconfctx_t actx;
+};
+
/*
* These zones should not leak onto the Internet.
*/
@@ -230,8 +269,8 @@ static const struct {
{ NULL, ISC_FALSE }
};
-static void
-fatal(const char *msg, isc_result_t result);
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
static void
ns_server_reload(isc_task_t *task, isc_event_t *event);
@@ -256,19 +295,25 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view,
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);
+ cfg_aclconfctx_t *aclconf, isc_boolean_t added);
+
+static isc_result_t
+add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
static void
end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
+static void
+cfgctx_destroy(void **cfgp);
+
/*%
* Configure a single view ACL at '*aclp'. Get its configuration from
* 'vconfig' (for per-view configuration) and maybe from 'config'
*/
static isc_result_t
configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
- const char *aclname, cfg_aclconfctx_t *actx,
- isc_mem_t *mctx, dns_acl_t **aclp)
+ const char *aclname, const char *acltuplename,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
{
isc_result_t result;
const cfg_obj_t *maps[3];
@@ -294,13 +339,21 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
*/
return (ISC_R_SUCCESS);
+ if (acltuplename != NULL) {
+ /*
+ * If the ACL is given in an optional tuple, retrieve it.
+ * The parser should have ensured that a valid object be
+ * returned.
+ */
+ aclobj = cfg_tuple_get(aclobj, acltuplename);
+ }
+
result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
actx, mctx, 0, aclp);
return (result);
}
-
/*%
* Configure a sortlist at '*aclp'. Essentially the same as
* configure_view_acl() except it calls cfg_acl_fromconfig with a
@@ -345,8 +398,88 @@ configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
}
static isc_result_t
-configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
- dns_keytable_t *keytable, isc_mem_t *mctx)
+configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ const char *confname, const char *conftuplename,
+ isc_mem_t *mctx, dns_rbt_t **rbtp)
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *obj = NULL;
+ const cfg_listelt_t *element;
+ int i = 0;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+ const char *str;
+ const cfg_obj_t *nameobj;
+
+ if (*rbtp != NULL)
+ dns_rbt_destroy(rbtp);
+ if (vconfig != NULL)
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ if (config != NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ maps[i++] = options;
+ }
+ maps[i] = NULL;
+
+ (void)ns_config_get(maps, confname, &obj);
+ if (obj == NULL)
+ /*
+ * No value available. *rbtp == NULL.
+ */
+ return (ISC_R_SUCCESS);
+
+ if (conftuplename != NULL) {
+ obj = cfg_tuple_get(obj, conftuplename);
+ if (cfg_obj_isvoid(obj))
+ return (ISC_R_SUCCESS);
+ }
+
+ result = dns_rbt_create(mctx, NULL, NULL, rbtp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ nameobj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(nameobj);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ /*
+ * We don't need the node data, but need to set dummy data to
+ * avoid a partial match with an empty node. For example, if
+ * we have foo.example.com and bar.example.com, we'd get a match
+ * for baz.example.com, which is not the expected result.
+ * We simply use (void *)1 as the dummy data.
+ */
+ result = dns_rbt_addname(*rbtp, name, (void *)1);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR,
+ "failed to add %s for %s: %s",
+ str, confname, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ }
+
+ return (result);
+
+ cleanup:
+ dns_rbt_destroy(rbtp);
+ return (result);
+
+}
+
+static isc_result_t
+dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
+ isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
{
dns_rdataclass_t viewclass;
dns_rdata_dnskey_t keystruct;
@@ -363,12 +496,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
isc_result_t result;
dst_key_t *dstkey = NULL;
+ INSIST(target != NULL && *target == NULL);
+
flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
keyname = dns_fixedname_name(&fkeyname);
keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+ if (managed) {
+ const char *initmethod;
+ initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
+
+ if (strcasecmp(initmethod, "initial-key") != 0) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "managed key '%s': "
+ "invalid initialization method '%s'",
+ keynamestr, initmethod);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ }
+
if (vconfig == NULL)
viewclass = dns_rdataclass_in;
else {
@@ -408,7 +557,8 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
keystruct.algorithm == DST_ALG_RSAMD5) &&
r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
- "trusted key '%s' has a weak exponent",
+ "%s key '%s' has a weak exponent",
+ managed ? "managed" : "trusted",
keynamestr);
CHECK(dns_rdata_fromstruct(NULL,
@@ -418,25 +568,28 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
dns_fixedname_init(&fkeyname);
isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
isc_buffer_add(&namebuf, strlen(keynamestr));
- CHECK(dns_name_fromtext(keyname, &namebuf,
- dns_rootname, ISC_FALSE,
- NULL));
+ CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
mctx, &dstkey));
- CHECK(dns_keytable_add(keytable, &dstkey));
- INSIST(dstkey == NULL);
+ *target = dstkey;
return (ISC_R_SUCCESS);
cleanup:
if (result == DST_R_NOCRYPTO) {
cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
- "ignoring trusted key for '%s': no crypto support",
+ "ignoring %s key for '%s': no crypto support",
+ managed ? "managed" : "trusted",
keynamestr);
- result = ISC_R_SUCCESS;
+ } else if (result == DST_R_UNSUPPORTEDALG) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "skipping %s key for '%s': %s",
+ managed ? "managed" : "trusted",
+ keynamestr, isc_result_totext(result));
} else {
cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
- "configuring trusted key for '%s': %s",
+ "configuring %s key for '%s': %s",
+ managed ? "managed" : "trusted",
keynamestr, isc_result_totext(result));
result = ISC_R_FAILURE;
}
@@ -447,63 +600,215 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key,
return (result);
}
+static isc_result_t
+load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
+ dns_view_t *view, isc_boolean_t managed,
+ dns_name_t *keyname, isc_mem_t *mctx)
+{
+ const cfg_listelt_t *elt, *elt2;
+ const cfg_obj_t *key, *keylist;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ dns_keytable_t *secroots = NULL;
+
+ CHECK(dns_view_getsecroots(view, &secroots));
+
+ for (elt = cfg_list_first(keys);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ keylist = cfg_listelt_value(elt);
+
+ for (elt2 = cfg_list_first(keylist);
+ elt2 != NULL;
+ elt2 = cfg_list_next(elt2)) {
+ key = cfg_listelt_value(elt2);
+ result = dstkey_fromconfig(vconfig, key, managed,
+ &dstkey, mctx);
+ if (result == DST_R_UNSUPPORTEDALG) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * If keyname was specified, we only add that key.
+ */
+ if (keyname != NULL &&
+ !dns_name_equal(keyname, dst_key_name(dstkey)))
+ {
+ dst_key_free(&dstkey);
+ continue;
+ }
+
+ CHECK(dns_keytable_add(secroots, managed, &dstkey));
+ }
+ }
+
+ cleanup:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+ if (result == DST_R_NOCRYPTO)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
/*%
- * Configure DNSSEC keys for a view. Currently used only for
- * the security roots.
+ * Configure DNSSEC keys for a view.
*
* The per-view configuration values and the server-global defaults are read
- * from 'vconfig' and 'config'. The variable to be configured is '*target'.
+ * from 'vconfig' and 'config'.
*/
static isc_result_t
-configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config,
- isc_mem_t *mctx, dns_keytable_t **target)
+configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
+ const cfg_obj_t *config, const cfg_obj_t *bindkeys,
+ isc_boolean_t auto_dlv, isc_boolean_t auto_root,
+ isc_mem_t *mctx)
{
- isc_result_t result;
- const cfg_obj_t *keys = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *view_keys = NULL;
+ const cfg_obj_t *global_keys = NULL;
+ const cfg_obj_t *view_managed_keys = NULL;
+ const cfg_obj_t *global_managed_keys = NULL;
+ const cfg_obj_t *maps[4];
const cfg_obj_t *voptions = NULL;
- const cfg_listelt_t *element, *element2;
- const cfg_obj_t *keylist;
- const cfg_obj_t *key;
- dns_keytable_t *keytable = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *obj = NULL;
+ const char *directory;
+ int i = 0;
- CHECK(dns_keytable_create(mctx, &keytable));
+ /* We don't need trust anchors for the _bind view */
+ if (strcmp(view->name, "_bind") == 0 &&
+ view->rdclass == dns_rdataclass_chaos) {
+ return (ISC_R_SUCCESS);
+ }
- if (vconfig != NULL)
+ if (vconfig != NULL) {
voptions = cfg_tuple_get(vconfig, "options");
+ if (voptions != NULL) {
+ (void) cfg_map_get(voptions, "trusted-keys",
+ &view_keys);
+ (void) cfg_map_get(voptions, "managed-keys",
+ &view_managed_keys);
+ maps[i++] = voptions;
+ }
+ }
- keys = NULL;
- if (voptions != NULL)
- (void)cfg_map_get(voptions, "trusted-keys", &keys);
- if (keys == NULL)
- (void)cfg_map_get(config, "trusted-keys", &keys);
+ if (config != NULL) {
+ (void)cfg_map_get(config, "trusted-keys", &global_keys);
+ (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL) {
+ maps[i++] = options;
+ }
+ }
- for (element = cfg_list_first(keys);
- element != NULL;
- element = cfg_list_next(element))
- {
- keylist = cfg_listelt_value(element);
- for (element2 = cfg_list_first(keylist);
- element2 != NULL;
- element2 = cfg_list_next(element2))
- {
- key = cfg_listelt_value(element2);
- CHECK(configure_view_dnsseckey(vconfig, key,
- keytable, mctx));
+ maps[i++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = dns_view_initsecroots(view, mctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "couldn't create keytable");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ if (auto_dlv && view->rdclass == dns_rdataclass_in) {
+ const cfg_obj_t *builtin_keys = NULL;
+ const cfg_obj_t *builtin_managed_keys = NULL;
+
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "using built-in DLV key for view %s",
+ view->name);
+
+ /*
+ * If bind.keys exists, it overrides the managed-keys
+ * clause hard-coded in ns_g_config.
+ */
+ if (bindkeys != NULL) {
+ (void)cfg_map_get(bindkeys, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(bindkeys, "managed-keys",
+ &builtin_managed_keys);
+ } else {
+ (void)cfg_map_get(ns_g_config, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(ns_g_config, "managed-keys",
+ &builtin_managed_keys);
}
+
+ if (builtin_keys != NULL)
+ CHECK(load_view_keys(builtin_keys, vconfig, view,
+ ISC_FALSE, view->dlv, mctx));
+ if (builtin_managed_keys != NULL)
+ CHECK(load_view_keys(builtin_managed_keys, vconfig,
+ view, ISC_TRUE, view->dlv, mctx));
}
- dns_keytable_detach(target);
- *target = keytable; /* Transfer ownership. */
- keytable = NULL;
- result = ISC_R_SUCCESS;
+ if (auto_root && view->rdclass == dns_rdataclass_in) {
+ const cfg_obj_t *builtin_keys = NULL;
+ const cfg_obj_t *builtin_managed_keys = NULL;
- cleanup:
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "using built-in root key for view %s",
+ view->name);
+
+ /*
+ * If bind.keys exists, it overrides the managed-keys
+ * clause hard-coded in ns_g_config.
+ */
+ if (bindkeys != NULL) {
+ (void)cfg_map_get(bindkeys, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(bindkeys, "managed-keys",
+ &builtin_managed_keys);
+ } else {
+ (void)cfg_map_get(ns_g_config, "trusted-keys",
+ &builtin_keys);
+ (void)cfg_map_get(ns_g_config, "managed-keys",
+ &builtin_managed_keys);
+ }
+
+ if (builtin_keys != NULL)
+ CHECK(load_view_keys(builtin_keys, vconfig, view,
+ ISC_FALSE, dns_rootname, mctx));
+ if (builtin_managed_keys != NULL)
+ CHECK(load_view_keys(builtin_managed_keys, vconfig,
+ view, ISC_TRUE, dns_rootname,
+ mctx));
+ }
+
+ CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE,
+ NULL, mctx));
+ CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE,
+ NULL, mctx));
+
+ if (view->rdclass == dns_rdataclass_in) {
+ CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE,
+ NULL, mctx));
+ CHECK(load_view_keys(global_managed_keys, vconfig, view,
+ ISC_TRUE, NULL, mctx));
+ }
+
+ /*
+ * Add key zone for managed-keys.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "managed-keys-directory", &obj);
+ directory = obj != NULL ? cfg_obj_asstring(obj) : NULL;
+ CHECK(add_keydata_zone(view, directory, ns_g_mctx));
+
+ cleanup:
return (result);
}
static isc_result_t
-mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
-{
+mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
const cfg_listelt_t *element;
const cfg_obj_t *obj;
const char *str;
@@ -523,8 +828,7 @@ mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
- CHECK(dns_name_fromtext(name, &b, dns_rootname,
- ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
CHECK(dns_resolver_setmustbesecure(resolver, name, value));
}
@@ -684,7 +988,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) {
isc_buffer_add(&b, strlen(str));
dns_fixedname_init(&fixed);
result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
@@ -868,7 +1172,7 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
- CHECK(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
algorithms = cfg_tuple_get(disabled, "algorithms");
for (element = cfg_list_first(algorithms);
@@ -921,7 +1225,7 @@ on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
result = dns_name_fromtext(name, &b, dns_rootname,
- ISC_TRUE, NULL);
+ 0, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (dns_name_equal(name, zonename))
return (ISC_TRUE);
@@ -979,6 +1283,20 @@ setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
return (ISC_R_SUCCESS);
}
+static ns_cache_t *
+cachelist_find(ns_cachelist_t *cachelist, const char *cachename) {
+ ns_cache_t *nsc;
+
+ for (nsc = ISC_LIST_HEAD(*cachelist);
+ nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link)) {
+ if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0)
+ return (nsc);
+ }
+
+ return (NULL);
+}
+
static isc_boolean_t
cache_reusable(dns_view_t *originview, dns_view_t *view,
isc_boolean_t new_zero_no_soattl)
@@ -996,6 +1314,238 @@ cache_reusable(dns_view_t *originview, dns_view_t *view,
return (ISC_TRUE);
}
+static isc_boolean_t
+cache_sharable(dns_view_t *originview, dns_view_t *view,
+ isc_boolean_t new_zero_no_soattl,
+ unsigned int new_cleaning_interval,
+ isc_uint32_t new_max_cache_size)
+{
+ /*
+ * If the cache cannot even reused for the same view, it cannot be
+ * shared with other views.
+ */
+ if (!cache_reusable(originview, view, new_zero_no_soattl))
+ return (ISC_FALSE);
+
+ /*
+ * Check other cache related parameters that must be consistent among
+ * the sharing views.
+ */
+ if (dns_cache_getcleaninginterval(originview->cache) !=
+ new_cleaning_interval ||
+ dns_cache_getcachesize(originview->cache) != new_max_cache_size) {
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
+
+#ifdef DLZ
+/*
+ * Callback from DLZ configure when the driver sets up a writeable zone
+ */
+static isc_result_t
+dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) {
+ dns_name_t *origin = dns_zone_getorigin(zone);
+ dns_rdataclass_t zclass = view->rdclass;
+ isc_result_t result;
+
+ result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone);
+ if (result != ISC_R_SUCCESS)
+ return result;
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+
+ return ns_zone_configure_writeable_dlz(view->dlzdatabase,
+ zone, zclass, origin);
+}
+#endif
+
+static isc_result_t
+dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
+ unsigned int prefixlen, const char *server,
+ const char *contact)
+{
+ char *cp;
+ char reverse[48+sizeof("ip6.arpa.")];
+ const char *dns64_dbtype[4] = { "_builtin", "dns64", ".", "." };
+ const char *sep = ": view ";
+ const char *viewname = view->name;
+ const unsigned char *s6;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_zone_t *zone = NULL;
+ int dns64_dbtypec = 4;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
+ prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
+
+ if (!strcmp(viewname, "_default")) {
+ sep = "";
+ viewname = "";
+ }
+
+ /*
+ * Construct the reverse name of the zone.
+ */
+ cp = reverse;
+ s6 = na->type.in6.s6_addr;
+ while (prefixlen > 0) {
+ prefixlen -= 8;
+ sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf,
+ (s6[prefixlen/8] >> 4) & 0xf);
+ cp += 4;
+ }
+ strcat(cp, "ip6.arpa.");
+
+ /*
+ * Create the actual zone.
+ */
+ if (server != NULL)
+ dns64_dbtype[2] = server;
+ if (contact != NULL)
+ dns64_dbtype[3] = contact;
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ isc_buffer_init(&b, reverse, strlen(reverse));
+ isc_buffer_add(&b, strlen(reverse));
+ CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ CHECK(dns_zone_create(&zone, mctx));
+ CHECK(dns_zone_setorigin(zone, name));
+ dns_zone_setview(zone, view);
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+ dns_zone_setclass(zone, view->rdclass);
+ dns_zone_settype(zone, dns_zone_master);
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype));
+ if (view->queryacl != NULL)
+ dns_zone_setqueryacl(zone, view->queryacl);
+ if (view->queryonacl != NULL)
+ dns_zone_setqueryonacl(zone, view->queryonacl);
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
+ CHECK(setquerystats(zone, mctx, ISC_FALSE)); /* XXXMPA */
+ CHECK(dns_view_addzone(view, zone));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep,
+ viewname, reverse);
+
+cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+static isc_result_t
+configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
+ const cfg_obj_t *rpz_obj, *policy_obj;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *origin;
+ dns_rpz_zone_t *old, *new;
+ dns_zone_t *zone = NULL;
+ isc_result_t result;
+ unsigned int l1, l2;
+
+ new = isc_mem_get(view->mctx, sizeof(*new));
+ if (new == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ memset(new, 0, sizeof(*new));
+ dns_name_init(&new->nsdname, NULL);
+ dns_name_init(&new->origin, NULL);
+ dns_name_init(&new->cname, NULL);
+ ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link);
+
+ rpz_obj = cfg_listelt_value(element);
+ policy_obj = cfg_tuple_get(rpz_obj, "policy");
+ if (cfg_obj_isvoid(policy_obj)) {
+ new->policy = DNS_RPZ_POLICY_GIVEN;
+ } else {
+ str = cfg_obj_asstring(policy_obj);
+ new->policy = dns_rpz_str2policy(str);
+ INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
+ }
+
+ dns_fixedname_init(&fixed);
+ origin = dns_fixedname_name(&fixed);
+ str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name"));
+ result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone '%s'", str);
+ goto cleanup;
+ }
+
+ result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE,
+ origin, DNS_NAME_DOWNCASE, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid zone '%s'", str);
+ goto cleanup;
+ }
+
+ /*
+ * The origin is part of 'nsdname' so we don't need to keep it
+ * seperately.
+ */
+ l1 = dns_name_countlabels(&new->nsdname);
+ l2 = dns_name_countlabels(origin);
+ dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin);
+
+ /*
+ * Are we configured to with the reponse policy zone?
+ */
+ result = dns_view_findzone(view, &new->origin, &zone);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "unknown zone '%s'", str);
+ goto cleanup;
+ }
+
+ if (dns_zone_gettype(zone) != dns_zone_master &&
+ dns_zone_gettype(zone) != dns_zone_slave) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "zone '%s' is neither master nor slave", str);
+ dns_zone_detach(&zone);
+ result = DNS_R_NOTMASTER;
+ goto cleanup;
+ }
+ dns_zone_detach(&zone);
+
+ 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)) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "duplicate '%s'", str);
+ result = DNS_R_DUPLICATE;
+ goto cleanup;
+ }
+ }
+
+ if (new->policy == DNS_RPZ_POLICY_CNAME) {
+ str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname"));
+ result = dns_name_fromstring(&new->cname, str, 0, view->mctx);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
+ "invalid cname '%s'", str);
+ goto cleanup;
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_rpz_view_destroy(view);
+ return (result);
+}
+
/*
* Configure 'view' according to 'vconfig', taking defaults from 'config'
* where values are missing in 'vconfig'.
@@ -1004,12 +1554,15 @@ cache_reusable(dns_view_t *originview, dns_view_t *view,
* global defaults in 'config' used exclusively.
*/
static isc_result_t
-configure_view(dns_view_t *view, const cfg_obj_t *config,
- const cfg_obj_t *vconfig, isc_mem_t *mctx,
- cfg_aclconfctx_t *actx, isc_boolean_t need_hints)
+configure_view(dns_view_t *view, cfg_parser_t* parser,
+ cfg_obj_t *config, cfg_obj_t *vconfig,
+ ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys,
+ isc_mem_t *mctx, cfg_aclconfctx_t *actx,
+ isc_boolean_t need_hints)
{
const cfg_obj_t *maps[4];
const cfg_obj_t *cfgmaps[3];
+ const cfg_obj_t *optionmaps[3];
const cfg_obj_t *options = NULL;
const cfg_obj_t *voptions = NULL;
const cfg_obj_t *forwardtype;
@@ -1028,17 +1581,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_cache_t *cache = NULL;
isc_result_t result;
isc_uint32_t max_adb_size;
+ unsigned int cleaning_interval;
isc_uint32_t max_cache_size;
isc_uint32_t max_acache_size;
isc_uint32_t lame_ttl;
- dns_tsig_keyring_t *ring;
+ dns_tsig_keyring_t *ring = NULL;
dns_view_t *pview = NULL; /* Production view */
isc_mem_t *cmctx;
dns_dispatch_t *dispatch4 = NULL;
dns_dispatch_t *dispatch6 = NULL;
isc_boolean_t reused_cache = ISC_FALSE;
- int i;
+ isc_boolean_t shared_cache = ISC_FALSE;
+ int i = 0, j = 0, k = 0;
const char *str;
+ const char *cachename = NULL;
dns_order_t *order = NULL;
isc_uint32_t udpsize;
unsigned int resopts = 0;
@@ -1052,7 +1608,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
const cfg_obj_t *disablelist = NULL;
isc_stats_t *resstats = NULL;
dns_stats_t *resquerystats = NULL;
+ isc_boolean_t auto_dlv = ISC_FALSE;
+ isc_boolean_t auto_root = ISC_FALSE;
+ ns_cache_t *nsc;
isc_boolean_t zero_no_soattl;
+ cfg_parser_t *newzones_parser = NULL;
+ cfg_obj_t *nzfconf = NULL;
+ dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
+ unsigned int query_timeout;
REQUIRE(DNS_VIEW_VALID(view));
@@ -1061,22 +1624,28 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
if (config != NULL)
(void)cfg_map_get(config, "options", &options);
- i = 0;
+ /*
+ * maps: view options, options, defaults
+ * cfgmaps: view options, config
+ * optionmaps: view options, options
+ */
if (vconfig != NULL) {
voptions = cfg_tuple_get(vconfig, "options");
maps[i++] = voptions;
+ optionmaps[j++] = voptions;
+ cfgmaps[k++] = voptions;
}
- if (options != NULL)
+ if (options != NULL) {
maps[i++] = options;
+ optionmaps[j++] = options;
+ }
+
maps[i++] = ns_g_defaults;
maps[i] = NULL;
-
- i = 0;
- if (voptions != NULL)
- cfgmaps[i++] = voptions;
+ optionmaps[j] = NULL;
if (config != NULL)
- cfgmaps[i++] = config;
- cfgmaps[i] = NULL;
+ cfgmaps[k++] = config;
+ cfgmaps[k] = NULL;
if (!strcmp(viewname, "_default")) {
sep = "";
@@ -1137,12 +1706,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_acache_setcachesize(view->acache, max_acache_size);
}
- CHECK(configure_view_acl(vconfig, config, "allow-query", actx,
+ CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx,
ns_g_mctx, &view->queryacl));
-
if (view->queryacl == NULL) {
- CHECK(configure_view_acl(NULL, ns_g_config, "allow-query", actx,
- ns_g_mctx, &view->queryacl));
+ CHECK(configure_view_acl(NULL, ns_g_config, "allow-query",
+ NULL, actx, ns_g_mctx,
+ &view->queryacl));
}
/*
@@ -1159,7 +1728,62 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
{
const cfg_obj_t *zconfig = cfg_listelt_value(element);
CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
- actx));
+ actx, ISC_FALSE));
+ }
+
+ /*
+ * Are we allowing zones to be added and deleted dynamically?
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "allow-new-zones", &obj);
+ if (result == ISC_R_SUCCESS) {
+ isc_boolean_t allow = cfg_obj_asboolean(obj);
+ struct cfg_context *cfg = NULL;
+ if (allow) {
+ cfg = isc_mem_get(view->mctx, sizeof(*cfg));
+ if (cfg == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ memset(cfg, 0, sizeof(*cfg));
+ isc_mem_attach(view->mctx, &cfg->mctx);
+ if (config != NULL)
+ cfg_obj_attach(config, &cfg->config);
+ cfg_parser_attach(parser, &cfg->parser);
+ cfg_aclconfctx_clone(actx, &cfg->actx);
+ }
+ dns_view_setnewzones(view, allow, cfg, cfgctx_destroy);
+ }
+
+ /*
+ * If we're allowing added zones, then load zone configuration
+ * from the newzone file for zones that were added during previous
+ * runs.
+ */
+ if (view->new_zone_file != NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "loading additional zones for view '%s'",
+ view->name);
+
+ CHECK(cfg_parser_create(view->mctx, ns_g_lctx,
+ &newzones_parser));
+ result = cfg_parse_file(newzones_parser, view->new_zone_file,
+ &cfg_type_newzones, &nzfconf);
+ if (result == ISC_R_SUCCESS) {
+ zonelist = NULL;
+ cfg_map_get(nzfconf, "zone", &zonelist);
+ for (element = cfg_list_first(zonelist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig =
+ cfg_listelt_value(element);
+ CHECK(configure_zone(config, zconfig, vconfig,
+ mctx, view, actx,
+ ISC_TRUE));
+ }
+ }
}
#ifdef DLZ
@@ -1197,6 +1821,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
if (result != ISC_R_SUCCESS)
goto cleanup;
+
+ /*
+ * If the dlz backend supports configuration,
+ * then call its configure method now.
+ */
+ result = dns_dlzconfigure(view, dlzconfigure_callback);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
}
}
#endif
@@ -1205,6 +1837,32 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
* Obtain configuration parameters that affect the decision of whether
* we can reuse/share an existing cache.
*/
+ obj = NULL;
+ result = ns_config_get(maps, "cleaning-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ cleaning_interval = cfg_obj_asuint32(obj) * 60;
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-cache-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isstring(obj)) {
+ str = cfg_obj_asstring(obj);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ max_cache_size = ISC_UINT32_MAX;
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > ISC_UINT32_MAX) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
+ "'max-cache-size "
+ "%" ISC_PRINT_QUADFORMAT "d' is too large",
+ value);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ max_cache_size = (isc_uint32_t)value;
+ }
+
/* Check-names. */
obj = NULL;
result = ns_checknames_get(maps, "response", &obj);
@@ -1229,6 +1887,109 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
zero_no_soattl = cfg_obj_asboolean(obj);
obj = NULL;
+ result = ns_config_get(maps, "dns64", &obj);
+ if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") &&
+ strcmp(view->name, "_meta")) {
+ const cfg_listelt_t *element;
+ isc_netaddr_t na, suffix, *sp;
+ unsigned int prefixlen;
+ const char *server, *contact;
+ const cfg_obj_t *myobj;
+
+ myobj = NULL;
+ result = ns_config_get(maps, "dns64-server", &myobj);
+ if (result == ISC_R_SUCCESS)
+ server = cfg_obj_asstring(myobj);
+ else
+ server = NULL;
+
+ myobj = NULL;
+ result = ns_config_get(maps, "dns64-contact", &myobj);
+ if (result == ISC_R_SUCCESS)
+ contact = cfg_obj_asstring(myobj);
+ else
+ contact = NULL;
+
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *map = cfg_listelt_value(element);
+ dns_dns64_t *dns64 = NULL;
+ unsigned int dns64options = 0;
+
+ cfg_obj_asnetprefix(cfg_map_getname(map), &na,
+ &prefixlen);
+
+ obj = NULL;
+ (void)cfg_map_get(map, "suffix", &obj);
+ if (obj != NULL) {
+ sp = &suffix;
+ isc_netaddr_fromsockaddr(sp,
+ cfg_obj_assockaddr(obj));
+ } else
+ sp = NULL;
+
+ clients = mapped = excluded = NULL;
+ obj = NULL;
+ (void)cfg_map_get(map, "clients", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ ns_g_lctx, actx,
+ mctx, 0, &clients);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ obj = NULL;
+ (void)cfg_map_get(map, "mapped", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ ns_g_lctx, actx,
+ mctx, 0, &mapped);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ obj = NULL;
+ (void)cfg_map_get(map, "exclude", &obj);
+ if (obj != NULL) {
+ result = cfg_acl_fromconfig(obj, config,
+ ns_g_lctx, actx,
+ mctx, 0, &excluded);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(map, "recursive-only", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj))
+ dns64options |= DNS_DNS64_RECURSIVE_ONLY;
+
+ obj = NULL;
+ (void)cfg_map_get(map, "break-dnssec", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj))
+ dns64options |= DNS_DNS64_BREAK_DNSSEC;
+
+ result = dns_dns64_create(mctx, &na, prefixlen, sp,
+ clients, mapped, excluded,
+ dns64options, &dns64);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_dns64_append(&view->dns64, dns64);
+ view->dns64cnt++;
+ result = dns64_reverse(view, mctx, &na, prefixlen,
+ server, contact);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (clients != NULL)
+ dns_acl_detach(&clients);
+ if (mapped != NULL)
+ dns_acl_detach(&mapped);
+ if (excluded != NULL)
+ dns_acl_detach(&excluded);
+ }
+ }
+
+ obj = NULL;
result = ns_config_get(maps, "dnssec-accept-expired", &obj);
INSIST(result == ISC_R_SUCCESS);
view->acceptexpired = cfg_obj_asboolean(obj);
@@ -1236,7 +1997,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
obj = NULL;
result = ns_config_get(maps, "dnssec-validation", &obj);
INSIST(result == ISC_R_SUCCESS);
- view->enablevalidation = cfg_obj_asboolean(obj);
+ if (cfg_obj_isboolean(obj)) {
+ view->enablevalidation = cfg_obj_asboolean(obj);
+ } else {
+ /* If dnssec-validation is not boolean, it must be "auto" */
+ view->enablevalidation = ISC_TRUE;
+ auto_root = ISC_TRUE;
+ }
obj = NULL;
result = ns_config_get(maps, "max-cache-ttl", &obj);
@@ -1251,53 +2018,113 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
view->maxncachettl = 7 * 24 * 3600;
/*
- * Configure the view's cache. Try to reuse an existing
- * cache if possible, otherwise create a new cache.
- * Note that the ADB is not preserved in either case.
- * When a matching view is found, the associated statistics are
- * also retrieved and reused.
+ * Configure the view's cache.
+ *
+ * First, check to see if there are any attach-cache options. If yes,
+ * attempt to lookup an existing cache at attach it to the view. If
+ * there is not one, then try to reuse an existing cache if possible;
+ * otherwise create a new cache.
*
- * XXX Determining when it is safe to reuse a cache is tricky.
+ * Note that the ADB is not preserved or shared in either case.
+ *
+ * When a matching view is found, the associated statistics are also
+ * retrieved and reused.
+ *
+ * XXX Determining when it is safe to reuse or share a cache is tricky.
* When the view's configuration changes, the cached data may become
* invalid because it reflects our old view of the world. We check
- * some of the configuration parameters that could invalidate the cache,
- * but there are other configuration options that should be checked.
- * For example, if a view uses a forwarder, changes in the forwarder
- * configuration may invalidate the cache. At the moment, it's the
- * administrator's responsibility to ensure these configuration options
- * don't invalidate reusing.
+ * some of the configuration parameters that could invalidate the cache
+ * or otherwise make it unsharable, but there are other configuration
+ * options that should be checked. For example, if a view uses a
+ * forwarder, changes in the forwarder configuration may invalidate
+ * the cache. At the moment, it's the administrator's responsibility to
+ * ensure these configuration options don't invalidate reusing/sharing.
*/
- result = dns_viewlist_find(&ns_g_server->viewlist,
- view->name, view->rdclass,
- &pview);
- if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
- goto cleanup;
- if (pview != NULL) {
- if (cache_reusable(pview, view, zero_no_soattl)) {
- INSIST(pview->cache != NULL);
- isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(3),
- "reusing existing cache");
- reused_cache = ISC_TRUE;
- dns_cache_attach(pview->cache, &cache);
- } else {
+ obj = NULL;
+ result = ns_config_get(maps, "attach-cache", &obj);
+ if (result == ISC_R_SUCCESS)
+ cachename = cfg_obj_asstring(obj);
+ else
+ cachename = view->name;
+ cache = NULL;
+ nsc = cachelist_find(cachelist, cachename);
+ if (nsc != NULL) {
+ if (!cache_sharable(nsc->primaryview, view, zero_no_soattl,
+ cleaning_interval, max_cache_size)) {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
- NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
- "cache cannot be reused for view %s "
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "views %s and %s can't share the cache "
"due to configuration parameter mismatch",
- view->name);
+ nsc->primaryview->name, view->name);
+ result = ISC_R_FAILURE;
+ goto cleanup;
}
- dns_view_getresstats(pview, &resstats);
- dns_view_getresquerystats(pview, &resquerystats);
- dns_view_detach(&pview);
- }
- if (cache == NULL) {
- CHECK(isc_mem_create(0, 0, &cmctx));
- CHECK(dns_cache_create(cmctx, ns_g_taskmgr, ns_g_timermgr,
- view->rdclass, "rbt", 0, NULL, &cache));
- isc_mem_setname(cmctx, "cache", NULL);
+ dns_cache_attach(nsc->cache, &cache);
+ shared_cache = ISC_TRUE;
+ } else {
+ if (strcmp(cachename, view->name) == 0) {
+ result = dns_viewlist_find(&ns_g_server->viewlist,
+ cachename, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (pview != NULL) {
+ if (!cache_reusable(pview, view,
+ zero_no_soattl)) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(1),
+ "cache cannot be reused "
+ "for view %s due to "
+ "configuration parameter "
+ "mismatch", view->name);
+ } else {
+ INSIST(pview->cache != NULL);
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(3),
+ "reusing existing cache");
+ reused_cache = ISC_TRUE;
+ dns_cache_attach(pview->cache, &cache);
+ }
+ dns_view_getresstats(pview, &resstats);
+ dns_view_getresquerystats(pview,
+ &resquerystats);
+ dns_view_detach(&pview);
+ }
+ }
+ if (cache == NULL) {
+ /*
+ * Create a cache with the desired name. This normally
+ * equals the view name, but may also be a forward
+ * reference to a view that share the cache with this
+ * view but is not yet configured. If it is not the
+ * view name but not a forward reference either, then it
+ * is simply a named cache that is not shared.
+ */
+ CHECK(isc_mem_create(0, 0, &cmctx));
+ isc_mem_setname(cmctx, "cache", NULL);
+ CHECK(dns_cache_create2(cmctx, ns_g_taskmgr,
+ ns_g_timermgr, view->rdclass,
+ cachename, "rbt", 0, NULL,
+ &cache));
+ }
+ nsc = isc_mem_get(mctx, sizeof(*nsc));
+ if (nsc == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ nsc->cache = NULL;
+ dns_cache_attach(cache, &nsc->cache);
+ nsc->primaryview = view;
+ nsc->needflush = ISC_FALSE;
+ nsc->adbsizeadjusted = ISC_FALSE;
+ ISC_LINK_INIT(nsc, link);
+ ISC_LIST_APPEND(*cachelist, nsc, link);
}
- dns_view_setcache(view, cache);
+ dns_view_setcache2(view, cache, shared_cache);
/*
* cache-file cannot be inherited if views are present, but this
@@ -1307,35 +2134,11 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
result = ns_config_get(maps, "cache-file", &obj);
if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) {
CHECK(dns_cache_setfilename(cache, cfg_obj_asstring(obj)));
- if (!reused_cache)
+ if (!reused_cache && !shared_cache)
CHECK(dns_cache_load(cache));
}
- obj = NULL;
- result = ns_config_get(maps, "cleaning-interval", &obj);
- INSIST(result == ISC_R_SUCCESS);
- dns_cache_setcleaninginterval(cache, cfg_obj_asuint32(obj) * 60);
-
- obj = NULL;
- result = ns_config_get(maps, "max-cache-size", &obj);
- INSIST(result == ISC_R_SUCCESS);
- if (cfg_obj_isstring(obj)) {
- str = cfg_obj_asstring(obj);
- INSIST(strcasecmp(str, "unlimited") == 0);
- max_cache_size = ISC_UINT32_MAX;
- } else {
- isc_resourcevalue_t value;
- value = cfg_obj_asuint64(obj);
- if (value > ISC_UINT32_MAX) {
- cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
- "'max-cache-size "
- "%" ISC_PRINT_QUADFORMAT "d' is too large",
- value);
- result = ISC_R_RANGE;
- goto cleanup;
- }
- max_cache_size = (isc_uint32_t)value;
- }
+ dns_cache_setcleaninginterval(cache, cleaning_interval);
dns_cache_setcachesize(cache, max_cache_size);
dns_cache_detach(&cache);
@@ -1373,13 +2176,23 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_view_setresquerystats(view, resquerystats);
/*
- * Set the ADB cache size to 1/8th of the max-cache-size.
+ * Set the ADB cache size to 1/8th of the max-cache-size or
+ * MAX_ADB_SIZE_FOR_CACHESHARE when the cache is shared.
*/
max_adb_size = 0;
if (max_cache_size != 0) {
max_adb_size = max_cache_size / 8;
if (max_adb_size == 0)
max_adb_size = 1; /* Force minimum. */
+ if (view != nsc->primaryview &&
+ max_adb_size > MAX_ADB_SIZE_FOR_CACHESHARE) {
+ max_adb_size = MAX_ADB_SIZE_FOR_CACHESHARE;
+ if (!nsc->adbsizeadjusted) {
+ dns_adb_setadbsize(nsc->primaryview->adb,
+ MAX_ADB_SIZE_FOR_CACHESHARE);
+ nsc->adbsizeadjusted = ISC_TRUE;
+ }
+ }
}
dns_adb_setadbsize(view->adb, max_adb_size);
@@ -1395,6 +2208,18 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_resolver_setlamettl(view->resolver, lame_ttl);
/*
+ * Set the resolver's query timeout.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "resolver-query-timeout", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ query_timeout = cfg_obj_asuint32(obj);
+ dns_resolver_settimeout(view->resolver, query_timeout);
+
+ /* Specify whether to use 0-TTL for negative response for SOA query */
+ dns_resolver_setzeronosoattl(view->resolver, zero_no_soattl);
+
+ /*
* Set the resolver's EDNS UDP size.
*/
obj = NULL;
@@ -1484,9 +2309,29 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
/*
* Configure the view's TSIG keys.
*/
- ring = NULL;
CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
+ if (ns_g_server->sessionkey != NULL) {
+ CHECK(dns_tsigkeyring_add(ring, ns_g_server->session_keyname,
+ ns_g_server->sessionkey));
+ }
dns_view_setkeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+
+ /*
+ * See if we can re-use a dynamic key ring.
+ */
+ result = dns_viewlist_find(&ns_g_server->viewlist, view->name,
+ view->rdclass, &pview);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (pview != NULL) {
+ dns_view_getdynamickeyring(pview, &ring);
+ if (ring != NULL)
+ dns_view_setdynamickeyring(view, ring);
+ dns_tsigkeyring_detach(&ring);
+ dns_view_detach(&pview);
+ } else
+ dns_view_restorekeyring(view);
/*
* Configure the view's peer list.
@@ -1543,10 +2388,10 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
/*
* Configure the "match-clients" and "match-destinations" ACL.
*/
- CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
+ CHECK(configure_view_acl(vconfig, config, "match-clients", NULL, actx,
ns_g_mctx, &view->matchclients));
- CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
- ns_g_mctx, &view->matchdestinations));
+ CHECK(configure_view_acl(vconfig, config, "match-destinations", NULL,
+ actx, ns_g_mctx, &view->matchdestinations));
/*
* Configure the "match-recursive-only" option.
@@ -1618,20 +2463,20 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
* "allow-recursion", and "allow-recursion-on" acls if
* configured in named.conf.
*/
- CHECK(configure_view_acl(vconfig, config, "allow-query-cache",
+ CHECK(configure_view_acl(vconfig, config, "allow-query-cache", NULL,
actx, ns_g_mctx, &view->cacheacl));
- CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on",
+ CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", NULL,
actx, ns_g_mctx, &view->cacheonacl));
if (view->cacheonacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-query-cache-on", actx,
+ "allow-query-cache-on", NULL, actx,
ns_g_mctx, &view->cacheonacl));
if (strcmp(view->name, "_bind") != 0) {
CHECK(configure_view_acl(vconfig, config, "allow-recursion",
- actx, ns_g_mctx,
+ NULL, actx, ns_g_mctx,
&view->recursionacl));
CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
- actx, ns_g_mctx,
+ NULL, actx, ns_g_mctx,
&view->recursiononacl));
}
@@ -1643,8 +2488,14 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*/
if (view->cacheacl == NULL && view->recursionacl != NULL)
dns_acl_attach(view->recursionacl, &view->cacheacl);
+ /*
+ * XXXEACH: This call to configure_view_acl() is redundant. We
+ * are leaving it as it is because we are making a minimal change
+ * for a patch release. In the future this should be changed to
+ * dns_acl_attach(view->queryacl, &view->cacheacl).
+ */
if (view->cacheacl == NULL && view->recursion)
- CHECK(configure_view_acl(vconfig, config, "allow-query",
+ CHECK(configure_view_acl(vconfig, config, "allow-query", NULL,
actx, ns_g_mctx, &view->cacheacl));
if (view->recursion &&
view->recursionacl == NULL && view->cacheacl != NULL)
@@ -1656,24 +2507,44 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*/
if (view->recursionacl == NULL && view->recursion)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-recursion",
+ "allow-recursion", NULL,
actx, ns_g_mctx,
&view->recursionacl));
if (view->recursiononacl == NULL && view->recursion)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-recursion-on",
+ "allow-recursion-on", NULL,
actx, ns_g_mctx,
&view->recursiononacl));
if (view->cacheacl == NULL) {
if (view->recursion)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-query-cache", actx,
- ns_g_mctx, &view->cacheacl));
+ "allow-query-cache", NULL,
+ actx, ns_g_mctx,
+ &view->cacheacl));
else
- CHECK(dns_acl_none(ns_g_mctx, &view->cacheacl));
+ CHECK(dns_acl_none(mctx, &view->cacheacl));
}
/*
+ * Filter setting on addresses in the answer section.
+ */
+ CHECK(configure_view_acl(vconfig, config, "deny-answer-addresses",
+ "acl", actx, ns_g_mctx, &view->denyansweracl));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-addresses",
+ "except-from", ns_g_mctx,
+ &view->answeracl_exclude));
+
+ /*
+ * Filter setting on names (CNAME/DNAME targets) in the answer section.
+ */
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
+ "name", ns_g_mctx,
+ &view->denyanswernames));
+ CHECK(configure_view_nametable(vconfig, config, "deny-answer-aliases",
+ "except-from", ns_g_mctx,
+ &view->answernames_exclude));
+
+ /*
* Configure sortlist, if set
*/
CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
@@ -1686,19 +2557,19 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
*/
if (view->notifyacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-notify", actx,
+ "allow-notify", NULL, actx,
ns_g_mctx, &view->notifyacl));
if (view->transferacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-transfer", actx,
+ "allow-transfer", NULL, actx,
ns_g_mctx, &view->transferacl));
if (view->updateacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-update", actx,
+ "allow-update", NULL, actx,
ns_g_mctx, &view->updateacl));
if (view->upfwdacl == NULL)
CHECK(configure_view_acl(NULL, ns_g_config,
- "allow-update-forwarding", actx,
+ "allow-update-forwarding", NULL, actx,
ns_g_mctx, &view->upfwdacl));
obj = NULL;
@@ -1728,13 +2599,47 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
cfg_obj_asuint32(obj),
max_clients_per_query);
+#ifdef ALLOW_FILTER_AAAA_ON_V4
+ obj = NULL;
+ result = ns_config_get(maps, "filter-aaaa-on-v4", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj))
+ view->v4_aaaa = dns_v4_aaaa_filter;
+ else
+ view->v4_aaaa = dns_v4_aaaa_ok;
+ } else {
+ const char *v4_aaaastr = cfg_obj_asstring(obj);
+ if (strcasecmp(v4_aaaastr, "break-dnssec") == 0)
+ view->v4_aaaa = dns_v4_aaaa_break_dnssec;
+ else
+ INSIST(0);
+ }
+ CHECK(configure_view_acl(vconfig, config, "filter-aaaa", NULL,
+ actx, ns_g_mctx, &view->v4_aaaa_acl));
+#endif
+
obj = NULL;
result = ns_config_get(maps, "dnssec-enable", &obj);
INSIST(result == ISC_R_SUCCESS);
view->enablednssec = cfg_obj_asboolean(obj);
obj = NULL;
- result = ns_config_get(maps, "dnssec-lookaside", &obj);
+ result = ns_config_get(optionmaps, "dnssec-lookaside", &obj);
+ if (result == ISC_R_SUCCESS) {
+ /* If set to "auto", use the version from the defaults */
+ const cfg_obj_t *dlvobj;
+ dlvobj = cfg_listelt_value(cfg_list_first(obj));
+ if (!strcmp(cfg_obj_asstring(cfg_tuple_get(dlvobj, "domain")),
+ "auto") &&
+ cfg_obj_isvoid(cfg_tuple_get(dlvobj, "trust-anchor"))) {
+ auto_dlv = ISC_TRUE;
+ obj = NULL;
+ result = cfg_map_get(ns_g_defaults,
+ "dnssec-lookaside", &obj);
+ }
+ }
+
if (result == ISC_R_SUCCESS) {
for (element = cfg_list_first(obj);
element != NULL;
@@ -1745,31 +2650,13 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
dns_name_t *dlv;
obj = cfg_listelt_value(element);
-#if 0
- dns_fixedname_t fixed;
- dns_name_t *name;
-
- /*
- * When we support multiple dnssec-lookaside
- * entries this is how to find the domain to be
- * checked. XXXMPA
- */
- dns_fixedname_init(&fixed);
- name = dns_fixedname_name(&fixed);
- str = cfg_obj_asstring(cfg_tuple_get(obj,
- "domain"));
- isc_buffer_init(&b, str, strlen(str));
- isc_buffer_add(&b, strlen(str));
- CHECK(dns_name_fromtext(name, &b, dns_rootname,
- ISC_TRUE, NULL));
-#endif
str = cfg_obj_asstring(cfg_tuple_get(obj,
"trust-anchor"));
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
dlv = dns_fixedname_name(&view->dlv_fixed);
CHECK(dns_name_fromtext(dlv, &b, dns_rootname,
- ISC_TRUE, NULL));
+ DNS_NAME_DOWNCASE, NULL));
view->dlv = dns_fixedname_name(&view->dlv_fixed);
}
} else
@@ -1779,8 +2666,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
* For now, there is only one kind of trusted keys, the
* "security roots".
*/
- CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
- &view->secroots));
+ CHECK(configure_view_dnsseckeys(view, vconfig, config, bindkeys,
+ auto_dlv, auto_root, mctx));
dns_resolver_resetmustbesecure(view->resolver);
obj = NULL;
result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
@@ -1821,7 +2708,7 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
CHECK(dns_name_fromtext(name, &b, dns_rootname,
- ISC_FALSE, NULL));
+ 0, NULL));
CHECK(dns_view_excludedelegationonly(view,
name));
}
@@ -1874,8 +2761,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
str = cfg_obj_asstring(obj);
isc_buffer_init(&buffer, str, strlen(str));
isc_buffer_add(&buffer, strlen(str));
- CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
+ NULL));
isc_buffer_init(&buffer, server, sizeof(server) - 1);
CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
server[isc_buffer_usedlength(&buffer)] = 0;
@@ -1889,8 +2776,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
str = cfg_obj_asstring(obj);
isc_buffer_init(&buffer, str, strlen(str));
isc_buffer_add(&buffer, strlen(str));
- CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
+ NULL));
isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
contact[isc_buffer_usedlength(&buffer)] = 0;
@@ -1916,8 +2803,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
/*
* Look for zone on drop list.
*/
- CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
+ NULL));
if (disablelist != NULL &&
on_disable_list(disablelist, name))
continue;
@@ -2012,9 +2899,40 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
}
}
+ /*
+ * Make the list of response policy zone names for views that
+ * are used for real lookups and so care about hints.
+ */
+ zonelist = NULL;
+ if (view->rdclass == dns_rdataclass_in && need_hints) {
+ obj = NULL;
+ result = ns_config_get(maps, "response-policy", &obj);
+ if (result == ISC_R_SUCCESS)
+ cfg_map_get(obj, "zone", &zonelist);
+ }
+ if (zonelist != NULL) {
+
+ for (element = cfg_list_first(zonelist);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ result = configure_rpz(view, element);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rpz_set_need(ISC_TRUE);
+ }
+ }
+
result = ISC_R_SUCCESS;
cleanup:
+ if (clients != NULL)
+ dns_acl_detach(&clients);
+ if (mapped != NULL)
+ dns_acl_detach(&mapped);
+ if (excluded != NULL)
+ dns_acl_detach(&excluded);
+ if (ring != NULL)
+ dns_tsigkeyring_detach(&ring);
if (zone != NULL)
dns_zone_detach(&zone);
if (dispatch4 != NULL)
@@ -2033,6 +2951,12 @@ configure_view(dns_view_t *view, const cfg_obj_t *config,
if (cache != NULL)
dns_cache_detach(&cache);
+ if (newzones_parser != NULL) {
+ if (nzfconf != NULL)
+ cfg_obj_destroy(newzones_parser, &nzfconf);
+ cfg_parser_destroy(&newzones_parser);
+ }
+
return (result);
}
@@ -2105,8 +3029,8 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view,
isc_buffer_add(&buffer, strlen(str));
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
- CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
- ISC_FALSE, NULL));
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname, 0,
+ NULL));
portobj = cfg_tuple_get(alternate, "port");
if (cfg_obj_isuint32(portobj)) {
@@ -2286,7 +3210,7 @@ create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
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)
+ cfg_aclconfctx_t *aclconf, isc_boolean_t added)
{
dns_view_t *pview = NULL; /* Production view */
dns_zone_t *zone = NULL; /* New or reused zone */
@@ -2319,7 +3243,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
isc_buffer_add(&buffer, strlen(zname));
dns_fixedname_init(&fixorigin);
CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
- &buffer, dns_rootname, ISC_FALSE, NULL));
+ &buffer, dns_rootname, 0, NULL));
origin = dns_fixedname_name(&fixorigin);
CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
@@ -2349,7 +3273,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
ztypestr = cfg_obj_asstring(typeobj);
/*
- * "hints zones" aren't zones. If we've got one,
+ * "hints zones" aren't zones. If we've got one,
* configure it and return.
*/
if (strcasecmp(ztypestr, "hint") == 0) {
@@ -2500,6 +3424,11 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
}
/*
+ * Mark whether the zone was originally added at runtime or not
+ */
+ dns_zone_setadded(zone, added);
+
+ /*
* Configure the zone.
*/
CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
@@ -2519,6 +3448,95 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
}
/*
+ * Configure built-in zone for storing managed-key data.
+ */
+
+#define KEYZONE "managed-keys.bind"
+#define MKEYS ".mkeys"
+
+static isc_result_t
+add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_view_t *pview = NULL;
+ dns_zone_t *zone = NULL;
+ dns_acl_t *none = NULL;
+ char filename[PATH_MAX];
+ char buffer[ISC_SHA256_DIGESTSTRINGLENGTH + sizeof(MKEYS)];
+ int n;
+
+ REQUIRE(view != NULL);
+
+ /* See if we can re-use an existing keydata zone. */
+ result = dns_viewlist_find(&ns_g_server->viewlist,
+ view->name, view->rdclass,
+ &pview);
+ if (result != ISC_R_NOTFOUND &&
+ result != ISC_R_SUCCESS)
+ return (result);
+
+ if (pview != NULL && pview->managed_keys != NULL) {
+ dns_zone_attach(pview->managed_keys, &view->managed_keys);
+ dns_zone_setview(pview->managed_keys, view);
+ dns_view_detach(&pview);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* No existing keydata zone was found; create one */
+ CHECK(dns_zone_create(&zone, mctx));
+ CHECK(dns_zone_setorigin(zone, dns_rootname));
+
+ isc_sha256_data((void *)view->name, strlen(view->name), buffer);
+ strcat(buffer, MKEYS);
+ n = snprintf(filename, sizeof(filename), "%s%s%s",
+ directory ? directory : "", directory ? "/" : "",
+ strcmp(view->name, "_default") == 0 ? KEYZONE : buffer);
+ if (n < 0 || (size_t)n >= sizeof(filename)) {
+ result = (n < 0) ? ISC_R_FAILURE : ISC_R_NOSPACE;
+ goto cleanup;
+ }
+ CHECK(dns_zone_setfile(zone, filename));
+
+ dns_zone_setview(zone, view);
+ dns_zone_settype(zone, dns_zone_key);
+ dns_zone_setclass(zone, view->rdclass);
+
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+
+ CHECK(dns_acl_none(mctx, &none));
+ dns_zone_setqueryacl(zone, none);
+ dns_zone_setqueryonacl(zone, none);
+ dns_acl_detach(&none);
+
+ dns_zone_setdialup(zone, dns_dialuptype_no);
+ dns_zone_setnotifytype(zone, dns_notifytype_no);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
+ dns_zone_setjournalsize(zone, 0);
+
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ CHECK(setquerystats(zone, mctx, ISC_FALSE));
+
+ if (view->managed_keys != NULL)
+ dns_zone_detach(&view->managed_keys);
+ dns_zone_attach(zone, &view->managed_keys);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "set up managed keys zone for view %s, file '%s'",
+ view->name, filename);
+
+cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (none != NULL)
+ dns_acl_detach(&none);
+
+ return (result);
+}
+
+/*
* Configure a single server quota.
*/
static void
@@ -2914,13 +3932,226 @@ removed(dns_zone_t *zone, void *uap) {
return (ISC_R_SUCCESS);
}
+static void
+cleanup_session_key(ns_server_t *server, isc_mem_t *mctx) {
+ if (server->session_keyfile != NULL) {
+ isc_file_remove(server->session_keyfile);
+ isc_mem_free(mctx, server->session_keyfile);
+ server->session_keyfile = NULL;
+ }
+
+ if (server->session_keyname != NULL) {
+ if (dns_name_dynamic(server->session_keyname))
+ dns_name_free(server->session_keyname, mctx);
+ isc_mem_put(mctx, server->session_keyname, sizeof(dns_name_t));
+ server->session_keyname = NULL;
+ }
+
+ if (server->sessionkey != NULL)
+ dns_tsigkey_detach(&server->sessionkey);
+
+ server->session_keyalg = DST_ALG_UNKNOWN;
+ server->session_keybits = 0;
+}
+
+static isc_result_t
+generate_session_key(const char *filename, const char *keynamestr,
+ dns_name_t *keyname, const char *algstr,
+ dns_name_t *algname, unsigned int algtype,
+ isc_uint16_t bits, isc_mem_t *mctx,
+ dns_tsigkey_t **tsigkeyp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dst_key_t *key = NULL;
+ isc_buffer_t key_txtbuffer;
+ isc_buffer_t key_rawbuffer;
+ char key_txtsecret[256];
+ char key_rawsecret[64];
+ isc_region_t key_rawregion;
+ isc_stdtime_t now;
+ dns_tsigkey_t *tsigkey = NULL;
+ FILE *fp = NULL;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "generating session key for dynamic DNS");
+
+ /* generate key */
+ result = dst_key_generate(keyname, algtype, bits, 1, 0,
+ DNS_KEYPROTO_ANY, dns_rdataclass_in,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Dump the key to the buffer for later use. Should be done before
+ * we transfer the ownership of key to tsigkey.
+ */
+ isc_buffer_init(&key_rawbuffer, &key_rawsecret, sizeof(key_rawsecret));
+ CHECK(dst_key_tobuffer(key, &key_rawbuffer));
+
+ isc_buffer_usedregion(&key_rawbuffer, &key_rawregion);
+ isc_buffer_init(&key_txtbuffer, &key_txtsecret, sizeof(key_txtsecret));
+ CHECK(isc_base64_totext(&key_rawregion, -1, "", &key_txtbuffer));
+
+ /* Store the key in tsigkey. */
+ isc_stdtime_get(&now);
+ CHECK(dns_tsigkey_createfromkey(dst_key_name(key), algname, key,
+ ISC_FALSE, NULL, now, now, mctx, NULL,
+ &tsigkey));
+
+ /* Dump the key to the key file. */
+ fp = ns_os_openfile(filename, S_IRUSR|S_IWUSR, ISC_TRUE);
+ if (fp == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not create %s", filename);
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ fprintf(fp, "key \"%s\" {\n"
+ "\talgorithm %s;\n"
+ "\tsecret \"%.*s\";\n};\n", keynamestr, algstr,
+ (int) isc_buffer_usedlength(&key_txtbuffer),
+ (char*) isc_buffer_base(&key_txtbuffer));
+
+ RUNTIME_CHECK(isc_stdio_flush(fp) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_stdio_close(fp) == ISC_R_SUCCESS);
+
+ dst_key_free(&key);
+
+ *tsigkeyp = tsigkey;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed to generate session key "
+ "for dynamic DNS: %s", isc_result_totext(result));
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+ if (key != NULL)
+ dst_key_free(&key);
+
+ return (result);
+}
+
+static isc_result_t
+configure_session_key(const cfg_obj_t **maps, ns_server_t *server,
+ isc_mem_t *mctx)
+{
+ const char *keyfile, *keynamestr, *algstr;
+ unsigned int algtype;
+ dns_fixedname_t fname;
+ dns_name_t *keyname, *algname;
+ isc_buffer_t buffer;
+ isc_uint16_t bits;
+ const cfg_obj_t *obj;
+ isc_boolean_t need_deleteold = ISC_FALSE;
+ isc_boolean_t need_createnew = ISC_FALSE;
+ isc_result_t result;
+
+ obj = NULL;
+ result = ns_config_get(maps, "session-keyfile", &obj);
+ if (result == ISC_R_SUCCESS) {
+ if (cfg_obj_isvoid(obj))
+ keyfile = NULL; /* disable it */
+ else
+ keyfile = cfg_obj_asstring(obj);
+ } else
+ keyfile = ns_g_defaultsessionkeyfile;
+
+ obj = NULL;
+ result = ns_config_get(maps, "session-keyname", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ keynamestr = cfg_obj_asstring(obj);
+ dns_fixedname_init(&fname);
+ isc_buffer_init(&buffer, keynamestr, strlen(keynamestr));
+ isc_buffer_add(&buffer, strlen(keynamestr));
+ keyname = dns_fixedname_name(&fname);
+ result = dns_name_fromtext(keyname, &buffer, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = NULL;
+ result = ns_config_get(maps, "session-keyalg", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ algstr = cfg_obj_asstring(obj);
+ algname = NULL;
+ result = ns_config_getkeyalgorithm2(algstr, &algname, &algtype, &bits);
+ if (result != ISC_R_SUCCESS) {
+ const char *s = " (keeping current key)";
+
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "session-keyalg: "
+ "unsupported or unknown algorithm '%s'%s",
+ algstr,
+ server->session_keyfile != NULL ? s : "");
+ return (result);
+ }
+
+ /* See if we need to (re)generate a new key. */
+ if (keyfile == NULL) {
+ if (server->session_keyfile != NULL)
+ need_deleteold = ISC_TRUE;
+ } else if (server->session_keyfile == NULL)
+ need_createnew = ISC_TRUE;
+ else if (strcmp(keyfile, server->session_keyfile) != 0 ||
+ !dns_name_equal(server->session_keyname, keyname) ||
+ server->session_keyalg != algtype ||
+ server->session_keybits != bits) {
+ need_deleteold = ISC_TRUE;
+ need_createnew = ISC_TRUE;
+ }
+
+ if (need_deleteold) {
+ INSIST(server->session_keyfile != NULL);
+ INSIST(server->session_keyname != NULL);
+ INSIST(server->sessionkey != NULL);
+
+ cleanup_session_key(server, mctx);
+ }
+
+ if (need_createnew) {
+ INSIST(server->sessionkey == NULL);
+ INSIST(server->session_keyfile == NULL);
+ INSIST(server->session_keyname == NULL);
+ INSIST(server->session_keyalg == DST_ALG_UNKNOWN);
+ INSIST(server->session_keybits == 0);
+
+ server->session_keyname = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (server->session_keyname == NULL)
+ goto cleanup;
+ dns_name_init(server->session_keyname, NULL);
+ CHECK(dns_name_dup(keyname, mctx, server->session_keyname));
+
+ server->session_keyfile = isc_mem_strdup(mctx, keyfile);
+ if (server->session_keyfile == NULL)
+ goto cleanup;
+
+ server->session_keyalg = algtype;
+ server->session_keybits = bits;
+
+ CHECK(generate_session_key(keyfile, keynamestr, keyname, algstr,
+ algname, algtype, bits, mctx,
+ &server->sessionkey));
+ }
+
+ return (result);
+
+ cleanup:
+ cleanup_session_key(server, mctx);
+ return (result);
+}
+
static isc_result_t
load_configuration(const char *filename, ns_server_t *server,
isc_boolean_t first_time)
{
cfg_aclconfctx_t aclconfctx;
- cfg_obj_t *config;
- cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL, *bindkeys = NULL;
+ cfg_parser_t *conf_parser = NULL, *bindkeys_parser = NULL;
const cfg_listelt_t *element;
const cfg_obj_t *builtin_views;
const cfg_obj_t *maps[3];
@@ -2931,7 +4162,7 @@ load_configuration(const char *filename, ns_server_t *server,
dns_view_t *view = NULL;
dns_view_t *view_next;
dns_viewlist_t tmpviewlist;
- dns_viewlist_t viewlist;
+ dns_viewlist_t viewlist, builtin_viewlist;
in_port_t listen_port, udpport_low, udpport_high;
int i;
isc_interval_t interval;
@@ -2943,10 +4174,14 @@ load_configuration(const char *filename, ns_server_t *server,
isc_uint32_t interface_interval;
isc_uint32_t reserved;
isc_uint32_t udpsize;
+ ns_cachelist_t cachelist, tmpcachelist;
unsigned int maxsocks;
+ ns_cache_t *nsc;
cfg_aclconfctx_init(&aclconfctx);
ISC_LIST_INIT(viewlist);
+ ISC_LIST_INIT(builtin_viewlist);
+ ISC_LIST_INIT(cachelist);
/* Ensure exclusive access to configuration data. */
result = isc_task_beginexclusive(server->task);
@@ -2958,8 +4193,7 @@ load_configuration(const char *filename, ns_server_t *server,
if (first_time) {
CHECK(ns_config_parsedefaults(ns_g_parser, &ns_g_config));
RUNTIME_CHECK(cfg_map_get(ns_g_config, "options",
- &ns_g_defaults) ==
- ISC_R_SUCCESS);
+ &ns_g_defaults) == ISC_R_SUCCESS);
}
/*
@@ -2976,10 +4210,10 @@ load_configuration(const char *filename, ns_server_t *server,
NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
ISC_LOG_INFO, "loading configuration from '%s'",
filename);
- CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
- cfg_parser_setcallback(parser, directory_callback, NULL);
- result = cfg_parse_file(parser, filename, &cfg_type_namedconf,
- &config);
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
+ cfg_parser_setcallback(conf_parser, directory_callback, NULL);
+ result = cfg_parse_file(conf_parser, filename,
+ &cfg_type_namedconf, &config);
}
/*
@@ -2994,10 +4228,10 @@ load_configuration(const char *filename, ns_server_t *server,
NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
ISC_LOG_INFO, "loading configuration from '%s'",
lwresd_g_resolvconffile);
- if (parser != NULL)
- cfg_parser_destroy(&parser);
- CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &parser));
- result = ns_lwresd_parseeresolvconf(ns_g_mctx, parser,
+ if (conf_parser != NULL)
+ cfg_parser_destroy(&conf_parser);
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx, &conf_parser));
+ result = ns_lwresd_parseeresolvconf(ns_g_mctx, conf_parser,
&config);
}
CHECK(result);
@@ -3019,13 +4253,38 @@ load_configuration(const char *filename, ns_server_t *server,
maps[i++] = NULL;
/*
+ * If bind.keys exists, load it. If "dnssec-lookaside auto"
+ * is turned on, the keys found there will be used as default
+ * trust anchors.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "bindkeys-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->bindkeysfile,
+ cfg_obj_asstring(obj)), "strdup");
+
+ if (access(server->bindkeysfile, R_OK) == 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reading built-in trusted "
+ "keys from file '%s'", server->bindkeysfile);
+
+ CHECK(cfg_parser_create(ns_g_mctx, ns_g_lctx,
+ &bindkeys_parser));
+
+ result = cfg_parse_file(bindkeys_parser, server->bindkeysfile,
+ &cfg_type_bindkeys, &bindkeys);
+ CHECK(result);
+ }
+
+ /*
* Set process limits, which (usually) needs to be done as root.
*/
set_limits(maps);
/*
* Check if max number of open sockets that the system allows is
- * sufficiently large. Failing this condition is not necessarily fatal,
+ * sufficiently large. Failing this condition is not necessarily fatal,
* but may cause subsequent runtime failures for a busy recursive
* server.
*/
@@ -3078,7 +4337,7 @@ load_configuration(const char *filename, ns_server_t *server,
else
isc_quota_soft(&server->recursionquota, 0);
- CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
+ CHECK(configure_view_acl(NULL, config, "blackhole", NULL, &aclconfctx,
ns_g_mctx, &server->blackholeacl));
if (server->blackholeacl != NULL)
dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
@@ -3318,6 +4577,31 @@ load_configuration(const char *filename, ns_server_t *server,
&interval, ISC_FALSE));
/*
+ * Write the PID file.
+ */
+ obj = NULL;
+ if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
+ if (cfg_obj_isvoid(obj))
+ ns_os_writepidfile(NULL, first_time);
+ else
+ ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
+ else if (ns_g_lwresdonly)
+ ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
+ else
+ ns_os_writepidfile(ns_g_defaultpidfile, first_time);
+
+ /*
+ * Configure the server-wide session key. This must be done before
+ * configure views because zone configuration may need to know
+ * session-keyname.
+ *
+ * Failure of session key generation isn't fatal at this time; if it
+ * turns out that a session key is really needed but doesn't exist,
+ * we'll treat it as a fatal error then.
+ */
+ (void)configure_session_key(maps, server, ns_g_mctx);
+
+ /*
* Configure and freeze all explicit views. Explicit
* views that have zones were already created at parsing
* time, but views with no zones must be created here.
@@ -3328,12 +4612,13 @@ load_configuration(const char *filename, ns_server_t *server,
element != NULL;
element = cfg_list_next(element))
{
- const cfg_obj_t *vconfig = cfg_listelt_value(element);
+ cfg_obj_t *vconfig = cfg_listelt_value(element);
view = NULL;
CHECK(create_view(vconfig, &viewlist, &view));
INSIST(view != NULL);
- CHECK(configure_view(view, config, vconfig,
+ CHECK(configure_view(view, conf_parser, config, vconfig,
+ &cachelist, bindkeys,
ns_g_mctx, &aclconfctx, ISC_TRUE));
dns_view_freeze(view);
dns_view_detach(&view);
@@ -3351,15 +4636,15 @@ load_configuration(const char *filename, ns_server_t *server,
* In either case, we need to configure and freeze it.
*/
CHECK(create_view(NULL, &viewlist, &view));
- CHECK(configure_view(view, config, NULL, ns_g_mctx,
- &aclconfctx, ISC_TRUE));
+ CHECK(configure_view(view, conf_parser, config, NULL,
+ &cachelist, bindkeys,
+ ns_g_mctx, &aclconfctx, ISC_TRUE));
dns_view_freeze(view);
dns_view_detach(&view);
}
/*
- * Create (or recreate) the built-in views. Currently
- * there is only one, the _bind view.
+ * Create (or recreate) the built-in views.
*/
builtin_views = NULL;
RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
@@ -3368,25 +4653,38 @@ load_configuration(const char *filename, ns_server_t *server,
element != NULL;
element = cfg_list_next(element))
{
- const cfg_obj_t *vconfig = cfg_listelt_value(element);
- CHECK(create_view(vconfig, &viewlist, &view));
- CHECK(configure_view(view, config, vconfig, ns_g_mctx,
- &aclconfctx, ISC_FALSE));
+ cfg_obj_t *vconfig = cfg_listelt_value(element);
+
+ CHECK(create_view(vconfig, &builtin_viewlist, &view));
+ CHECK(configure_view(view, conf_parser, config, vconfig,
+ &cachelist, bindkeys,
+ ns_g_mctx, &aclconfctx, ISC_FALSE));
dns_view_freeze(view);
dns_view_detach(&view);
view = NULL;
}
- /*
- * Swap our new view list with the production one.
- */
+ /* Now combine the two viewlists into one */
+ ISC_LIST_APPENDLIST(viewlist, builtin_viewlist, link);
+
+ /* Swap our new view list with the production one. */
tmpviewlist = server->viewlist;
server->viewlist = viewlist;
viewlist = tmpviewlist;
- /*
- * Load the TKEY information from the configuration.
- */
+ /* Make the view list available to each of the views */
+ view = ISC_LIST_HEAD(server->viewlist);
+ while (view != NULL) {
+ view->viewlist = &server->viewlist;
+ view = ISC_LIST_NEXT(view, link);
+ }
+
+ /* Swap our new cache list with the production one. */
+ tmpcachelist = server->cachelist;
+ server->cachelist = cachelist;
+ cachelist = tmpcachelist;
+
+ /* Load the TKEY information from the configuration. */
if (options != NULL) {
dns_tkeyctx_t *t = NULL;
CHECKM(ns_tkeyctx_fromconfig(options, ns_g_mctx, ns_g_entropy,
@@ -3551,16 +4849,6 @@ load_configuration(const char *filename, ns_server_t *server,
}
}
- obj = NULL;
- if (ns_config_get(maps, "pid-file", &obj) == ISC_R_SUCCESS)
- if (cfg_obj_isvoid(obj))
- ns_os_writepidfile(NULL, first_time);
- else
- ns_os_writepidfile(cfg_obj_asstring(obj), first_time);
- else if (ns_g_lwresdonly)
- ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
- else
- ns_os_writepidfile(ns_g_defaultpidfile, first_time);
obj = NULL;
if (options != NULL &&
@@ -3591,6 +4879,12 @@ load_configuration(const char *filename, ns_server_t *server,
"strdup");
obj = NULL;
+ result = ns_config_get(maps, "secroots-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->secrootsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
result = ns_config_get(maps, "recursing-file", &obj);
INSIST(result == ISC_R_SUCCESS);
CHECKM(setstring(server, &server->recfile, cfg_obj_asstring(obj)),
@@ -3647,12 +4941,18 @@ load_configuration(const char *filename, ns_server_t *server,
if (v6portset != NULL)
isc_portset_destroy(ns_g_mctx, &v6portset);
- cfg_aclconfctx_destroy(&aclconfctx);
+ cfg_aclconfctx_clear(&aclconfctx);
- if (parser != NULL) {
+ if (conf_parser != NULL) {
if (config != NULL)
- cfg_obj_destroy(parser, &config);
- cfg_parser_destroy(&parser);
+ cfg_obj_destroy(conf_parser, &config);
+ cfg_parser_destroy(&conf_parser);
+ }
+
+ if (bindkeys_parser != NULL) {
+ if (bindkeys != NULL)
+ cfg_obj_destroy(bindkeys_parser, &bindkeys);
+ cfg_parser_destroy(&bindkeys_parser);
}
if (view != NULL)
@@ -3675,6 +4975,13 @@ load_configuration(const char *filename, ns_server_t *server,
dns_view_detach(&view);
}
+ /* Same cleanup for cache list. */
+ while ((nsc = ISC_LIST_HEAD(cachelist)) != NULL) {
+ ISC_LIST_UNLINK(cachelist, nsc, link);
+ dns_cache_detach(&nsc->cache);
+ isc_mem_put(server->mctx, nsc, sizeof(*nsc));
+ }
+
/*
* Adjust the listening interfaces in accordance with the source
* addresses specified in views and zones.
@@ -3708,6 +5015,8 @@ load_zones(ns_server_t *server, isc_boolean_t stop) {
view = ISC_LIST_NEXT(view, link))
{
CHECK(dns_view_load(view, stop));
+ if (view->managed_keys != NULL)
+ CHECK(dns_zone_load(view->managed_keys));
}
/*
@@ -3737,11 +5046,14 @@ load_new_zones(ns_server_t *server, isc_boolean_t stop) {
view = ISC_LIST_NEXT(view, link))
{
CHECK(dns_view_loadnew(view, stop));
+
+ /* Load managed-keys data */
+ if (view->managed_keys != NULL)
+ CHECK(dns_zone_loadnew(view->managed_keys));
}
+
/*
- * Force zone maintenance. Do this after loading
- * so that we know when we need to force AXFR of
- * slave zones whose master files are missing.
+ * Resume zone XFRs.
*/
dns_zonemgr_resumexfrs(server->zonemgr);
cleanup:
@@ -3820,6 +5132,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
dns_view_t *view, *view_next;
ns_server_t *server = (ns_server_t *)event->ev_arg;
isc_boolean_t flush = server->flushonshutdown;
+ ns_cache_t *nsc;
UNUSED(task);
INSIST(task == server->task);
@@ -3834,6 +5147,7 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
ns_statschannels_shutdown(server);
ns_controls_shutdown(server->controls);
end_reserved_dispatches(server, ISC_TRUE);
+ cleanup_session_key(server, server->mctx);
cfg_obj_destroy(ns_g_parser, &ns_g_config);
cfg_parser_destroy(&ns_g_parser);
@@ -3849,6 +5163,12 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
dns_view_detach(&view);
}
+ while ((nsc = ISC_LIST_HEAD(server->cachelist)) != NULL) {
+ ISC_LIST_UNLINK(server->cachelist, nsc, link);
+ dns_cache_detach(&nsc->cache);
+ isc_mem_put(server->mctx, nsc, sizeof(*nsc));
+ }
+
isc_timer_detach(&server->interface_timer);
isc_timer_detach(&server->heartbeat_timer);
isc_timer_detach(&server->pps_timer);
@@ -3860,6 +5180,11 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
dns_zonemgr_shutdown(server->zonemgr);
+ if (ns_g_sessionkey != NULL) {
+ dns_tsigkey_detach(&ns_g_sessionkey);
+ dns_name_free(&ns_g_sessionkeyname, server->mctx);
+ }
+
if (server->blackholeacl != NULL)
dns_acl_detach(&server->blackholeacl);
@@ -3918,7 +5243,8 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
ISC_R_NOMEMORY : ISC_R_SUCCESS,
"allocating reload event");
- CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
+ CHECKFATAL(dst_lib_init2(ns_g_mctx, ns_g_entropy,
+ ns_g_engine, ISC_ENTROPY_GOODONLY),
"initializing DST");
server->tkeyctx = NULL;
@@ -3963,10 +5289,20 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
"isc_stats_create");
isc_socketmgr_setstats(ns_g_socketmgr, server->sockstats);
+ server->bindkeysfile = isc_mem_strdup(server->mctx, "bind.keys");
+ CHECKFATAL(server->bindkeysfile == NULL ? ISC_R_NOMEMORY :
+ ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
CHECKFATAL(server->dumpfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
"isc_mem_strdup");
+ server->secrootsfile = isc_mem_strdup(server->mctx, "named.secroots");
+ CHECKFATAL(server->secrootsfile == NULL ? ISC_R_NOMEMORY :
+ ISC_R_SUCCESS,
+ "isc_mem_strdup");
+
server->recfile = isc_mem_strdup(server->mctx, "named.recursing");
CHECKFATAL(server->recfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
"isc_mem_strdup");
@@ -4008,6 +5344,14 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
ISC_LIST_INIT(server->statschannels);
+ ISC_LIST_INIT(server->cachelist);
+
+ server->sessionkey = NULL;
+ server->session_keyfile = NULL;
+ server->session_keyname = NULL;
+ server->session_keyalg = DST_ALG_UNKNOWN;
+ server->session_keybits = 0;
+
server->magic = NS_SERVER_MAGIC;
*serverp = server;
}
@@ -4027,7 +5371,9 @@ ns_server_destroy(ns_server_t **serverp) {
isc_stats_detach(&server->sockstats);
isc_mem_free(server->mctx, server->statsfile);
+ isc_mem_free(server->mctx, server->bindkeysfile);
isc_mem_free(server->mctx, server->dumpfile);
+ isc_mem_free(server->mctx, server->secrootsfile);
isc_mem_free(server->mctx, server->recfile);
if (server->version != NULL)
@@ -4047,6 +5393,7 @@ ns_server_destroy(ns_server_t **serverp) {
isc_event_free(&server->reload_event);
INSIST(ISC_LIST_EMPTY(server->viewlist));
+ INSIST(ISC_LIST_EMPTY(server->cachelist));
dns_aclenv_destroy(&server->aclenv);
@@ -4278,7 +5625,9 @@ next_token(char **stringp, const char *delim) {
* set '*zonep' to NULL.
*/
static isc_result_t
-zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
+zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep,
+ const char **zonename)
+{
char *input, *ptr;
const char *zonetxt;
char *classtxt;
@@ -4302,6 +5651,8 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
zonetxt = next_token(&input, " \t");
if (zonetxt == NULL)
return (ISC_R_SUCCESS);
+ if (zonename)
+ *zonename = zonetxt;
/* Look for the optional class name. */
classtxt = next_token(&input, " \t");
@@ -4314,7 +5665,7 @@ zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
isc_buffer_add(&buf, strlen(zonetxt));
dns_fixedname_init(&name);
result = dns_name_fromtext(dns_fixedname_name(&name),
- &buf, dns_rootname, ISC_FALSE, NULL);
+ &buf, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
goto fail1;
@@ -4362,7 +5713,7 @@ ns_server_retransfercommand(ns_server_t *server, char *args) {
dns_zone_t *zone = NULL;
dns_zonetype_t type;
- result = zone_from_args(server, args, &zone);
+ result = zone_from_args(server, args, &zone, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (zone == NULL)
@@ -4386,7 +5737,7 @@ ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
dns_zonetype_t type;
const char *msg = NULL;
- result = zone_from_args(server, args, &zone);
+ result = zone_from_args(server, args, &zone, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (zone == NULL) {
@@ -4446,7 +5797,7 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
dns_zone_t *zone = NULL;
const unsigned char msg[] = "zone notify queued";
- result = zone_from_args(server, args, &zone);
+ result = zone_from_args(server, args, &zone, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (zone == NULL)
@@ -4471,7 +5822,7 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
const unsigned char msg2[] = "not a slave or stub zone";
dns_zonetype_t type;
- result = zone_from_args(server, args, &zone);
+ result = zone_from_args(server, args, &zone, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (zone == NULL)
@@ -4710,15 +6061,23 @@ dumpdone(void *arg, isc_result_t result) {
nextview:
fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
resume:
- if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
+ if (dctx->dumpcache && dns_view_iscacheshared(dctx->view->view)) {
+ fprintf(dctx->fp,
+ ";\n; Cache of view '%s' is shared as '%s'\n",
+ dctx->view->view->name,
+ dns_cache_getname(dctx->view->view->cache));
+ } else if (dctx->zone == NULL && dctx->cache == NULL &&
+ dctx->dumpcache)
+ {
style = &dns_master_style_cache;
/* start cache dump */
if (dctx->view->view->cachedb != NULL)
dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
if (dctx->cache != NULL) {
-
- fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
- dctx->view->view->name);
+ fprintf(dctx->fp,
+ ";\n; Cache dump of view '%s' (cache %s)\n;\n",
+ dctx->view->view->name,
+ dns_cache_getname(dctx->view->view->cache));
result = dns_master_dumptostreaminc(dctx->mctx,
dctx->cache, NULL,
style, dctx->fp,
@@ -4880,6 +6239,68 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
}
isc_result_t
+ns_server_dumpsecroots(ns_server_t *server, char *args) {
+ dns_view_t *view;
+ dns_keytable_t *secroots = NULL;
+ isc_result_t result;
+ char *ptr;
+ FILE *fp = NULL;
+ isc_time_t now;
+ char tbuf[64];
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+ ptr = next_token(&args, " \t");
+
+ CHECKMF(isc_stdio_open(server->secrootsfile, "w", &fp),
+ "could not open secroots dump file", server->secrootsfile);
+ TIME_NOW(&now);
+ isc_time_formattimestamp(&now, tbuf, sizeof(tbuf));
+ fprintf(fp, "%s\n", tbuf);
+
+ nextview:
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (ptr != NULL && strcmp(view->name, ptr) != 0)
+ continue;
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+ result = dns_view_getsecroots(view, &secroots);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ continue;
+ }
+ fprintf(fp, "\n Start view %s\n\n", view->name);
+ CHECK(dns_keytable_dump(secroots, fp));
+ }
+ if (ptr != NULL) {
+ ptr = next_token(&args, " \t");
+ if (ptr != NULL)
+ goto nextview;
+ }
+
+ cleanup:
+ if (secroots != NULL)
+ dns_keytable_detach(&secroots);
+ if (fp != NULL)
+ (void)isc_stdio_close(fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpsecroots complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpsecroots failed: %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+isc_result_t
ns_server_dumprecursing(ns_server_t *server) {
FILE *fp = NULL;
isc_result_t result;
@@ -4997,6 +6418,7 @@ ns_server_flushcache(ns_server_t *server, char *args) {
isc_boolean_t flushed;
isc_boolean_t found;
isc_result_t result;
+ ns_cache_t *nsc;
/* Skip the command name. */
ptr = next_token(&args, " \t");
@@ -5010,22 +6432,96 @@ ns_server_flushcache(ns_server_t *server, char *args) {
RUNTIME_CHECK(result == ISC_R_SUCCESS);
flushed = ISC_TRUE;
found = ISC_FALSE;
- for (view = ISC_LIST_HEAD(server->viewlist);
- view != NULL;
- view = ISC_LIST_NEXT(view, link))
- {
- if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
- continue;
+
+ /*
+ * Flushing a cache is tricky when caches are shared by multiple views.
+ * We first identify which caches should be flushed in the local cache
+ * list, flush these caches, and then update other views that refer to
+ * the flushed cache DB.
+ */
+ if (viewname != NULL) {
+ /*
+ * Mark caches that need to be flushed. This is an O(#view^2)
+ * operation in the very worst case, but should be normally
+ * much more lightweight because only a few (most typically just
+ * one) views will match.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (strcasecmp(viewname, view->name) != 0)
+ continue;
+ found = ISC_TRUE;
+ for (nsc = ISC_LIST_HEAD(server->cachelist);
+ nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link)) {
+ if (nsc->cache == view->cache)
+ break;
+ }
+ INSIST(nsc != NULL);
+ nsc->needflush = ISC_TRUE;
+ }
+ } else
found = ISC_TRUE;
- result = dns_view_flushcache(view);
+
+ /* Perform flush */
+ for (nsc = ISC_LIST_HEAD(server->cachelist);
+ nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link)) {
+ if (viewname != NULL && !nsc->needflush)
+ continue;
+ nsc->needflush = ISC_TRUE;
+ result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE);
if (result != ISC_R_SUCCESS) {
flushed = ISC_FALSE;
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
"flushing cache in view '%s' failed: %s",
- view->name, isc_result_totext(result));
+ nsc->primaryview->name,
+ isc_result_totext(result));
+ }
+ }
+
+ /*
+ * Fix up views that share a flushed cache: let the views update the
+ * cache DB they're referring to. This could also be an expensive
+ * operation, but should typically be marginal: the inner loop is only
+ * necessary for views that share a cache, and if there are many such
+ * views the number of shared cache should normally be small.
+ * A worst case is that we have n views and n/2 caches, each shared by
+ * two views. Then this will be a O(n^2/4) operation.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (!dns_view_iscacheshared(view))
+ continue;
+ for (nsc = ISC_LIST_HEAD(server->cachelist);
+ nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link)) {
+ if (!nsc->needflush || nsc->cache != view->cache)
+ continue;
+ result = dns_view_flushcache2(view, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ flushed = ISC_FALSE;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "fixing cache in view '%s' "
+ "failed: %s", view->name,
+ isc_result_totext(result));
+ }
}
}
+
+ /* Cleanup the cache list. */
+ for (nsc = ISC_LIST_HEAD(server->cachelist);
+ nsc != NULL;
+ nsc = ISC_LIST_NEXT(nsc, link)) {
+ nsc->needflush = ISC_FALSE;
+ }
+
if (flushed && found) {
if (viewname != NULL)
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
@@ -5076,7 +6572,7 @@ ns_server_flushname(ns_server_t *server, char *args) {
isc_buffer_add(&b, strlen(target));
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
- result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
return (result);
@@ -5094,6 +6590,11 @@ ns_server_flushname(ns_server_t *server, char *args) {
if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
continue;
found = ISC_TRUE;
+ /*
+ * It's a little inefficient to try flushing name for all views
+ * if some of the views share a single cache. But since the
+ * operation is lightweight we prefer simplicity here.
+ */
result = dns_view_flushname(view, name);
if (result != ISC_R_SUCCESS) {
flushed = ISC_FALSE;
@@ -5408,6 +6909,46 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
}
/*
+ * Act on a "sign" or "loadkeys" command from the command channel.
+ */
+isc_result_t
+ns_server_rekey(ns_server_t *server, char *args) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+ isc_uint16_t keyopts;
+ isc_boolean_t fullsign = ISC_FALSE;
+
+ if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0)
+ fullsign = ISC_TRUE;
+
+ result = zone_from_args(server, args, &zone, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL)
+ return (ISC_R_UNEXPECTEDEND); /* XXX: or do all zones? */
+
+ type = dns_zone_gettype(zone);
+ if (type != dns_zone_master) {
+ dns_zone_detach(&zone);
+ return (DNS_R_NOTMASTER);
+ }
+
+ keyopts = dns_zone_getkeyopts(zone);
+
+ /* "rndc loadkeys" requires "auto-dnssec maintain". */
+ if ((keyopts & DNS_ZONEKEY_ALLOW) == 0)
+ result = ISC_R_NOPERM;
+ else if ((keyopts & DNS_ZONEKEY_MAINTAIN) == 0 && !fullsign)
+ result = ISC_R_NOPERM;
+ else
+ dns_zone_rekey(zone, fullsign);
+
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
* Act on a "freeze" or "thaw" command from the command channel.
*/
isc_result_t
@@ -5425,7 +6966,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
isc_boolean_t frozen;
const char *msg = NULL;
- result = zone_from_args(server, args, &zone);
+ result = zone_from_args(server, args, &zone, NULL);
if (result != ISC_R_SUCCESS)
return (result);
if (zone == NULL) {
@@ -5451,7 +6992,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
type = dns_zone_gettype(zone);
if (type != dns_zone_master) {
dns_zone_detach(&zone);
- return (ISC_R_NOTFOUND);
+ return (DNS_R_NOTMASTER);
}
result = isc_task_beginexclusive(server->task);
@@ -5502,8 +7043,8 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
strlen(msg) + 1);
view = dns_zone_getview(zone);
- if (strcmp(view->name, "_bind") == 0 ||
- strcmp(view->name, "_default") == 0)
+ if (strcmp(view->name, "_default") == 0 ||
+ strcmp(view->name, "_bind") == 0)
{
vname = "";
sep = "";
@@ -5543,3 +7084,376 @@ ns_smf_add_message(isc_buffer_t *text) {
return (ISC_R_SUCCESS);
}
#endif /* HAVE_LIBSCF */
+
+/*
+ * Act on an "addzone" command from the command channel.
+ */
+isc_result_t
+ns_server_add_zone(ns_server_t *server, char *args) {
+ isc_result_t result;
+ isc_buffer_t argbuf;
+ size_t arglen;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *vconfig = NULL;
+ const cfg_obj_t *views = NULL;
+ const cfg_obj_t *parms = NULL;
+ const cfg_obj_t *obj = NULL;
+ const cfg_listelt_t *element;
+ const char *zonename;
+ const char *classname = NULL;
+ const char *argp;
+ const char *viewname = NULL;
+ dns_rdataclass_t rdclass;
+ dns_view_t *view = 0;
+ isc_buffer_t buf, *nbuf = NULL;
+ dns_name_t dnsname;
+ dns_zone_t *zone = NULL;
+ FILE *fp = NULL;
+ struct cfg_context *cfg = NULL;
+
+ /* Try to parse the argument string */
+ arglen = strlen(args);
+ isc_buffer_init(&argbuf, args, arglen);
+ isc_buffer_add(&argbuf, strlen(args));
+ CHECK(cfg_parser_create(server->mctx, ns_g_lctx, &parser));
+ CHECK(cfg_parse_buffer(parser, &argbuf, &cfg_type_addzoneconf,
+ &config));
+ CHECK(cfg_map_get(config, "addzone", &parms));
+
+ zonename = cfg_obj_asstring(cfg_tuple_get(parms, "name"));
+ isc_buffer_init(&buf, zonename, strlen(zonename));
+ isc_buffer_add(&buf, strlen(zonename));
+ dns_name_init(&dnsname, NULL);
+ isc_buffer_allocate(server->mctx, &nbuf, 256);
+ dns_name_setbuffer(&dnsname, nbuf);
+ CHECK(dns_name_fromtext(&dnsname, &buf, dns_rootname, ISC_FALSE, NULL));
+
+ /* Make sense of optional class argument */
+ obj = cfg_tuple_get(parms, "class");
+ CHECK(ns_config_getclass(obj, dns_rdataclass_in, &rdclass));
+ if (rdclass != dns_rdataclass_in && obj)
+ classname = cfg_obj_asstring(obj);
+
+ /* Make sense of optional view argument */
+ obj = cfg_tuple_get(parms, "view");
+ if (obj && cfg_obj_isstring(obj))
+ viewname = cfg_obj_asstring(obj);
+ if (viewname == NULL || *viewname == '\0')
+ viewname = "_default";
+ CHECK(dns_viewlist_find(&server->viewlist, viewname, rdclass, &view));
+
+ /* Are we accepting new zones? */
+ if (view->new_zone_file == NULL) {
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ cfg = (struct cfg_context *) view->new_zone_config;
+ if (cfg == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* Zone shouldn't already exist */
+ result = dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone);
+ if (result == ISC_R_SUCCESS) {
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ } else if (result == DNS_R_PARTIALMATCH) {
+ /* Create our sub-zone anyway */
+ dns_zone_detach(&zone);
+ zone = NULL;
+ }
+ else if (result != ISC_R_NOTFOUND)
+ goto cleanup;
+
+ /* Find the view statement */
+ cfg_map_get(cfg->config, "view", &views);
+ for (element = cfg_list_first(views);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *vname;
+ vconfig = cfg_listelt_value(element);
+ vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
+ if (vname && !strcasecmp(vname, viewname))
+ break;
+ vconfig = NULL;
+ }
+
+ /* Open save file for write configuration */
+ CHECK(isc_stdio_open(view->new_zone_file, "a", &fp));
+
+ /* Mark view unfrozen so that zone can be added */
+ dns_view_thaw(view);
+ result = configure_zone(cfg->config, parms, vconfig,
+ server->mctx, view, &cfg->actx, ISC_FALSE);
+ dns_view_freeze(view);
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ /* Is it there yet? */
+ CHECK(dns_zt_find(view->zonetable, &dnsname, 0, NULL, &zone));
+
+ /*
+ * Load the zone from the master file. If this fails, we'll
+ * need to undo the configuration we've done already.
+ */
+ result = dns_zone_loadnew(zone);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_t *dbp = NULL;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "addzone failed; reverting.");
+
+ /* If the zone loaded partially, unload it */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ /* Remove the zone from the zone table */
+ dns_zt_unmount(view->zonetable, zone);
+ goto cleanup;
+ }
+
+ /* Flag the zone as having been added at runtime */
+ dns_zone_setadded(zone, ISC_TRUE);
+
+ /* Emit just the zone name from args */
+ CHECK(isc_stdio_write("zone ", 5, 1, fp, NULL));
+ CHECK(isc_stdio_write(zonename, strlen(zonename), 1, fp, NULL));
+ CHECK(isc_stdio_write(" ", 1, 1, fp, NULL));
+
+ /* Classname, if not default */
+ if (classname != NULL && *classname != '\0') {
+ CHECK(isc_stdio_write(classname, strlen(classname), 1, fp,
+ NULL));
+ CHECK(isc_stdio_write(" ", 1, 1, fp, NULL));
+ }
+
+ /* Find beginning of option block from args */
+ for (argp = args; *argp; argp++, arglen--) {
+ if (*argp == '{') { /* Assume matching '}' */
+ /* Add that to our file */
+ CHECK(isc_stdio_write(argp, arglen, 1, fp, NULL));
+
+ /* Make sure we end with a LF */
+ if (argp[arglen-1] != '\n') {
+ CHECK(isc_stdio_write("\n", 1, 1, fp, NULL));
+ }
+ break;
+ }
+ }
+
+ CHECK(isc_stdio_close(fp));
+ fp = NULL;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone %s added to view %s via addzone",
+ zonename, viewname);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (fp != NULL)
+ isc_stdio_close(fp);
+ if (parser != NULL) {
+ if (config != NULL)
+ cfg_obj_destroy(parser, &config);
+ cfg_parser_destroy(&parser);
+ }
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (view != NULL)
+ dns_view_detach(&view);
+ if (nbuf != NULL)
+ isc_buffer_free(&nbuf);
+
+ return (result);
+}
+
+/*
+ * Act on a "delzone" command from the command channel.
+ */
+isc_result_t
+ns_server_del_zone(ns_server_t *server, char *args) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_view_t *view = NULL;
+ dns_db_t *dbp = NULL;
+ const char *filename = NULL;
+ char *tmpname = NULL;
+ char buf[1024];
+ const char *zonename = NULL;
+ size_t znamelen = 0;
+ FILE *ifp = NULL, *ofp = NULL;
+
+ /* Parse parameters */
+ CHECK(zone_from_args(server, args, &zone, &zonename));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ /*
+ * Was this zone originally added at runtime?
+ * If not, we can't delete it now.
+ */
+ if (!dns_zone_getadded(zone)) {
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ if (zonename != NULL)
+ znamelen = strlen(zonename);
+
+ /* Dig out configuration for this zone */
+ view = dns_zone_getview(zone);
+ filename = view->new_zone_file;
+ if (filename == NULL) {
+ /* No adding zones in this view */
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* Rewrite zone list */
+ result = isc_stdio_open(filename, "r", &ifp);
+ if (ifp != NULL && result == ISC_R_SUCCESS) {
+ char *found = NULL, *p = NULL;
+ size_t n;
+
+ /* Create a temporary file */
+ CHECK(isc_string_printf(buf, 1023, "%s.%ld", filename,
+ (long)getpid()));
+ if (!(tmpname = isc_mem_strdup(server->mctx, buf))) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ CHECK(isc_stdio_open(tmpname, "w", &ofp));
+
+ /* Look for the entry for that zone */
+ while (fgets(buf, 1024, ifp)) {
+ /* A 'zone' line */
+ if (strncasecmp(buf, "zone", 4)) {
+ fputs(buf, ofp);
+ continue;
+ }
+ p = buf+4;
+
+ /* Locate a name */
+ while (*p &&
+ ((*p == '"') || isspace((unsigned char)*p)))
+ p++;
+
+ /* Is that the zone we're looking for */
+ if (strncasecmp(p, zonename, znamelen)) {
+ fputs(buf, ofp);
+ continue;
+ }
+
+ /* And nothing else? */
+ p += znamelen;
+ if (isspace((unsigned char)*p) ||
+ *p == '"' || *p == '{') {
+ /* This must be the entry */
+ found = p;
+ break;
+ }
+
+ /* Spit it out, keep looking */
+ fputs(buf, ofp);
+ }
+
+ /* Skip over an option block (matching # of braces) */
+ if (found) {
+ int obrace = 0, cbrace = 0;
+ for (;;) {
+ while (*p) {
+ if (*p == '{') obrace++;
+ if (*p == '}') cbrace++;
+ p++;
+ }
+ if (obrace && (obrace == cbrace))
+ break;
+ if (!fgets(buf, 1024, ifp))
+ break;
+ p = buf;
+ }
+
+ /* Just spool the remainder of the file out */
+ result = isc_stdio_read(buf, 1, 1024, ifp, &n);
+ while (n > 0U) {
+ if (result == ISC_R_EOF)
+ result = ISC_R_SUCCESS;
+ CHECK(result);
+ isc_stdio_write(buf, 1, n, ofp, NULL);
+ result = isc_stdio_read(buf, 1, 1024, ifp, &n);
+ }
+
+ /* Move temporary into place */
+ CHECK(isc_file_rename(tmpname, view->new_zone_file));
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "deleted zone %s was missing from "
+ "new zone file", zonename);
+ goto cleanup;
+ }
+ }
+
+ /* Stop answering for this zone */
+ if (dns_zone_getdb(zone, &dbp) == ISC_R_SUCCESS) {
+ dns_db_detach(&dbp);
+ dns_zone_unload(zone);
+ }
+
+ CHECK(dns_zt_unmount(view->zonetable, zone));
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "zone %s removed via delzone", zonename);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (ifp != NULL)
+ isc_stdio_close(ifp);
+ if (ofp != NULL) {
+ isc_stdio_close(ofp);
+ isc_file_remove(tmpname);
+ }
+ if (tmpname != NULL)
+ isc_mem_free(server->mctx, tmpname);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ return (result);
+}
+
+static void
+cfgctx_destroy(void **cfgp) {
+ struct cfg_context *cfg;
+ isc_mem_t *mctx;
+
+ REQUIRE(cfgp != NULL && *cfgp != NULL);
+ cfg = *cfgp;
+ mctx = cfg->mctx;
+ cfg->mctx = NULL;
+
+ if (cfg->parser != NULL) {
+ if (cfg->config != NULL)
+ cfg_obj_destroy(cfg->parser, &cfg->config);
+ cfg_parser_destroy(&cfg->parser);
+ }
+ cfg_aclconfctx_clear(&cfg->actx);
+
+ isc_mem_put(mctx, cfg, sizeof(*cfg));
+ isc_mem_detach(&mctx);
+ *cfgp = NULL;
+}
diff --git a/contrib/bind9/bin/named/statschannel.c b/contrib/bind9/bin/named/statschannel.c
index c77d3ca1bfeb..6dce8e0a77c5 100644
--- a/contrib/bind9/bin/named/statschannel.c
+++ b/contrib/bind9/bin/named/statschannel.c
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: statschannel.c,v 1.14.64.11 2010-02-04 23:47:46 tbox Exp $ */
+/* $Id: statschannel.c,v 1.26 2010-02-04 23:49:13 tbox Exp $ */
/*! \file */
@@ -29,6 +29,7 @@
#include <isc/stats.h>
#include <isc/task.h>
+#include <dns/cache.h>
#include <dns/db.h>
#include <dns/opcode.h>
#include <dns/resolver.h>
@@ -823,9 +824,9 @@ generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
TRY0(xmlTextWriterStartElement(writer,
ISC_XMLCHAR "cache"));
TRY0(xmlTextWriterWriteAttribute(writer,
- ISC_XMLCHAR "name",
- ISC_XMLCHAR
- view->name));
+ ISC_XMLCHAR "name",
+ ISC_XMLCHAR
+ dns_cache_getname(view->cache)));
dumparg.result = ISC_R_SUCCESS;
dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
&dumparg, 0);
@@ -1405,7 +1406,15 @@ ns_stats_dump(ns_server_t *server, FILE *fp) {
if (strcmp(view->name, "_default") == 0)
fprintf(fp, "[View: default]\n");
else
- fprintf(fp, "[View: %s]\n", view->name);
+ fprintf(fp, "[View: %s (Cache: %s)]\n", view->name,
+ dns_cache_getname(view->cache));
+ if (dns_view_iscacheshared(view)) {
+ /*
+ * Avoid dumping redundant statistics when the cache is
+ * shared.
+ */
+ continue;
+ }
dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg,
0);
}
diff --git a/contrib/bind9/bin/named/tkeyconf.c b/contrib/bind9/bin/named/tkeyconf.c
index 734497803191..66c2d7f47cc9 100644
--- a/contrib/bind9/bin/named/tkeyconf.c
+++ b/contrib/bind9/bin/named/tkeyconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tkeyconf.c,v 1.29 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: tkeyconf.c,v 1.33 2010-12-20 23:47:20 tbox Exp $ */
/*! \file */
@@ -77,8 +77,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
isc_buffer_add(&b, strlen(s));
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
- RETERR(dns_name_fromtext(name, &b, dns_rootname,
- ISC_FALSE, NULL));
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY;
RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH,
type, NULL, mctx, &tctx->dhkey));
@@ -92,8 +91,7 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
isc_buffer_add(&b, strlen(s));
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
- RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE,
- NULL));
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t));
if (tctx->domain == NULL) {
result = ISC_R_NOMEMORY;
@@ -112,12 +110,22 @@ ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
isc_buffer_add(&b, strlen(s));
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
- RETERR(dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE,
- NULL));
- RETERR(dst_gssapi_acquirecred(name, ISC_FALSE,
- &tctx->gsscred));
+ RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+ RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred));
}
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-gssapi-keytab", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+ tctx->gssapi_keytab = isc_mem_strdup(mctx, s);
+ if (tctx->gssapi_keytab == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ }
+
+
*tctxp = tctx;
return (ISC_R_SUCCESS);
diff --git a/contrib/bind9/bin/named/tsigconf.c b/contrib/bind9/bin/named/tsigconf.c
index e90a86b5a783..19e8d385e05b 100644
--- a/contrib/bind9/bin/named/tsigconf.c
+++ b/contrib/bind9/bin/named/tsigconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: tsigconf.c,v 1.30 2007-06-19 23:46:59 tbox Exp $ */
+/* $Id: tsigconf.c,v 1.35 2011-01-11 23:47:12 tbox Exp $ */
/*! \file */
@@ -82,7 +82,7 @@ add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
isc_buffer_add(&keynamesrc, strlen(keyid));
isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
- ISC_TRUE, &keynamebuf);
+ DNS_NAME_DOWNCASE, &keynamebuf);
if (ret != ISC_R_SUCCESS)
goto failure;
@@ -149,6 +149,8 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
isc_result_t result;
int i;
+ REQUIRE(ringp != NULL && *ringp == NULL);
+
i = 0;
if (config != NULL)
maps[i++] = config;
@@ -176,6 +178,6 @@ ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
return (ISC_R_SUCCESS);
failure:
- dns_tsigkeyring_destroy(&ring);
+ dns_tsigkeyring_detach(&ring);
return (result);
}
diff --git a/contrib/bind9/bin/named/unix/Makefile.in b/contrib/bind9/bin/named/unix/Makefile.in
index 502db2508c98..ca92c49b5c78 100644
--- a/contrib/bind9/bin/named/unix/Makefile.in
+++ b/contrib/bind9/bin/named/unix/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1999-2001 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.10 2007-06-19 23:46:59 tbox Exp $
+# $Id: Makefile.in,v 1.13 2009-12-05 23:31:40 each Exp $
srcdir = @srcdir@
VPATH = @srcdir@
diff --git a/contrib/bind9/bin/named/unix/include/named/os.h b/contrib/bind9/bin/named/unix/include/named/os.h
index 0a846080a66f..c2768f426647 100644
--- a/contrib/bind9/bin/named/unix/include/named/os.h
+++ b/contrib/bind9/bin/named/unix/include/named/os.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: os.h,v 1.29 2008-10-24 01:44:48 tbox Exp $ */
+/* $Id: os.h,v 1.31 2009-08-05 23:47:43 tbox Exp $ */
#ifndef NS_OS_H
#define NS_OS_H 1
@@ -51,8 +51,12 @@ ns_os_adjustnofile(void);
void
ns_os_minprivs(void);
+FILE *
+ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user);
+
void
ns_os_writepidfile(const char *filename, isc_boolean_t first_time);
+
void
ns_os_shutdown(void);
diff --git a/contrib/bind9/bin/named/unix/os.c b/contrib/bind9/bin/named/unix/os.c
index 3f07784fcb82..53e9e4501249 100644
--- a/contrib/bind9/bin/named/unix/os.c
+++ b/contrib/bind9/bin/named/unix/os.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: os.c,v 1.89.12.5 2009-03-02 03:03:54 marka Exp $ */
+/* $Id: os.c,v 1.104 2010-11-17 23:47:08 tbox Exp $ */
/*! \file */
@@ -291,6 +291,12 @@ linux_initialprivs(void) {
*/
SET_CAP(CAP_SYS_RESOURCE);
+ /*
+ * We need to be able to set the ownership of the containing
+ * directory of the pid file when we create it.
+ */
+ SET_CAP(CAP_CHOWN);
+
linux_setcaps(caps);
#ifdef HAVE_LIBCAP
@@ -631,7 +637,7 @@ ns_os_minprivs(void) {
}
static int
-safe_open(const char *filename, isc_boolean_t append) {
+safe_open(const char *filename, mode_t mode, isc_boolean_t append) {
int fd;
struct stat sb;
@@ -644,13 +650,11 @@ safe_open(const char *filename, isc_boolean_t append) {
}
if (append)
- fd = open(filename, O_WRONLY|O_CREAT|O_APPEND,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, mode);
else {
if (unlink(filename) < 0 && errno != ENOENT)
return (-1);
- fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ fd = open(filename, O_WRONLY|O_CREAT|O_EXCL, mode);
}
return (fd);
}
@@ -686,6 +690,15 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) {
}
if (mkdirpath(filename, report) == -1)
goto error;
+ /*
+ * Handle "//", "/./" and "/../" in path.
+ */
+ if (!strcmp(slash + 1, "") ||
+ !strcmp(slash + 1, ".") ||
+ !strcmp(slash + 1, "..")) {
+ *slash = '/';
+ return (0);
+ }
mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */
mode |= S_IRGRP | S_IXGRP; /* g=rx */
mode |= S_IROTH | S_IXOTH; /* o=rx */
@@ -695,6 +708,13 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) {
strbuf);
goto error;
}
+ if (runas_pw != NULL &&
+ chown(filename, runas_pw->pw_uid,
+ runas_pw->pw_gid) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't chown '%s': %s", filename,
+ strbuf);
+ }
}
*slash = '/';
}
@@ -705,11 +725,127 @@ mkdirpath(char *filename, void (*report)(const char *, ...)) {
return (-1);
}
+static void
+setperms(uid_t uid, gid_t gid) {
+ char strbuf[ISC_STRERRORSIZE];
+#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
+ gid_t oldgid, tmpg;
+#endif
+#if !defined(HAVE_SETEUID) && defined(HAVE_SETRESUID)
+ uid_t olduid, tmpu;
+#endif
+#if defined(HAVE_SETEGID)
+ if (getegid() != gid && setegid(gid) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective gid to %ld: %s",
+ (long)gid, strbuf);
+ }
+#elif defined(HAVE_SETRESGID)
+ if (getresgid(&tmpg, &oldgid, &tmpg) == -1 || oldgid != gid) {
+ if (setresgid(-1, gid, -1) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective "
+ "gid to %d: %s", gid, strbuf);
+ }
+ }
+#endif
+
+#if defined(HAVE_SETEUID)
+ if (geteuid() != uid && seteuid(uid) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective uid to %ld: %s",
+ (long)uid, strbuf);
+ }
+#elif defined(HAVE_SETRESUID)
+ if (getresuid(&tmpu, &olduid, &tmpu) == -1 || olduid != uid) {
+ if (setresuid(-1, uid, -1) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("unable to set effective "
+ "uid to %d: %s", uid, strbuf);
+ }
+ }
+#endif
+}
+
+FILE *
+ns_os_openfile(const char *filename, mode_t mode, isc_boolean_t switch_user) {
+ char strbuf[ISC_STRERRORSIZE], *f;
+ FILE *fp;
+ int fd;
+
+ /*
+ * Make the containing directory if it doesn't exist.
+ */
+ f = strdup(filename);
+ if (f == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("couldn't strdup() '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+ if (mkdirpath(f, ns_main_earlywarning) == -1) {
+ free(f);
+ return (NULL);
+ }
+ free(f);
+
+ if (switch_user && runas_pw != NULL) {
+ /* Set UID/GID to the one we'll be running with eventually */
+ setperms(runas_pw->pw_uid, runas_pw->pw_gid);
+
+ fd = safe_open(filename, mode, ISC_FALSE);
+
+#ifndef HAVE_LINUXTHREADS
+ /* Restore UID/GID to root */
+ setperms(0, 0);
+#endif /* HAVE_LINUXTHREADS */
+
+ if (fd == -1) {
+#ifndef HAVE_LINUXTHREADS
+ fd = safe_open(filename, mode, ISC_FALSE);
+ if (fd != -1) {
+ ns_main_earlywarning("Required root "
+ "permissions to open "
+ "'%s'.", filename);
+ } else {
+ ns_main_earlywarning("Could not open "
+ "'%s'.", filename);
+ }
+ ns_main_earlywarning("Please check file and "
+ "directory permissions "
+ "or reconfigure the filename.");
+#else /* HAVE_LINUXTHREADS */
+ ns_main_earlywarning("Could not open "
+ "'%s'.", filename);
+ ns_main_earlywarning("Please check file and "
+ "directory permissions "
+ "or reconfigure the filename.");
+#endif /* HAVE_LINUXTHREADS */
+ }
+ } else {
+ fd = safe_open(filename, mode, ISC_FALSE);
+ }
+
+ if (fd < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not open file '%s': %s",
+ filename, strbuf);
+ return (NULL);
+ }
+
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("could not fdopen() file '%s': %s",
+ filename, strbuf);
+ }
+
+ return (fp);
+}
+
void
ns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
- int fd;
FILE *lockfile;
- size_t len;
pid_t pid;
char strbuf[ISC_STRERRORSIZE];
void (*report)(const char *, ...);
@@ -725,40 +861,16 @@ ns_os_writepidfile(const char *filename, isc_boolean_t first_time) {
if (filename == NULL)
return;
- len = strlen(filename);
- pidfile = malloc(len + 1);
+ pidfile = strdup(filename);
if (pidfile == NULL) {
isc__strerror(errno, strbuf, sizeof(strbuf));
- (*report)("couldn't malloc '%s': %s", filename, strbuf);
+ (*report)("couldn't strdup() '%s': %s", filename, strbuf);
return;
}
- /* This is safe. */
- strcpy(pidfile, filename);
-
- /*
- * Make the containing directory if it doesn't exist.
- */
- if (mkdirpath(pidfile, report) == -1) {
- free(pidfile);
- pidfile = NULL;
- return;
- }
-
- fd = safe_open(filename, ISC_FALSE);
- if (fd < 0) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- (*report)("couldn't open pid file '%s': %s", filename, strbuf);
- free(pidfile);
- pidfile = NULL;
- return;
- }
- lockfile = fdopen(fd, "w");
+ lockfile = ns_os_openfile(filename, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
+ first_time);
if (lockfile == NULL) {
- isc__strerror(errno, strbuf, sizeof(strbuf));
- (*report)("could not fdopen() pid file '%s': %s",
- filename, strbuf);
- (void)close(fd);
cleanup_pidfile();
return;
}
diff --git a/contrib/bind9/bin/named/update.c b/contrib/bind9/bin/named/update.c
index 1504a44b5ad0..eb1ed1d64ef9 100644
--- a/contrib/bind9/bin/named/update.c
+++ b/contrib/bind9/bin/named/update.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: update.c,v 1.151.12.11 2010-02-26 23:48:43 tbox Exp $ */
+/* $Id: update.c,v 1.186.16.1.2.1 2011-06-02 23:47:28 tbox Exp $ */
#include <config.h>
@@ -38,6 +38,7 @@
#include <dns/message.h>
#include <dns/nsec.h>
#include <dns/nsec3.h>
+#include <dns/private.h>
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
@@ -45,6 +46,7 @@
#include <dns/rdatatype.h>
#include <dns/soa.h>
#include <dns/ssu.h>
+#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
#include <dns/zt.h>
@@ -281,6 +283,47 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
}
/*%
+ * Check if we could have queried for the contents of this zone or
+ * if the zone is potentially updateable.
+ * If the zone can potentially be updated and the check failed then
+ * log a error otherwise we log a informational message.
+ */
+static isc_result_t
+checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
+ dns_acl_t *updateacl, dns_ssutable_t *ssutable)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ int level;
+ isc_result_t result;
+
+ result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ level = (updateacl == NULL && ssutable == NULL) ?
+ ISC_LOG_INFO : ISC_LOG_ERROR;
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, level,
+ "update '%s/%s' denied due to allow-query",
+ namebuf, classbuf);
+ } else if (updateacl == NULL && ssutable == NULL) {
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ result = DNS_R_REFUSED;
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
+ "update '%s/%s' denied", namebuf, classbuf);
+ }
+ return (result);
+}
+
+/*%
* Override the default acl logging when checking whether a client
* can update the zone or whether we can forward the request to the
* master based on IP address.
@@ -809,6 +852,9 @@ typedef struct {
/* The ssu table to check against. */
dns_ssutable_t *table;
+
+ /* the key used for TKEY requests */
+ dst_key_t *key;
} ssu_check_t;
static isc_result_t
@@ -825,14 +871,14 @@ ssu_checkrule(void *data, dns_rdataset_t *rrset) {
return (ISC_R_SUCCESS);
result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
ssuinfo->name, ssuinfo->tcpaddr,
- rrset->type);
+ rrset->type, ssuinfo->key);
return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE);
}
static isc_boolean_t
ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_ssutable_t *ssutable, dns_name_t *signer,
- isc_netaddr_t *tcpaddr)
+ isc_netaddr_t *tcpaddr, dst_key_t *key)
{
isc_result_t result;
ssu_check_t ssuinfo;
@@ -841,6 +887,7 @@ ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
ssuinfo.table = ssutable;
ssuinfo.signer = signer;
ssuinfo.tcpaddr = tcpaddr;
+ ssuinfo.key = key;
result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo);
return (ISC_TF(result == ISC_R_SUCCESS));
}
@@ -889,7 +936,7 @@ temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) {
b->op == DNS_DIFFOP_EXISTS);
INSIST(a->rdata.type == b->rdata.type);
INSIST(dns_name_equal(&a->name, &b->name));
- if (dns_rdata_compare(&a->rdata, &b->rdata) != 0)
+ if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0)
return (DNS_R_NXRRSET);
a = ISC_LIST_NEXT(a, link);
b = ISC_LIST_NEXT(b, link);
@@ -917,7 +964,7 @@ temp_order(const void *av, const void *bv) {
r = (b->rdata.type - a->rdata.type);
if (r != 0)
return (r);
- r = dns_rdata_compare(&a->rdata, &b->rdata);
+ r = dns_rdata_casecompare(&a->rdata, &b->rdata);
return (r);
}
@@ -1146,7 +1193,7 @@ rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
* dns_rdata_equal() (that used dns_name_equal()), since it
* would be faster. Not a priority.
*/
- return (dns_rdata_compare(update_rr, db_rr) == 0 ?
+ return (dns_rdata_casecompare(update_rr, db_rr) == 0 ?
ISC_TRUE : ISC_FALSE);
}
@@ -1208,11 +1255,10 @@ replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
return (ISC_FALSE);
INSIST(db_rr->length >= 4 && update_rr->length >= 4);
/*
- * Replace records added in this UPDATE request.
+ * Replace NSEC3PARAM records that only differ by the
+ * flags field.
*/
if (db_rr->data[0] == update_rr->data[0] &&
- db_rr->data[1] & DNS_NSEC3FLAG_UPDATE &&
- update_rr->data[1] & DNS_NSEC3FLAG_UPDATE &&
memcmp(db_rr->data+2, update_rr->data+2,
update_rr->length - 2) == 0)
return (ISC_TRUE);
@@ -1293,7 +1339,7 @@ add_rr_prepare_action(void *data, rr_t *rr) {
* If the update RR is a "duplicate" of the update RR,
* the update should be silently ignored.
*/
- equal = ISC_TF(dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0);
+ equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0);
if (equal && rr->ttl == ctx->update_rr_ttl) {
ctx->ignore_add = ISC_TRUE;
return (ISC_R_SUCCESS);
@@ -1717,35 +1763,6 @@ next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
return (result);
}
-static isc_boolean_t
-has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
- isc_result_t result;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdataset_t rdataset;
- isc_boolean_t has_bit = ISC_FALSE;
-
- dns_rdataset_init(&rdataset);
- CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
- dns_rdatatype_none, 0, &rdataset, NULL));
- CHECK(dns_rdataset_first(&rdataset));
- dns_rdataset_current(&rdataset, &rdata);
- has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt);
- failure:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- return (has_bit);
-}
-
-static void
-set_bit(unsigned char *array, unsigned int index) {
- unsigned int shift, bit;
-
- shift = 7 - (index % 8);
- bit = 1 << shift;
-
- array[index / 8] |= bit;
-}
-
/*%
* Add a NSEC record for "name", recording the change in "diff".
* The existing NSEC is removed.
@@ -1777,24 +1794,6 @@ add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
dns_rdata_init(&rdata);
CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
- /*
- * Preserve the status of the OPT bit in the origin's NSEC record.
- */
- if (dns_name_equal(dns_db_origin(db), name) &&
- has_opt_bit(db, ver, node))
- {
- isc_region_t region;
- dns_name_t next;
-
- dns_name_init(&next, NULL);
- dns_rdata_toregion(&rdata, &region);
- dns_name_fromregion(&next, &region);
- isc_region_consume(&region, next.length);
- INSIST(region.length > (2 + dns_rdatatype_opt / 8) &&
- region.base[0] == 0 &&
- region.base[1] > dns_rdatatype_opt / 8);
- set_bit(region.base + 2, dns_rdatatype_opt);
- }
dns_db_detachnode(db, &node);
/*
@@ -1856,44 +1855,6 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
return (result);
}
-static isc_boolean_t
-ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
- isc_boolean_t ret = ISC_FALSE;
- isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
- isc_result_t result;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdata_dnskey_t dnskey;
-
- dns_rdataset_init(&rdataset);
- CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
- CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
- &rdataset, NULL));
- CHECK(dns_rdataset_first(&rdataset));
- while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
- dns_rdataset_current(&rdataset, &rdata);
- CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
- if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
- == DNS_KEYOWNER_ZONE) {
- if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
- have_ksk = ISC_TRUE;
- else
- have_nonksk = ISC_TRUE;
- }
- dns_rdata_reset(&rdata);
- result = dns_rdataset_next(&rdataset);
- }
- if (have_ksk && have_nonksk)
- ret = ISC_TRUE;
- failure:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- if (node != NULL)
- dns_db_detachnode(db, &node);
- return (ret);
-}
-
/*%
* Add RRSIG records for an RRset, recording the change in "diff".
*/
@@ -1902,7 +1863,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
isc_stdtime_t inception, isc_stdtime_t expire,
- isc_boolean_t check_ksk)
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
@@ -1910,7 +1871,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
isc_buffer_t buffer;
unsigned char data[1024]; /* XXX */
- unsigned int i;
+ unsigned int i, j;
isc_boolean_t added_sig = ISC_FALSE;
isc_mem_t *mctx = client->mctx;
@@ -1926,13 +1887,52 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
(isc_stdtime_t) 0, &rdataset, NULL));
dns_db_detachnode(db, &node);
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
+#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
+#define ALG(x) dst_key_alg(x)
+
+ /*
+ * If we are honoring KSK flags then we need to check that we
+ * have both KSK and non-KSK keys that are not revoked per
+ * algorithm.
+ */
for (i = 0; i < nkeys; i++) {
+ isc_boolean_t both = ISC_FALSE;
- if (check_ksk && type != dns_rdatatype_dnskey &&
- (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ if (!dst_key_isprivate(keys[i]))
continue;
- if (!dst_key_isprivate(keys[i]))
+ if (check_ksk && !REVOKE(keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i || ALG(keys[i]) != ALG(keys[j]))
+ continue;
+ if (REVOKE(keys[j]))
+ continue;
+ if (KSK(keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+
+ if (both) {
+ if (type == dns_rdatatype_dnskey) {
+ if (!KSK(keys[i]) && keyset_kskonly)
+ continue;
+ } else if (KSK(keys[i]))
+ continue;
+ } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
continue;
/* Calculate the signature, creating a RRSIG RDATA. */
@@ -1950,7 +1950,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
}
if (!added_sig) {
update_log(client, zone, ISC_LOG_ERROR,
- "found no private keys, "
+ "found no active private keys, "
"unable to generate any signatures");
result = ISC_R_NOTFOUND;
}
@@ -2044,7 +2044,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
isc_stdtime_t inception, isc_stdtime_t expire,
- isc_boolean_t check_ksk)
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node;
@@ -2090,7 +2090,8 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
if (flag)
continue;;
result = add_sigs(client, zone, db, ver, name, type, diff,
- keys, nkeys, inception, expire, check_ksk);
+ keys, nkeys, inception, expire,
+ check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS)
goto cleanup_iterator;
}
@@ -2120,8 +2121,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
static isc_result_t
update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *oldver, dns_dbversion_t *newver,
- dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
- isc_boolean_t *deleted_zsk)
+ dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
{
isc_result_t result;
dns_difftuple_t *t;
@@ -2130,7 +2130,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_diff_t sig_diff;
dns_diff_t nsec_diff;
dns_diff_t nsec_mindiff;
- isc_boolean_t flag;
+ isc_boolean_t flag, build_nsec, build_nsec3;
dst_key_t *zone_keys[MAXZONEKEYS];
unsigned int nkeys = 0;
unsigned int i;
@@ -2140,9 +2140,10 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t rdataset;
dns_dbnode_t *node = NULL;
- isc_boolean_t check_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly;
isc_boolean_t unsecure;
isc_boolean_t cut;
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
dns_diff_init(client->mctx, &diffnames);
dns_diff_init(client->mctx, &affected);
@@ -2172,27 +2173,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
*/
check_ksk = ISC_TF((dns_zone_getoptions(zone) &
DNS_ZONEOPT_UPDATECHECKKSK) != 0);
- /*
- * If we are not checking the ZSK flag then all DNSKEY's are
- * already signing all RRsets so we don't need to trigger special
- * changes.
- */
- if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver)))
- *deleted_zsk = ISC_FALSE;
-
- if (check_ksk) {
- check_ksk = ksk_sanity(db, newver);
- if (!check_ksk && ksk_sanity(db, oldver))
- update_log(client, zone, ISC_LOG_WARNING,
- "disabling update-check-ksk");
- }
-
- /*
- * If we have deleted a ZSK and we we still have some ZSK's
- * we don't need to convert the KSK's to a ZSK's.
- */
- if (*deleted_zsk && check_ksk)
- *deleted_zsk = ISC_FALSE;
+ keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
+ DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
/*
* Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
@@ -2259,7 +2241,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(add_sigs(client, zone, db, newver, name,
type, &sig_diff, zone_keys,
nkeys, inception, expire,
- check_ksk));
+ check_ksk, keyset_kskonly));
}
skip:
/* Skip any other updates to the same RRset. */
@@ -2289,12 +2271,11 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
"removed any orphaned NSEC records");
/*
- * If we don't have a NSEC record at the origin then we need to
- * update the NSEC3 records.
+ * See if we need to build NSEC or NSEC3 chains.
*/
- CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec,
- 0, &flag));
- if (!flag)
+ CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
+ &build_nsec3));
+ if (!build_nsec)
goto update_nsec3;
update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain");
@@ -2398,16 +2379,25 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_rdatatype_any, 0, NULL, diff));
} else {
/*
- * This name is not obscured. It should have a NSEC.
+ * This name is not obscured. It needs to have a
+ * NSEC unless it is the at the origin, in which
+ * case it should already exist if there is a complete
+ * NSEC chain and if there isn't a complete NSEC chain
+ * we don't want to add one as that would signal that
+ * there is a complete NSEC chain.
*/
- CHECK(rrset_exists(db, newver, name,
- dns_rdatatype_nsec, 0, &flag));
- if (! flag)
- CHECK(add_placeholder_nsec(db, newver, name,
- diff));
+ if (!dns_name_equal(name, dns_db_origin(db))) {
+ CHECK(rrset_exists(db, newver, name,
+ dns_rdatatype_nsec, 0,
+ &flag));
+ if (!flag)
+ CHECK(add_placeholder_nsec(db, newver,
+ name, diff));
+ }
CHECK(add_exposed_sigs(client, zone, db, newver, name,
cut, diff, zone_keys, nkeys,
- inception, expire, check_ksk));
+ inception, expire, check_ksk,
+ keyset_kskonly));
}
}
@@ -2469,7 +2459,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(add_sigs(client, zone, db, newver, &t->name,
dns_rdatatype_nsec, &sig_diff,
zone_keys, nkeys, inception, expire,
- check_ksk));
+ check_ksk, keyset_kskonly));
} else {
INSIST(0);
}
@@ -2491,13 +2481,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
- /*
- * Check if we have any active NSEC3 chains by looking for a
- * NSEC3PARAM RRset.
- */
- CHECK(rrset_exists(db, newver, dns_db_origin(db),
- dns_rdatatype_nsec3param, 0, &flag));
- if (!flag) {
+ if (!build_nsec3) {
update_log(client, zone, ISC_LOG_DEBUG(3),
"no NSEC3 chains to rebuild");
goto failure;
@@ -2521,6 +2505,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
isc_boolean_t ns_existed, dname_existed;
isc_boolean_t ns_exists, dname_exists;
+ isc_boolean_t exists, existed;
if (t->rdata.type == dns_rdatatype_nsec ||
t->rdata.type == dns_rdatatype_rrsig) {
@@ -2539,7 +2524,9 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0,
&dname_exists));
- if ((ns_exists || dname_exists) == (ns_existed || dname_existed))
+ exists = ns_exists || dname_exists;
+ existed = ns_existed || dname_existed;
+ if (exists == existed)
goto nextname;
/*
* There was a delegation change. Mark all subdomains
@@ -2563,14 +2550,16 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
if (!flag) {
CHECK(delete_if(rrsig_p, db, newver, name,
dns_rdatatype_any, 0, NULL, diff));
- CHECK(dns_nsec3_delnsec3s(db, newver, name,
- &nsec_diff));
+ CHECK(dns_nsec3_delnsec3sx(db, newver, name,
+ privatetype, &nsec_diff));
} else {
CHECK(add_exposed_sigs(client, zone, db, newver, name,
cut, diff, zone_keys, nkeys,
- inception, expire, check_ksk));
- CHECK(dns_nsec3_addnsec3s(db, newver, name, nsecttl,
- unsecure, &nsec_diff));
+ inception, expire, check_ksk,
+ keyset_kskonly));
+ CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl,
+ unsecure, privatetype,
+ &nsec_diff));
}
}
@@ -2601,7 +2590,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
CHECK(add_sigs(client, zone, db, newver, &t->name,
dns_rdatatype_nsec3,
&sig_diff, zone_keys, nkeys,
- inception, expire, check_ksk));
+ inception, expire, check_ksk,
+ keyset_kskonly));
} else {
INSIST(0);
}
@@ -2734,6 +2724,7 @@ ns_update_start(ns_client_t *client, isc_result_t sigresult) {
switch(dns_zone_gettype(zone)) {
case dns_zone_master:
+ case dns_zone_dlz:
/*
* We can now fail due to a bad signature as we now know
* that we are the master.
@@ -2943,7 +2934,7 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
result = dns_rdataset_next(&rdataset)) {
dns_rdata_t myrdata = DNS_RDATA_INIT;
dns_rdataset_current(&rdataset, &myrdata);
- if (!dns_rdata_compare(&myrdata, rdata))
+ if (!dns_rdata_casecompare(&myrdata, rdata))
break;
}
dns_rdataset_disassociate(&rdataset);
@@ -2961,7 +2952,9 @@ rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
}
static isc_result_t
-get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) {
+get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype,
+ unsigned int *iterationsp)
+{
dns_dbnode_t *node = NULL;
dns_rdata_nsec3param_t nsec3param;
dns_rdataset_t rdataset;
@@ -2975,7 +2968,33 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) {
return (result);
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
0, (isc_stdtime_t) 0, &rdataset, NULL);
- dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto try_private;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (nsec3param.iterations > iterations)
+ iterations = nsec3param.iterations;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ dns_rdataset_disassociate(&rdataset);
+
+ try_private:
+ if (privatetype == 0)
+ goto success;
+
+ result = dns_db_findrdataset(db, node, ver, privatetype,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
if (result == ISC_R_NOTFOUND)
goto success;
if (result != ISC_R_SUCCESS)
@@ -2984,8 +3003,14 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) {
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t private = DNS_RDATA_INIT;
dns_rdata_t rdata = DNS_RDATA_INIT;
+
dns_rdataset_current(&rdataset, &rdata);
+ if (!dns_nsec3param_fromprivate(&private, &rdata,
+ buf, sizeof(buf)))
+ continue;
CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
continue;
@@ -3000,6 +3025,8 @@ get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) {
result = ISC_R_SUCCESS;
failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
if (dns_rdataset_isassociated(&rdataset))
dns_rdataset_disassociate(&rdataset);
return (result);
@@ -3013,77 +3040,83 @@ static isc_result_t
check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *ver, dns_diff_t *diff)
{
- dns_diff_t temp_diff;
- dns_diffop_t op;
- dns_difftuple_t *tuple, *newtuple = NULL, *next;
- isc_boolean_t flag;
+ dns_difftuple_t *tuple;
+ isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
isc_result_t result;
unsigned int iterations = 0, max;
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
- dns_diff_init(diff->mctx, &temp_diff);
-
- CHECK(dns_nsec_nseconly(db, ver, &flag));
+ /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ if (tuple->op != DNS_DIFFOP_ADD)
+ continue;
- if (flag)
- CHECK(dns_nsec3_active(db, ver, ISC_FALSE, &flag));
- if (flag) {
- update_log(client, zone, ISC_LOG_WARNING,
- "NSEC only DNSKEYs and NSEC3 chains not allowed");
- } else {
- CHECK(get_iterations(db, ver, &iterations));
- CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max));
- if (max != 0 && iterations > max) {
- flag = ISC_TRUE;
- update_log(client, zone, ISC_LOG_WARNING,
- "too many NSEC3 iterations (%u) for "
- "weakest DNSKEY (%u)", iterations, max);
+ if (tuple->rdata.type == dns_rdatatype_dnskey) {
+ isc_uint8_t alg;
+ alg = tuple->rdata.data[3];
+ if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
+ alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
+ nseconly = ISC_TRUE;
+ break;
+ }
+ } else if (tuple->rdata.type == dns_rdatatype_nsec3param) {
+ nsec3 = ISC_TRUE;
+ break;
}
}
- if (flag) {
- for (tuple = ISC_LIST_HEAD(diff->tuples);
- tuple != NULL;
- tuple = next) {
- next = ISC_LIST_NEXT(tuple, link);
- if (tuple->rdata.type != dns_rdatatype_dnskey &&
- tuple->rdata.type != dns_rdatatype_nsec3param)
- continue;
- op = (tuple->op == DNS_DIFFOP_DEL) ?
- DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
- CHECK(dns_difftuple_create(temp_diff.mctx, op,
- &tuple->name, tuple->ttl,
- &tuple->rdata, &newtuple));
- CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff));
- INSIST(newtuple == NULL);
- }
- for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
- tuple != NULL;
- tuple = ISC_LIST_HEAD(temp_diff.tuples)) {
- ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
- dns_diff_appendminimal(diff, &tuple);
- }
+
+ /* Check existing DB for NSEC-only DNSKEY */
+ if (!nseconly)
+ CHECK(dns_nsec_nseconly(db, ver, &nseconly));
+
+ /* Check existing DB for NSEC3 */
+ if (!nsec3)
+ CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
+ privatetype, &nsec3));
+
+ /* Refuse to allow NSEC3 with NSEC-only keys */
+ if (nseconly && nsec3) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "NSEC only DNSKEYs and NSEC3 chains not allowed");
+ result = DNS_R_REFUSED;
+ goto failure;
}
+ /* Verify NSEC3 params */
+ CHECK(get_iterations(db, ver, privatetype, &iterations));
+ CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max));
+ if (max != 0 && iterations > max) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "too many NSEC3 iterations (%u) for "
+ "weakest DNSKEY (%u)", iterations, max);
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
failure:
- dns_diff_clear(&temp_diff);
return (result);
}
-#ifdef ALLOW_NSEC3PARAM_UPDATE
/*
* Delay NSEC3PARAM changes as they need to be applied to the whole zone.
*/
static isc_result_t
add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
- dns_name_t *name, dns_dbversion_t *ver, dns_diff_t *diff)
+ dns_dbversion_t *ver, dns_diff_t *diff)
{
isc_result_t result = ISC_R_SUCCESS;
dns_difftuple_t *tuple, *newtuple = NULL, *next;
dns_rdata_t rdata = DNS_RDATA_INIT;
- unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
dns_diff_t temp_diff;
dns_diffop_t op;
isc_boolean_t flag;
+ dns_name_t *name = dns_zone_getorigin(zone);
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
+ isc_uint32_t ttl = 0;
+ isc_boolean_t ttl_good = ISC_FALSE;
update_log(client, zone, ISC_LOG_DEBUG(3),
"checking for NSEC3PARAM changes");
@@ -3106,55 +3139,143 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
}
+ /*
+ * Extract TTL changes pairs, we don't need to convert these to
+ * delayed changes.
+ */
for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
tuple != NULL; tuple = next) {
-
if (tuple->op == DNS_DIFFOP_ADD) {
+ if (!ttl_good) {
+ /*
+ * Any adds here will contain the final
+ * NSEC3PARAM RRset TTL.
+ */
+ ttl = tuple->ttl;
+ ttl_good = ISC_TRUE;
+ }
+ /*
+ * Walk the temp_diff list looking for the
+ * corresponding delete.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ while (next != NULL) {
+ unsigned char *next_data = next->rdata.data;
+ unsigned char *tuple_data = tuple->rdata.data;
+ if (next->op == DNS_DIFFOP_DEL &&
+ next->rdata.length == tuple->rdata.length &&
+ !memcmp(next_data, tuple_data,
+ next->rdata.length)) {
+ ISC_LIST_UNLINK(temp_diff.tuples, next,
+ link);
+ ISC_LIST_APPEND(diff->tuples, next,
+ link);
+ break;
+ }
+ next = ISC_LIST_NEXT(next, link);
+ }
+ /*
+ * If we have not found a pair move onto the next
+ * tuple.
+ */
+ if (next == NULL) {
+ next = ISC_LIST_NEXT(tuple, link);
+ continue;
+ }
+ /*
+ * Find the next tuple to be processed before
+ * unlinking then complete moving the pair to 'diff'.
+ */
+ next = ISC_LIST_NEXT(tuple, link);
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ } else
next = ISC_LIST_NEXT(tuple, link);
+ }
+
+ /*
+ * Preserve any ongoing changes from a BIND 9.6.x upgrade.
+ *
+ * Any NSEC3PARAM records with flags other than OPTOUT named
+ * in managing and should not be touched so revert such changes
+ * taking into account any TTL change of the NSEC3PARAM RRset.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ next = ISC_LIST_NEXT(tuple, link);
+ if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
+ /*
+ * If we havn't had any adds then the tuple->ttl must
+ * be the original ttl and should be used for any
+ * future changes.
+ */
+ if (!ttl_good) {
+ ttl = tuple->ttl;
+ ttl_good = ISC_TRUE;
+ }
+ op = (tuple->op == DNS_DIFFOP_DEL) ?
+ DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
+ CHECK(dns_difftuple_create(diff->mctx, op, name,
+ ttl, &tuple->rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ dns_diff_appendminimal(diff, &tuple);
+ }
+ }
+
+ /*
+ * We now have just the actual changes to the NSEC3PARAM RRset.
+ * Convert the adds to delayed adds and the deletions into delayed
+ * deletions.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ /*
+ * If we havn't had any adds then the tuple->ttl must be the
+ * original ttl and should be used for any future changes.
+ */
+ if (!ttl_good) {
+ ttl = tuple->ttl;
+ ttl_good = ISC_TRUE;
+ }
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ /*
+ * Look for any deletes which match this ADD ignoring
+ * OPTOUT. We don't need to explictly remove them as
+ * they will be removed a side effect of processing
+ * the add.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
while (next != NULL) {
unsigned char *next_data = next->rdata.data;
unsigned char *tuple_data = tuple->rdata.data;
- if (next_data[0] != tuple_data[0] ||
- /* Ignore flags. */
+ if (next->op != DNS_DIFFOP_DEL ||
+ next->rdata.length != tuple->rdata.length ||
+ next_data[0] != tuple_data[0] ||
next_data[2] != tuple_data[2] ||
next_data[3] != tuple_data[3] ||
- next_data[4] != tuple_data[4] ||
- !memcmp(&next_data[5], &tuple_data[5],
- tuple_data[4])) {
+ memcmp(next_data + 4, tuple_data + 4,
+ tuple->rdata.length - 4)) {
next = ISC_LIST_NEXT(next, link);
continue;
}
- op = (next->op == DNS_DIFFOP_DEL) ?
- DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
- CHECK(dns_difftuple_create(diff->mctx, op,
- name, next->ttl,
- &next->rdata,
- &newtuple));
- CHECK(do_one_tuple(&newtuple, db, ver, diff));
ISC_LIST_UNLINK(temp_diff.tuples, next, link);
- dns_diff_appendminimal(diff, &next);
- next = ISC_LIST_NEXT(tuple, link);
+ ISC_LIST_APPEND(diff->tuples, next, link);
+ next = ISC_LIST_HEAD(temp_diff.tuples);
}
-
- INSIST(tuple->rdata.data[1] & DNS_NSEC3FLAG_UPDATE);
-
/*
* See if we already have a CREATE request in progress.
*/
- dns_rdata_clone(&tuple->rdata, &rdata);
- INSIST(rdata.length <= sizeof(buf));
- memcpy(buf, rdata.data, rdata.length);
- buf[1] |= DNS_NSEC3FLAG_CREATE;
- buf[1] &= ~DNS_NSEC3FLAG_UPDATE;
- rdata.data = buf;
-
+ dns_nsec3param_toprivate(&tuple->rdata, &rdata,
+ privatetype, buf, sizeof(buf));
+ buf[2] |= DNS_NSEC3FLAG_CREATE;
CHECK(rr_exists(db, ver, name, &rdata, &flag));
if (!flag) {
CHECK(dns_difftuple_create(diff->mctx,
DNS_DIFFOP_ADD,
- name, tuple->ttl,
- &rdata,
+ name, 0, &rdata,
&newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
}
@@ -3164,26 +3285,26 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
* otherwise indentical chain with a reversed
* OPTOUT state.
*/
- buf[1] ^= DNS_NSEC3FLAG_OPTOUT;
+ buf[2] ^= DNS_NSEC3FLAG_OPTOUT;
CHECK(rr_exists(db, ver, name, &rdata, &flag));
if (flag) {
CHECK(dns_difftuple_create(diff->mctx,
DNS_DIFFOP_DEL,
- name, tuple->ttl,
- &rdata,
+ name, 0, &rdata,
&newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
}
/*
- * Remove the temporary add record.
+ * Find the next tuple to be processed and remove the
+ * temporary add record.
*/
+ next = ISC_LIST_NEXT(tuple, link);
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
- name, tuple->ttl,
- &tuple->rdata, &newtuple));
+ name, ttl, &tuple->rdata,
+ &newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
- next = ISC_LIST_NEXT(tuple, link);
ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
dns_diff_appendminimal(diff, &tuple);
dns_rdata_reset(&rdata);
@@ -3191,50 +3312,33 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
next = ISC_LIST_NEXT(tuple, link);
}
- /*
- * Reverse any pending changes.
- */
for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
tuple != NULL; tuple = next) {
- next = ISC_LIST_NEXT(tuple, link);
- if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
- op = (tuple->op == DNS_DIFFOP_DEL) ?
- DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
- CHECK(dns_difftuple_create(diff->mctx, op, name,
- tuple->ttl, &tuple->rdata,
- &newtuple));
- CHECK(do_one_tuple(&newtuple, db, ver, diff));
- ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
- dns_diff_appendminimal(diff, &tuple);
- }
- }
- /*
- * Convert deletions into delayed deletions.
- */
- for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
- tuple != NULL; tuple = next) {
+ INSIST(ttl_good);
+
next = ISC_LIST_NEXT(tuple, link);
/*
* See if we already have a REMOVE request in progress.
*/
- dns_rdata_clone(&tuple->rdata, &rdata);
- INSIST(rdata.length <= sizeof(buf));
- memcpy(buf, rdata.data, rdata.length);
- buf[1] |= DNS_NSEC3FLAG_REMOVE;
- rdata.data = buf;
+ dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype,
+ buf, sizeof(buf));
+
+ buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ if (!flag) {
+ buf[2] &= ~DNS_NSEC3FLAG_NONSEC;
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+ }
if (!flag) {
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
- name, tuple->ttl, &rdata,
- &newtuple));
+ name, 0, &rdata, &newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
}
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
- tuple->ttl, &tuple->rdata,
- &newtuple));
+ ttl, &tuple->rdata, &newtuple));
CHECK(do_one_tuple(&newtuple, db, ver, diff));
ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
dns_diff_appendminimal(diff, &tuple);
@@ -3246,17 +3350,75 @@ add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_diff_clear(&temp_diff);
return (result);
}
-#endif
+
+static isc_result_t
+rollback_private(dns_db_t *db, dns_rdatatype_t privatetype,
+ dns_dbversion_t *ver, dns_diff_t *diff)
+{
+ dns_diff_t temp_diff;
+ dns_diffop_t op;
+ dns_difftuple_t *tuple, *newtuple = NULL, *next;
+ dns_name_t *name = dns_db_origin(db);
+ isc_mem_t *mctx = diff->mctx;
+ isc_result_t result;
+
+ if (privatetype == 0)
+ return (ISC_R_SUCCESS);
+
+ dns_diff_init(mctx, &temp_diff);
+
+ /*
+ * Extract the changes to be rolled back.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL; tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
+ if (tuple->rdata.type != privatetype ||
+ !dns_name_equal(name, &tuple->name))
+ continue;
+
+ /*
+ * Allow records which indicate that a zone has been
+ * signed with a DNSKEY to be be removed.
+ */
+ if (tuple->op == DNS_DIFFOP_DEL &&
+ tuple->rdata.length == 5 &&
+ tuple->rdata.data[0] != 0 &&
+ tuple->rdata.data[4] != 0)
+ continue;
+
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_PREPEND(temp_diff.tuples, tuple, link);
+ }
+
+ /*
+ * Rollback the changes.
+ */
+ while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) {
+ op = (tuple->op == DNS_DIFFOP_DEL) ?
+ DNS_DIFFOP_ADD : DNS_DIFFOP_DEL;
+ CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl,
+ &tuple->rdata, &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff));
+ }
+ result = ISC_R_SUCCESS;
+
+ failure:
+ dns_diff_clear(&temp_diff);
+ return (result);
+}
/*
* Add records to cause the delayed signing of the zone by added DNSKEY
* to remove the RRSIG records generated by a deleted DNSKEY.
*/
static isc_result_t
-add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver,
- dns_rdatatype_t privatetype, dns_diff_t *diff)
+add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
+ dns_dbversion_t *ver, dns_diff_t *diff)
{
- dns_difftuple_t *tuple, *newtuple = NULL;
+ dns_difftuple_t *tuple, *newtuple = NULL, *next;
dns_rdata_dnskey_t dnskey;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_boolean_t flag;
@@ -3264,13 +3426,82 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver,
isc_result_t result = ISC_R_SUCCESS;
isc_uint16_t keyid;
unsigned char buf[5];
+ dns_name_t *name = dns_db_origin(db);
+ dns_diff_t temp_diff;
+
+ dns_diff_init(diff->mctx, &temp_diff);
+ /*
+ * Extract the DNSKEY tuples from the list.
+ */
for (tuple = ISC_LIST_HEAD(diff->tuples);
- tuple != NULL;
- tuple = ISC_LIST_NEXT(tuple, link)) {
+ tuple != NULL; tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
if (tuple->rdata.type != dns_rdatatype_dnskey)
continue;
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
+ }
+
+ /*
+ * Extract TTL changes pairs, we don't need signing records for these.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ /*
+ * Walk the temp_diff list looking for the
+ * corresponding delete.
+ */
+ next = ISC_LIST_HEAD(temp_diff.tuples);
+ while (next != NULL) {
+ unsigned char *next_data = next->rdata.data;
+ unsigned char *tuple_data = tuple->rdata.data;
+ if (next->op == DNS_DIFFOP_DEL &&
+ dns_name_equal(&tuple->name, &next->name) &&
+ next->rdata.length == tuple->rdata.length &&
+ !memcmp(next_data, tuple_data,
+ next->rdata.length)) {
+ ISC_LIST_UNLINK(temp_diff.tuples, next,
+ link);
+ ISC_LIST_APPEND(diff->tuples, next,
+ link);
+ break;
+ }
+ next = ISC_LIST_NEXT(next, link);
+ }
+ /*
+ * If we have not found a pair move onto the next
+ * tuple.
+ */
+ if (next == NULL) {
+ next = ISC_LIST_NEXT(tuple, link);
+ continue;
+ }
+ /*
+ * Find the next tuple to be processed before
+ * unlinking then complete moving the pair to 'diff'.
+ */
+ next = ISC_LIST_NEXT(tuple, link);
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ } else
+ next = ISC_LIST_NEXT(tuple, link);
+ }
+
+ /*
+ * Process the remaining DNSKEY entries.
+ */
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_HEAD(temp_diff.tuples)) {
+
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+
dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
if ((dnskey.flags &
(DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
@@ -3278,6 +3509,7 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver,
continue;
dns_rdata_toregion(&tuple->rdata, &r);
+
keyid = dst_region_computeid(&r, dnskey.algorithm);
buf[0] = dnskey.algorithm;
@@ -3310,87 +3542,25 @@ add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver,
INSIST(newtuple == NULL);
}
}
+
failure:
+ dns_diff_clear(&temp_diff);
return (result);
}
-#ifdef ALLOW_NSEC3PARAM_UPDATE
-/*
- * Mark all NSEC3 chains for deletion without creating a NSEC chain as
- * a side effect of deleting the last chain.
- */
-static isc_result_t
-delete_chains(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
- dns_diff_t *diff)
-{
- dns_dbnode_t *node = NULL;
- dns_difftuple_t *tuple = NULL;
- dns_name_t next;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdataset_t rdataset;
- isc_boolean_t flag;
- isc_result_t result = ISC_R_SUCCESS;
- unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
-
- dns_name_init(&next, NULL);
- dns_rdataset_init(&rdataset);
-
- result = dns_db_getoriginnode(db, &node);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- /*
- * Cause all NSEC3 chains to be deleted.
- */
- result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
- 0, (isc_stdtime_t) 0, &rdataset, NULL);
- if (result == ISC_R_NOTFOUND)
- goto success;
- if (result != ISC_R_SUCCESS)
- goto failure;
-
- for (result = dns_rdataset_first(&rdataset);
- result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&rdataset)) {
- dns_rdataset_current(&rdataset, &rdata);
- INSIST(rdata.length <= sizeof(buf));
- memcpy(buf, rdata.data, rdata.length);
-
- if (buf[1] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) {
- dns_rdata_reset(&rdata);
- continue;
- }
-
- CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
- origin, 0, &rdata, &tuple));
- CHECK(do_one_tuple(&tuple, db, ver, diff));
- INSIST(tuple == NULL);
-
- buf[1] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
- rdata.data = buf;
-
- CHECK(rr_exists(db, ver, origin, &rdata, &flag));
+static isc_boolean_t
+isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) {
+ isc_result_t result;
+ isc_boolean_t build_nsec, build_nsec3;
- if (!flag) {
- CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
- origin, 0, &rdata, &tuple));
- CHECK(do_one_tuple(&tuple, db, ver, diff));
- INSIST(tuple == NULL);
- }
- dns_rdata_reset(&rdata);
- }
- if (result != ISC_R_NOMORE)
- goto failure;
- success:
- result = ISC_R_SUCCESS;
+ if (dns_db_issecure(db))
+ return (ISC_TRUE);
- failure:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- dns_db_detachnode(db, &node);
- return (result);
+ result = dns_private_chains(db, ver, privatetype,
+ &build_nsec, &build_nsec3);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ return (build_nsec || build_nsec3);
}
-#endif
static void
update_action(isc_task_t *task, isc_event_t *event) {
@@ -3414,15 +3584,10 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_fixedname_t tmpnamefixed;
dns_name_t *tmpname = NULL;
unsigned int options;
- isc_boolean_t deleted_zsk;
dns_difftuple_t *tuple;
dns_rdata_dnskey_t dnskey;
-#ifdef ALLOW_NSEC3PARAM_UPDATE
- unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
-#endif
-#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE)
isc_boolean_t had_dnskey;
-#endif
+ dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
INSIST(event->ev_type == DNS_EVENT_UPDATE);
@@ -3433,6 +3598,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
zonename = dns_db_origin(db);
zoneclass = dns_db_class(db);
dns_zone_getssutable(zone, &ssutable);
+
+ /*
+ * Update message processing can leak record existance information
+ * so check that we are allowed to query this zone. Additionally
+ * if we would refuse all updates for this zone we bail out here.
+ */
+ CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename,
+ dns_zone_getupdateacl(zone), ssutable));
+
+ /*
+ * Get old and new versions now that queryacl has been checked.
+ */
dns_db_currentversion(db, &oldver);
CHECK(dns_db_newversion(db, &ver));
@@ -3525,7 +3702,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
if (result != ISC_R_NOMORE)
FAIL(result);
-
/*
* Perform the final check of the "rrset exists (value dependent)"
* prerequisites.
@@ -3619,31 +3795,31 @@ update_action(isc_task_t *task, isc_event_t *event) {
update_class);
FAIL(DNS_R_FORMERR);
}
+
/*
* draft-ietf-dnsind-simple-secure-update-01 says
* "Unlike traditional dynamic update, the client
* is forbidden from updating NSEC records."
*/
- if (dns_db_issecure(db)) {
- if (rdata.type == dns_rdatatype_nsec3) {
- FAILC(DNS_R_REFUSED,
- "explicit NSEC3 updates are not allowed "
- "in secure zones");
- } else if (rdata.type == dns_rdatatype_nsec) {
- FAILC(DNS_R_REFUSED,
- "explicit NSEC updates are not allowed "
- "in secure zones");
- } else if (rdata.type == dns_rdatatype_rrsig &&
- !dns_name_equal(name, zonename)) {
- FAILC(DNS_R_REFUSED,
- "explicit RRSIG updates are currently "
- "not supported in secure zones except "
- "at the apex");
- }
+ if (rdata.type == dns_rdatatype_nsec3) {
+ FAILC(DNS_R_REFUSED,
+ "explicit NSEC3 updates are not allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_nsec) {
+ FAILC(DNS_R_REFUSED,
+ "explicit NSEC updates are not allowed "
+ "in secure zones");
+ } else if (rdata.type == dns_rdatatype_rrsig &&
+ !dns_name_equal(name, zonename)) {
+ FAILC(DNS_R_REFUSED,
+ "explicit RRSIG updates are currently "
+ "not supported in secure zones except "
+ "at the apex");
}
if (ssutable != NULL) {
isc_netaddr_t *tcpaddr, netaddr;
+ dst_key_t *tsigkey = NULL;
/*
* If this is a TCP connection then pass the
* address of the client through for tcp-self
@@ -3656,16 +3832,22 @@ update_action(isc_task_t *task, isc_event_t *event) {
tcpaddr = &netaddr;
} else
tcpaddr = NULL;
+
+ if (client->message->tsigkey != NULL)
+ tsigkey = client->message->tsigkey->key;
+
if (rdata.type != dns_rdatatype_any) {
if (!dns_ssutable_checkrules(ssutable,
client->signer,
name, tcpaddr,
- rdata.type))
+ rdata.type,
+ tsigkey))
FAILC(DNS_R_REFUSED,
"rejected by secure update");
} else {
if (!ssu_checkall(db, ver, name, ssutable,
- client->signer, tcpaddr))
+ client->signer, tcpaddr,
+ tsigkey))
FAILC(DNS_R_REFUSED,
"rejected by secure update");
}
@@ -3774,7 +3956,14 @@ update_action(isc_task_t *task, isc_event_t *event) {
soa_serial_changed = ISC_TRUE;
}
-#ifdef ALLOW_NSEC3PARAM_UPDATE
+ if (rdata.type == privatetype) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to add a private type "
+ "(%u) record rejected internal "
+ "use only", privatetype);
+ continue;
+ }
+
if (rdata.type == dns_rdatatype_nsec3param) {
/*
* Ignore attempts to add NSEC3PARAM records
@@ -3788,27 +3977,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
"flag");
continue;
}
-
- /*
- * Set the NSEC3CHAIN creation flag.
- */
- INSIST(rdata.length <= sizeof(buf));
- memcpy(buf, rdata.data, rdata.length);
- buf[1] |= DNS_NSEC3FLAG_UPDATE;
- rdata.data = buf;
- /*
- * Force the TTL to zero for NSEC3PARAM records.
- */
- ttl = 0;
}
-#else
- if (rdata.type == dns_rdatatype_nsec3param) {
- update_log(client, zone, LOGLEVEL_PROTOCOL,
- "attempt to add NSEC3PARAM "
- "record ignored");
- continue;
- };
-#endif
if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 &&
dns_name_internalwildcard(name)) {
@@ -3885,13 +4054,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_rdatatype_any, 0,
&rdata, &diff));
}
-#ifndef ALLOW_NSEC3PARAM_UPDATE
- } else if (rdata.type == dns_rdatatype_nsec3param) {
- update_log(client, zone, LOGLEVEL_PROTOCOL,
- "attempt to delete a NSEC3PARAM "
- "records ignored");
- continue;
-#endif
} else if (dns_name_equal(name, zonename) &&
(rdata.type == dns_rdatatype_soa ||
rdata.type == dns_rdatatype_ns)) {
@@ -3920,6 +4082,9 @@ update_action(isc_task_t *task, isc_event_t *event) {
&diff));
}
} else if (update_class == dns_rdataclass_none) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+
/*
* The (name == zonename) condition appears in
* RFC2136 3.4.2.4 but is missing from the pseudocode.
@@ -3947,11 +4112,13 @@ update_action(isc_task_t *task, isc_event_t *event) {
}
}
}
- update_log(client, zone,
- LOGLEVEL_PROTOCOL,
- "deleting an RR");
- CHECK(delete_if(rr_equal_p, db, ver, name,
- rdata.type, covers, &rdata, &diff));
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(rdata.type, typestr,
+ sizeof(typestr));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "deleting an RR at %s %s", namestr, typestr);
+ CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type,
+ covers, &rdata, &diff));
}
}
if (result != ISC_R_NOMORE)
@@ -3965,6 +4132,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
if (! ISC_LIST_EMPTY(diff.tuples))
CHECK(check_dnssec(client, zone, db, ver, &diff));
+ if (! ISC_LIST_EMPTY(diff.tuples)) {
+ unsigned int errors = 0;
+ CHECK(dns_zone_nscheck(zone, db, ver, &errors));
+ if (errors != 0) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update rejected: post update name server "
+ "sanity check failed");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+ }
+
/*
* If any changes were made, increment the SOA serial number,
* update RRSIGs and NSECs (if zone is secure), and write the update
@@ -3990,37 +4169,29 @@ update_action(isc_task_t *task, isc_event_t *event) {
CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey,
0, &has_dnskey));
-#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE)
- CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey,
- 0, &had_dnskey));
+#define ALLOW_SECURE_TO_INSECURE(zone) \
+ ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0)
-#ifndef ALLOW_SECURE_TO_INSECURE
- if (had_dnskey && !has_dnskey) {
- update_log(client, zone, LOGLEVEL_PROTOCOL,
- "update rejected: all DNSKEY records "
- "removed");
- result = DNS_R_REFUSED;
- goto failure;
- }
-#endif
-#ifndef ALLOW_INSECURE_TO_SECURE
- if (!had_dnskey && has_dnskey) {
- update_log(client, zone, LOGLEVEL_PROTOCOL,
- "update rejected: DNSKEY record added");
- result = DNS_R_REFUSED;
- goto failure;
+ if (!ALLOW_SECURE_TO_INSECURE(zone)) {
+ CHECK(rrset_exists(db, oldver, zonename,
+ dns_rdatatype_dnskey, 0,
+ &had_dnskey));
+ if (had_dnskey && !has_dnskey) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "update rejected: all DNSKEY "
+ "records removed and "
+ "'dnssec-secure-to-insecure' "
+ "not set");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
}
-#endif
-#endif
- CHECK(add_signing_records(db, zonename, ver,
- dns_zone_getprivatetype(zone),
- &diff));
+ CHECK(rollback_private(db, privatetype, ver, &diff));
+
+ CHECK(add_signing_records(db, privatetype, ver, &diff));
-#ifdef ALLOW_NSEC3PARAM_UPDATE
- CHECK(add_nsec3param_records(client, zone, db, zonename,
- ver, &diff));
-#endif
+ CHECK(add_nsec3param_records(client, zone, db, ver, &diff));
if (!has_dnskey) {
/*
@@ -4029,15 +4200,13 @@ update_action(isc_task_t *task, isc_event_t *event) {
* the last signature for the DNSKEY records are
* remove any NSEC chain present will also be removed.
*/
-#ifdef ALLOW_NSEC3PARAM_UPDATE
- CHECK(delete_chains(db, ver, zonename, &diff));
-#endif
- } else if (has_dnskey && dns_db_isdnssec(db)) {
+ CHECK(dns_nsec3param_deletechains(db, ver, zone,
+ &diff));
+ } else if (has_dnskey && isdnssec(db, ver, privatetype)) {
isc_uint32_t interval;
interval = dns_zone_getsigvalidityinterval(zone);
result = update_signatures(client, zone, db, oldver,
- ver, &diff, interval,
- &deleted_zsk);
+ ver, &diff, interval);
if (result != ISC_R_SUCCESS) {
update_log(client, zone,
ISC_LOG_ERROR,
@@ -4123,7 +4292,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
}
}
-#ifdef ALLOW_NSEC3PARAM_UPDATE
/*
* Cause the zone to add/delete NSEC3 chains for the
* deferred NSEC3PARAM changes.
@@ -4133,13 +4301,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
for (tuple = ISC_LIST_HEAD(diff.tuples);
tuple != NULL;
tuple = ISC_LIST_NEXT(tuple, link)) {
+ unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_nsec3param_t nsec3param;
- if (tuple->rdata.type != dns_rdatatype_nsec3param ||
+ if (tuple->rdata.type != privatetype ||
tuple->op != DNS_DIFFOP_ADD)
continue;
- dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL);
+ if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
+ buf, sizeof(buf)))
+ continue;
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
if (nsec3param.flags == 0)
continue;
@@ -4150,7 +4323,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
dns_result_totext(result));
}
}
-#endif
} else {
update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
dns_db_closeversion(db, &ver, ISC_TRUE);
diff --git a/contrib/bind9/bin/named/xfrout.c b/contrib/bind9/bin/named/xfrout.c
index e61dc72efda2..b036ed14d57f 100644
--- a/contrib/bind9/bin/named/xfrout.c
+++ b/contrib/bind9/bin/named/xfrout.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrout.c,v 1.131.26.6 2010-05-27 23:48:18 tbox Exp $ */
+/* $Id: xfrout.c,v 1.139 2010-12-18 01:56:19 each Exp $ */
#include <config.h>
@@ -40,6 +40,7 @@
#include <dns/rdataset.h>
#include <dns/rdatasetiter.h>
#include <dns/result.h>
+#include <dns/rriterator.h>
#include <dns/soa.h>
#include <dns/stats.h>
#include <dns/timer.h>
@@ -112,43 +113,6 @@
} while (0)
/**************************************************************************/
-/*%
- * A db_rr_iterator_t is an iterator that iterates over an entire database,
- * returning one RR at a time, in some arbitrary order.
- */
-
-typedef struct db_rr_iterator db_rr_iterator_t;
-
-/*% db_rr_iterator structure */
-struct db_rr_iterator {
- isc_result_t result;
- dns_db_t *db;
- dns_dbiterator_t *dbit;
- dns_dbversion_t *ver;
- isc_stdtime_t now;
- dns_dbnode_t *node;
- dns_fixedname_t fixedname;
- dns_rdatasetiter_t *rdatasetit;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata;
-};
-
-static isc_result_t
-db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
- isc_stdtime_t now);
-
-static isc_result_t
-db_rr_iterator_first(db_rr_iterator_t *it);
-
-static isc_result_t
-db_rr_iterator_next(db_rr_iterator_t *it);
-
-static void
-db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
- isc_uint32_t *ttl, dns_rdata_t **rdata);
-
-static void
-db_rr_iterator_destroy(db_rr_iterator_t *it);
static inline void
inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
@@ -160,145 +124,6 @@ inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
}
}
-static isc_result_t
-db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
- isc_stdtime_t now)
-{
- isc_result_t result;
- it->db = db;
- it->dbit = NULL;
- it->ver = ver;
- it->now = now;
- it->node = NULL;
- result = dns_db_createiterator(it->db, 0, &it->dbit);
- if (result != ISC_R_SUCCESS)
- return (result);
- it->rdatasetit = NULL;
- dns_rdata_init(&it->rdata);
- dns_rdataset_init(&it->rdataset);
- dns_fixedname_init(&it->fixedname);
- INSIST(! dns_rdataset_isassociated(&it->rdataset));
- it->result = ISC_R_SUCCESS;
- return (it->result);
-}
-
-static isc_result_t
-db_rr_iterator_first(db_rr_iterator_t *it) {
- it->result = dns_dbiterator_first(it->dbit);
- /*
- * The top node may be empty when out of zone glue exists.
- * Walk the tree to find the first node with data.
- */
- while (it->result == ISC_R_SUCCESS) {
- it->result = dns_dbiterator_current(it->dbit, &it->node,
- dns_fixedname_name(&it->fixedname));
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
-
- it->result = dns_db_allrdatasets(it->db, it->node,
- it->ver, it->now,
- &it->rdatasetit);
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
-
- it->result = dns_rdatasetiter_first(it->rdatasetit);
- if (it->result != ISC_R_SUCCESS) {
- /*
- * This node is empty. Try next node.
- */
- dns_rdatasetiter_destroy(&it->rdatasetit);
- dns_db_detachnode(it->db, &it->node);
- it->result = dns_dbiterator_next(it->dbit);
- continue;
- }
- dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
- it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
- it->result = dns_rdataset_first(&it->rdataset);
- return (it->result);
- }
- return (it->result);
-}
-
-
-static isc_result_t
-db_rr_iterator_next(db_rr_iterator_t *it) {
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
-
- INSIST(it->dbit != NULL);
- INSIST(it->node != NULL);
- INSIST(it->rdatasetit != NULL);
-
- it->result = dns_rdataset_next(&it->rdataset);
- if (it->result == ISC_R_NOMORE) {
- dns_rdataset_disassociate(&it->rdataset);
- it->result = dns_rdatasetiter_next(it->rdatasetit);
- /*
- * The while loop body is executed more than once
- * only when an empty dbnode needs to be skipped.
- */
- while (it->result == ISC_R_NOMORE) {
- dns_rdatasetiter_destroy(&it->rdatasetit);
- dns_db_detachnode(it->db, &it->node);
- it->result = dns_dbiterator_next(it->dbit);
- if (it->result == ISC_R_NOMORE) {
- /* We are at the end of the entire database. */
- return (it->result);
- }
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
- it->result = dns_dbiterator_current(it->dbit,
- &it->node,
- dns_fixedname_name(&it->fixedname));
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
- it->result = dns_db_allrdatasets(it->db, it->node,
- it->ver, it->now,
- &it->rdatasetit);
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
- it->result = dns_rdatasetiter_first(it->rdatasetit);
- }
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
- dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
- it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
- it->result = dns_rdataset_first(&it->rdataset);
- if (it->result != ISC_R_SUCCESS)
- return (it->result);
- }
- return (it->result);
-}
-
-static void
-db_rr_iterator_pause(db_rr_iterator_t *it) {
- RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
-}
-
-static void
-db_rr_iterator_destroy(db_rr_iterator_t *it) {
- if (dns_rdataset_isassociated(&it->rdataset))
- dns_rdataset_disassociate(&it->rdataset);
- if (it->rdatasetit != NULL)
- dns_rdatasetiter_destroy(&it->rdatasetit);
- if (it->node != NULL)
- dns_db_detachnode(it->db, &it->node);
- dns_dbiterator_destroy(&it->dbit);
-}
-
-static void
-db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
- isc_uint32_t *ttl, dns_rdata_t **rdata)
-{
- REQUIRE(name != NULL && *name == NULL);
- REQUIRE(it->result == ISC_R_SUCCESS);
- *name = dns_fixedname_name(&it->fixedname);
- *ttl = it->rdataset.ttl;
- dns_rdata_reset(&it->rdata);
- dns_rdataset_current(&it->rdataset, &it->rdata);
- *rdata = &it->rdata;
-}
-
/**************************************************************************/
/*% Log an RR (for debugging) */
@@ -488,7 +313,7 @@ static rrstream_methods_t ixfr_rrstream_methods = {
typedef struct axfr_rrstream {
rrstream_t common;
- db_rr_iterator_t it;
+ dns_rriterator_t it;
isc_boolean_t it_valid;
} axfr_rrstream_t;
@@ -516,7 +341,7 @@ axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
s->common.methods = &axfr_rrstream_methods;
s->it_valid = ISC_FALSE;
- CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
+ CHECK(dns_rriterator_init(&s->it, db, ver, 0));
s->it_valid = ISC_TRUE;
*sp = (rrstream_t *) s;
@@ -531,7 +356,7 @@ static isc_result_t
axfr_rrstream_first(rrstream_t *rs) {
axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
isc_result_t result;
- result = db_rr_iterator_first(&s->it);
+ result = dns_rriterator_first(&s->it);
if (result != ISC_R_SUCCESS)
return (result);
/* Skip SOA records. */
@@ -539,11 +364,11 @@ axfr_rrstream_first(rrstream_t *rs) {
dns_name_t *name_dummy = NULL;
isc_uint32_t ttl_dummy;
dns_rdata_t *rdata = NULL;
- db_rr_iterator_current(&s->it, &name_dummy,
- &ttl_dummy, &rdata);
+ dns_rriterator_current(&s->it, &name_dummy,
+ &ttl_dummy, NULL, &rdata);
if (rdata->type != dns_rdatatype_soa)
break;
- result = db_rr_iterator_next(&s->it);
+ result = dns_rriterator_next(&s->it);
if (result != ISC_R_SUCCESS)
break;
}
@@ -560,11 +385,11 @@ axfr_rrstream_next(rrstream_t *rs) {
dns_name_t *name_dummy = NULL;
isc_uint32_t ttl_dummy;
dns_rdata_t *rdata = NULL;
- result = db_rr_iterator_next(&s->it);
+ result = dns_rriterator_next(&s->it);
if (result != ISC_R_SUCCESS)
break;
- db_rr_iterator_current(&s->it, &name_dummy,
- &ttl_dummy, &rdata);
+ dns_rriterator_current(&s->it, &name_dummy,
+ &ttl_dummy, NULL, &rdata);
if (rdata->type != dns_rdatatype_soa)
break;
}
@@ -576,20 +401,20 @@ axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
dns_rdata_t **rdata)
{
axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
- db_rr_iterator_current(&s->it, name, ttl, rdata);
+ dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
}
static void
axfr_rrstream_pause(rrstream_t *rs) {
axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
- db_rr_iterator_pause(&s->it);
+ dns_rriterator_pause(&s->it);
}
static void
axfr_rrstream_destroy(rrstream_t **rsp) {
axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
if (s->it_valid)
- db_rr_iterator_destroy(&s->it);
+ dns_rriterator_destroy(&s->it);
isc_mem_put(s->common.mctx, s, sizeof(*s));
}
@@ -1038,6 +863,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
switch(dns_zone_gettype(zone)) {
case dns_zone_master:
case dns_zone_slave:
+ case dns_zone_dlz:
break; /* Master and slave zones are OK for transfer. */
default:
FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
diff --git a/contrib/bind9/bin/named/zoneconf.c b/contrib/bind9/bin/named/zoneconf.c
index 367ddd320d2c..eb93f1bbe45b 100644
--- a/contrib/bind9/bin/named/zoneconf.c
+++ b/contrib/bind9/bin/named/zoneconf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zoneconf.c,v 1.147.50.2 2009-01-29 23:47:44 tbox Exp $ */
+/* $Id: zoneconf.c,v 1.170 2011-01-06 23:47:00 tbox Exp $ */
/*% */
@@ -30,10 +30,16 @@
#include <isc/util.h>
#include <dns/acl.h>
+#include <dns/db.h>
#include <dns/fixedname.h>
#include <dns/log.h>
#include <dns/name.h>
+#include <dns/rdata.h>
#include <dns/rdatatype.h>
+#include <dns/rdataset.h>
+#include <dns/rdatalist.h>
+#include <dns/result.h>
+#include <dns/sdlz.h>
#include <dns/ssu.h>
#include <dns/stats.h>
#include <dns/view.h>
@@ -55,16 +61,18 @@ typedef enum {
allow_update_forwarding
} acl_type_t;
-/*%
- * These are BIND9 server defaults, not necessarily identical to the
- * library defaults defined in zone.c.
- */
#define RETERR(x) do { \
isc_result_t _r = (x); \
if (_r != ISC_R_SUCCESS) \
return (_r); \
} while (0)
+#define CHECK(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
/*%
* Convenience function for configuring a single zone ACL.
*/
@@ -133,8 +141,11 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
}
/* Check for default ACLs that haven't been parsed yet */
- if (vconfig != NULL)
- maps[i++] = cfg_tuple_get(vconfig, "options");
+ if (vconfig != NULL) {
+ const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
+ if (options != NULL)
+ maps[i++] = options;
+ }
if (config != NULL) {
const cfg_obj_t *options = NULL;
(void)cfg_map_get(config, "options", &options);
@@ -169,19 +180,29 @@ parse_acl:
* Parse the zone update-policy statement.
*/
static isc_result_t
-configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
+configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ const char *zname)
+{
const cfg_obj_t *updatepolicy = NULL;
const cfg_listelt_t *element, *element2;
dns_ssutable_t *table = NULL;
isc_mem_t *mctx = dns_zone_getmctx(zone);
+ isc_boolean_t autoddns = ISC_FALSE;
isc_result_t result;
(void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
+
if (updatepolicy == NULL) {
dns_zone_setssutable(zone, NULL);
return (ISC_R_SUCCESS);
}
+ if (cfg_obj_isstring(updatepolicy) &&
+ strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
+ autoddns = ISC_TRUE;
+ updatepolicy = NULL;
+ }
+
result = dns_ssutable_create(mctx, &table);
if (result != ISC_R_SUCCESS)
return (result);
@@ -198,6 +219,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
const char *str;
isc_boolean_t grant = ISC_FALSE;
+ isc_boolean_t usezone = ISC_FALSE;
unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
dns_fixedname_t fname, fident;
isc_buffer_t b;
@@ -237,6 +259,11 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
mtype = DNS_SSUMATCHTYPE_TCPSELF;
else if (strcasecmp(str, "6to4-self") == 0)
mtype = DNS_SSUMATCHTYPE_6TO4SELF;
+ else if (strcasecmp(str, "zonesub") == 0) {
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
+ usezone = ISC_TRUE;
+ } else if (strcasecmp(str, "external") == 0)
+ mtype = DNS_SSUMATCHTYPE_EXTERNAL;
else
INSIST(0);
@@ -245,7 +272,7 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
"'%s' is not a valid name", str);
@@ -253,15 +280,27 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
}
dns_fixedname_init(&fname);
- str = cfg_obj_asstring(dname);
- isc_buffer_init(&b, str, strlen(str));
- isc_buffer_add(&b, strlen(str));
- result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
- dns_rootname, ISC_FALSE, NULL);
- if (result != ISC_R_SUCCESS) {
- cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
- "'%s' is not a valid name", str);
- goto cleanup;
+ if (usezone) {
+ result = dns_name_copy(dns_zone_getorigin(zone),
+ dns_fixedname_name(&fname),
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "error copying origin: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ } else {
+ str = cfg_obj_asstring(dname);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(dns_fixedname_name(&fname),
+ &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
}
n = ns_config_listcount(typelist);
@@ -311,7 +350,34 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
+ }
+
+ /*
+ * If "update-policy local;" and a session key exists,
+ * then use the default policy, which is equivalent to:
+ * update-policy { grant <session-keyname> zonesub any; };
+ */
+ if (autoddns) {
+ dns_rdatatype_t any = dns_rdatatype_any;
+
+ if (ns_g_server->session_keyname == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "failed to enable auto DDNS policy "
+ "for zone %s: session key not found",
+ zname);
+ result = ISC_R_NOTFOUND;
+ goto cleanup;
+ }
+ result = dns_ssutable_addrule(table, ISC_TRUE,
+ ns_g_server->session_keyname,
+ DNS_SSUMATCHTYPE_SUBDOMAIN,
+ dns_zone_getorigin(zone),
+ 1, &any);
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
}
result = ISC_R_SUCCESS;
@@ -322,6 +388,323 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
return (result);
}
+/*
+ * This is the TTL used for internally generated RRsets for static-stub zones.
+ * The value doesn't matter because the mapping is static, but needs to be
+ * defined for the sake of implementation.
+ */
+#define STATICSTUB_SERVER_TTL 86400
+
+/*%
+ * Configure an apex NS with glues for a static-stub zone.
+ * For example, for the zone named "example.com", the following RRs will be
+ * added to the zone DB:
+ * example.com. NS example.com.
+ * example.com. A 192.0.2.1
+ * example.com. AAAA 2001:db8::1
+ */
+static isc_result_t
+configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ dns_rdatalist_t *rdatalist_ns,
+ dns_rdatalist_t *rdatalist_a,
+ dns_rdatalist_t *rdatalist_aaaa)
+{
+ const cfg_listelt_t *element;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ isc_region_t region, sregion;
+ dns_rdata_t *rdata;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (element = cfg_list_first(zconfig);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const isc_sockaddr_t* sa;
+ isc_netaddr_t na;
+ const cfg_obj_t *address = cfg_listelt_value(element);
+ dns_rdatalist_t *rdatalist;
+
+ sa = cfg_obj_assockaddr(address);
+ if (isc_sockaddr_getport(sa) != 0) {
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "port is not configurable for "
+ "static stub server-addresses");
+ return (ISC_R_FAILURE);
+ }
+ isc_netaddr_fromsockaddr(&na, sa);
+ if (isc_netaddr_getzone(&na) != 0) {
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "scoped address is not allowed "
+ "for static stub "
+ "server-addresses");
+ return (ISC_R_FAILURE);
+ }
+
+ switch (na.family) {
+ case AF_INET:
+ region.length = sizeof(na.type.in);
+ rdatalist = rdatalist_a;
+ break;
+ default:
+ INSIST(na.family == AF_INET6);
+ region.length = sizeof(na.type.in6);
+ rdatalist = rdatalist_aaaa;
+ break;
+ }
+
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+ region.base = (unsigned char *)(rdata + 1);
+ memcpy(region.base, &na.type, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
+ rdatalist->type, &region);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ }
+
+ /*
+ * If no address is specified (unlikely in this context, but possible),
+ * there's nothing to do anymore.
+ */
+ if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
+ ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Add to the list an apex NS with the ns name being the origin name */
+ dns_name_toregion(dns_zone_getorigin(zone), &sregion);
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
+ if (rdata == NULL) {
+ /*
+ * Already allocated data will be freed in the caller, so
+ * we can simply return here.
+ */
+ return (ISC_R_NOMEMORY);
+ }
+ region.length = sregion.length;
+ region.base = (unsigned char *)(rdata + 1);
+ memcpy(region.base, sregion.base, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
+ dns_rdatatype_ns, &region);
+ ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
+
+ return (result);
+}
+
+/*%
+ * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
+ * For example, for the zone named "example.com", something like the following
+ * RRs will be added to the zone DB:
+ * example.com. NS ns.example.net.
+ */
+static isc_result_t
+configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ dns_rdatalist_t *rdatalist, const char *zname)
+{
+ const cfg_listelt_t *element;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_rdata_t *rdata;
+ isc_region_t sregion, region;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (element = cfg_list_first(zconfig);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *obj;
+ const char *str;
+ dns_fixedname_t fixed_name;
+ dns_name_t *nsname;
+ isc_buffer_t b;
+
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(obj);
+
+ dns_fixedname_init(&fixed_name);
+ nsname = dns_fixedname_name(&fixed_name);
+
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "server-name '%s' is not a valid "
+ "name", str);
+ return (result);
+ }
+ if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "server-name '%s' must not be a "
+ "subdomain of zone name '%s'",
+ str, zname);
+ return (ISC_R_FAILURE);
+ }
+
+ dns_name_toregion(nsname, &sregion);
+ rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+ region.length = sregion.length;
+ region.base = (unsigned char *)(rdata + 1);
+ memcpy(region.base, sregion.base, region.length);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
+ dns_rdatatype_ns, &region);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ }
+
+ return (result);
+}
+
+/*%
+ * Configure static-stub zone.
+ */
+static isc_result_t
+configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
+ const char *zname, const char *dbtype)
+{
+ int i = 0;
+ const cfg_obj_t *obj;
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_db_t *db = NULL;
+ dns_dbversion_t *dbversion = NULL;
+ dns_dbnode_t *apexnode = NULL;
+ dns_name_t apexname;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
+ dns_rdatalist_t* rdatalists[] = {
+ &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL
+ };
+ dns_rdata_t *rdata;
+ isc_region_t region;
+
+ /* Create the DB beforehand */
+ RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
+ dns_dbtype_stub, dns_zone_getclass(zone),
+ 0, NULL, &db));
+ dns_zone_setdb(zone, db);
+
+ dns_rdatalist_init(&rdatalist_ns);
+ rdatalist_ns.rdclass = dns_zone_getclass(zone);
+ rdatalist_ns.type = dns_rdatatype_ns;
+ rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
+
+ dns_rdatalist_init(&rdatalist_a);
+ rdatalist_a.rdclass = dns_zone_getclass(zone);
+ rdatalist_a.type = dns_rdatatype_a;
+ rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
+
+ dns_rdatalist_init(&rdatalist_aaaa);
+ rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
+ rdatalist_aaaa.type = dns_rdatatype_aaaa;
+ rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
+
+ /* Prepare zone RRs from the configuration */
+ obj = NULL;
+ result = cfg_map_get(zconfig, "server-addresses", &obj);
+ if (obj != NULL) {
+ result = configure_staticstub_serveraddrs(obj, zone,
+ &rdatalist_ns,
+ &rdatalist_a,
+ &rdatalist_aaaa);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ obj = NULL;
+ result = cfg_map_get(zconfig, "server-names", &obj);
+ if (obj != NULL) {
+ result = configure_staticstub_servernames(obj, zone,
+ &rdatalist_ns,
+ zname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ /*
+ * Sanity check: there should be at least one NS RR at the zone apex
+ * to trigger delegation.
+ */
+ if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "No NS record is configured for a "
+ "static-stub zone '%s'", zname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /*
+ * Now add NS and glue A/AAAA RRsets to the zone DB.
+ * First open a new version for the add operation and get a pointer
+ * to the apex node (all RRs are of the apex name).
+ */
+ result = dns_db_newversion(db, &dbversion);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_name_init(&apexname, NULL);
+ dns_name_clone(dns_zone_getorigin(zone), &apexname);
+ result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add NS RRset */
+ dns_rdataset_init(&rdataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
+ 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add glue A RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0,
+ &rdataset, 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ /* Add glue AAAA RRset, if any */
+ if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa,
+ &rdataset)
+ == ISC_R_SUCCESS);
+ result = dns_db_addrdataset(db, apexnode, dbversion, 0,
+ &rdataset, 0, NULL);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (apexnode != NULL)
+ dns_db_detachnode(db, &apexnode);
+ if (dbversion != NULL)
+ dns_db_closeversion(db, &dbversion, ISC_TRUE);
+ if (db != NULL)
+ dns_db_detach(&db);
+ for (i = 0; rdatalists[i] != NULL; i++) {
+ while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
+ ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
+ dns_rdata_toregion(rdata, &region);
+ isc_mem_put(mctx, rdata,
+ sizeof(*rdata) + region.length);
+ }
+ }
+
+ return (result);
+}
+
/*%
* Convert a config file zone type into a server zone type.
*/
@@ -503,6 +886,19 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
if (result == ISC_R_SUCCESS)
filename = cfg_obj_asstring(obj);
+ /*
+ * Unless we're using some alternative database, a master zone
+ * will be needing a master file.
+ */
+ if (ztype == dns_zone_master && cpval == default_dbtype &&
+ filename == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'file' not specified",
+ zname);
+ return (ISC_R_FAILURE);
+ }
+
masterformat = dns_masterformat_text;
obj = NULL;
result= ns_config_get(maps, "masterfile-format", &obj);
@@ -577,7 +973,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
* to primary masters (type "master") and slaves
* acting as masters (type "slave"), but not to stubs.
*/
- if (ztype != dns_zone_stub) {
+ if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) {
obj = NULL;
result = ns_config_get(maps, "notify", &obj);
INSIST(result == ISC_R_SUCCESS);
@@ -731,6 +1127,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
*/
if (ztype == dns_zone_master) {
dns_acl_t *updateacl;
+
RETERR(configure_zone_acl(zconfig, vconfig, config,
allow_update, ac, zone,
dns_zone_setupdateacl,
@@ -744,7 +1141,7 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
"address, which is insecure",
zname);
- RETERR(configure_zone_ssutable(zoptions, zone));
+ RETERR(configure_zone_ssutable(zoptions, zone, zname));
obj = NULL;
result = ns_config_get(maps, "sig-validity-interval", &obj);
@@ -774,12 +1171,6 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
result = ns_config_get(maps, "key-directory", &obj);
if (result == ISC_R_SUCCESS) {
filename = cfg_obj_asstring(obj);
- if (!isc_file_isabsolute(filename)) {
- cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
- "key-directory '%s' "
- "is not absolute", filename);
- return (ISC_R_FAILURE);
- }
RETERR(dns_zone_setkeydirectory(zone, filename));
}
@@ -804,6 +1195,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
cfg_obj_asboolean(obj));
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
+ cfg_obj_asboolean(obj));
} else if (ztype == dns_zone_slave) {
RETERR(configure_zone_acl(zconfig, vconfig, config,
allow_update_forwarding, ac, zone,
@@ -811,11 +1207,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
dns_zone_clearforwardacl));
}
-
/*%
* Primary master functionality.
*/
if (ztype == dns_zone_master) {
+ isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;
+ isc_boolean_t create = ISC_FALSE;
+
obj = NULL;
result = ns_config_get(maps, "check-wildcard", &obj);
if (result == ISC_R_SUCCESS)
@@ -825,6 +1223,21 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);
obj = NULL;
+ result = ns_config_get(maps, "check-dup-records", &obj);
+ INSIST(obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ fail = ISC_FALSE;
+ check = ISC_TRUE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ fail = check = ISC_TRUE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ fail = check = ISC_FALSE;
+ } else
+ INSIST(0);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
+
+ obj = NULL;
result = ns_config_get(maps, "check-mx", &obj);
INSIST(obj != NULL);
if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
@@ -874,6 +1287,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
INSIST(0);
dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
+ INSIST(obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "auto-dnssec", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *arg = cfg_obj_asstring(obj);
+ if (strcasecmp(arg, "allow") == 0)
+ allow = ISC_TRUE;
+ else if (strcasecmp(arg, "maintain") == 0)
+ allow = maint = ISC_TRUE;
+ else if (strcasecmp(arg, "create") == 0)
+ allow = maint = create = ISC_TRUE;
+ else if (strcasecmp(arg, "off") == 0)
+ ;
+ else
+ INSIST(0);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
+ dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, create);
+ }
}
/*
@@ -982,6 +1420,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
cfg_obj_asboolean(obj));
break;
+ case dns_zone_staticstub:
+ RETERR(configure_staticstub(zoptions, zone, zname,
+ default_dbtype));
+ break;
+
default:
break;
}
@@ -989,6 +1432,31 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
return (ISC_R_SUCCESS);
}
+
+#ifdef DLZ
+/*
+ * Set up a DLZ zone as writeable
+ */
+isc_result_t
+ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
+ dns_rdataclass_t rdclass, dns_name_t *name)
+{
+ dns_db_t *db = NULL;
+ isc_time_t now;
+ isc_result_t result;
+
+ TIME_NOW(&now);
+
+ dns_zone_settype(zone, dns_zone_dlz);
+ result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
+ if (result != ISC_R_SUCCESS)
+ return result;
+ result = dns_zone_dlzpostload(zone, db);
+ dns_db_detach(&db);
+ return result;
+}
+#endif
+
isc_boolean_t
ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
const cfg_obj_t *zoptions = NULL;
@@ -1001,6 +1469,13 @@ ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone))
return (ISC_FALSE);
+ /*
+ * We always reconfigure a static-stub zone for simplicity, assuming
+ * the amount of data to be loaded is small.
+ */
+ if (zonetype_fromconfig(zoptions) == dns_zone_staticstub)
+ return (ISC_FALSE);
+
obj = NULL;
(void)cfg_map_get(zoptions, "file", &obj);
if (obj != NULL)