summaryrefslogtreecommitdiffstats
path: root/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch')
-rw-r--r--meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch1090
1 files changed, 0 insertions, 1090 deletions
diff --git a/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch b/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch
deleted file mode 100644
index 75bc211cb6..0000000000
--- a/meta/recipes-connectivity/bind/bind/CVE-2016-6170.patch
+++ /dev/null
@@ -1,1090 +0,0 @@
-From 1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f Mon Sep 17 00:00:00 2001
-From: Mark Andrews <marka@isc.org>
-Date: Wed, 2 Nov 2016 17:31:27 +1100
-Subject: [PATCH] 4504. [security] Allow the maximum number of records in a
- zone to be specified. This provides a control for issues raised in
- CVE-2016-6170. [RT #42143]
-
-(cherry picked from commit 5f8412a4cb5ee14a0e8cddd4107854b40ee3291e)
-
-Upstream-Status: Backport
-[https://source.isc.org/cgi-bin/gitweb.cgi?p=bind9.git;a=commit;h=1bbcfe2fc84f57b1e4e075fb3bc2a1dd0a3a851f]
-
-CVE: CVE-2016-6170
-
-Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
----
- CHANGES | 4 +
- bin/named/config.c | 1 +
- bin/named/named.conf.docbook | 3 +
- bin/named/update.c | 16 +++
- bin/named/zoneconf.c | 7 ++
- bin/tests/system/nsupdate/clean.sh | 1 +
- bin/tests/system/nsupdate/ns3/named.conf | 7 ++
- bin/tests/system/nsupdate/ns3/too-big.test.db.in | 10 ++
- bin/tests/system/nsupdate/setup.sh | 2 +
- bin/tests/system/nsupdate/tests.sh | 15 +++
- bin/tests/system/xfer/clean.sh | 1 +
- bin/tests/system/xfer/ns1/axfr-too-big.db | 10 ++
- bin/tests/system/xfer/ns1/ixfr-too-big.db.in | 13 +++
- bin/tests/system/xfer/ns1/named.conf | 11 ++
- bin/tests/system/xfer/ns6/named.conf | 14 +++
- bin/tests/system/xfer/setup.sh | 2 +
- bin/tests/system/xfer/tests.sh | 26 +++++
- doc/arm/Bv9ARM-book.xml | 21 ++++
- doc/arm/notes.xml | 9 ++
- lib/bind9/check.c | 2 +
- lib/dns/db.c | 13 +++
- lib/dns/ecdb.c | 3 +-
- lib/dns/include/dns/db.h | 20 ++++
- lib/dns/include/dns/rdataslab.h | 13 +++
- lib/dns/include/dns/result.h | 6 +-
- lib/dns/include/dns/zone.h | 28 ++++-
- lib/dns/rbtdb.c | 127 +++++++++++++++++++++--
- lib/dns/rdataslab.c | 13 +++
- lib/dns/result.c | 9 +-
- lib/dns/sdb.c | 3 +-
- lib/dns/sdlz.c | 3 +-
- lib/dns/xfrin.c | 22 +++-
- lib/dns/zone.c | 23 +++-
- lib/isccfg/namedconf.c | 1 +
- 34 files changed, 444 insertions(+), 15 deletions(-)
- create mode 100644 bin/tests/system/nsupdate/ns3/too-big.test.db.in
- create mode 100644 bin/tests/system/xfer/ns1/axfr-too-big.db
- create mode 100644 bin/tests/system/xfer/ns1/ixfr-too-big.db.in
-
-diff --git a/CHANGES b/CHANGES
-index 41cfce5..97d2e60 100644
---- a/CHANGES
-+++ b/CHANGES
-@@ -1,3 +1,7 @@
-+4504. [security] Allow the maximum number of records in a zone to
-+ be specified. This provides a control for issues
-+ raised in CVE-2016-6170. [RT #42143]
-+
- 4489. [security] It was possible to trigger assertions when processing
- a response. (CVE-2016-8864) [RT #43465]
-
-diff --git a/bin/named/config.c b/bin/named/config.c
-index f06348c..c24e334 100644
---- a/bin/named/config.c
-+++ b/bin/named/config.c
-@@ -209,6 +209,7 @@ options {\n\
- max-transfer-time-out 120;\n\
- max-transfer-idle-in 60;\n\
- max-transfer-idle-out 60;\n\
-+ max-records 0;\n\
- max-retry-time 1209600; /* 2 weeks */\n\
- min-retry-time 500;\n\
- max-refresh-time 2419200; /* 4 weeks */\n\
-diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook
-index 4c99a61..c2d173a 100644
---- a/bin/named/named.conf.docbook
-+++ b/bin/named/named.conf.docbook
-@@ -338,6 +338,7 @@ options {
- };
-
- max-journal-size <replaceable>size_no_default</replaceable>;
-+ max-records <replaceable>integer</replaceable>;
- max-transfer-time-in <replaceable>integer</replaceable>;
- max-transfer-time-out <replaceable>integer</replaceable>;
- max-transfer-idle-in <replaceable>integer</replaceable>;
-@@ -527,6 +528,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
- };
-
- max-journal-size <replaceable>size_no_default</replaceable>;
-+ max-records <replaceable>integer</replaceable>;
- max-transfer-time-in <replaceable>integer</replaceable>;
- max-transfer-time-out <replaceable>integer</replaceable>;
- max-transfer-idle-in <replaceable>integer</replaceable>;
-@@ -624,6 +626,7 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
- };
-
- max-journal-size <replaceable>size_no_default</replaceable>;
-+ max-records <replaceable>integer</replaceable>;
- max-transfer-time-in <replaceable>integer</replaceable>;
- max-transfer-time-out <replaceable>integer</replaceable>;
- max-transfer-idle-in <replaceable>integer</replaceable>;
-diff --git a/bin/named/update.c b/bin/named/update.c
-index 83b1a05..cc2a611 100644
---- a/bin/named/update.c
-+++ b/bin/named/update.c
-@@ -2455,6 +2455,8 @@ update_action(isc_task_t *task, isc_event_t *event) {
- isc_boolean_t had_dnskey;
- dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
- dns_ttl_t maxttl = 0;
-+ isc_uint32_t maxrecords;
-+ isc_uint64_t records;
-
- INSIST(event->ev_type == DNS_EVENT_UPDATE);
-
-@@ -3138,6 +3140,20 @@ update_action(isc_task_t *task, isc_event_t *event) {
- }
- }
-
-+ maxrecords = dns_zone_getmaxrecords(zone);
-+ if (maxrecords != 0U) {
-+ result = dns_db_getsize(db, ver, &records, NULL);
-+ if (result == ISC_R_SUCCESS && records > maxrecords) {
-+ update_log(client, zone, ISC_LOG_ERROR,
-+ "records in zone (%"
-+ ISC_PRINT_QUADFORMAT
-+ "u) exceeds max-records (%u)",
-+ records, maxrecords);
-+ result = DNS_R_TOOMANYRECORDS;
-+ goto failure;
-+ }
-+ }
-+
- journalfile = dns_zone_getjournal(zone);
- if (journalfile != NULL) {
- update_log(client, zone, LOGLEVEL_DEBUG,
-diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
-index 4ee3dfe..14dd8ce 100644
---- a/bin/named/zoneconf.c
-+++ b/bin/named/zoneconf.c
-@@ -978,6 +978,13 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
- dns_zone_setmaxttl(raw, maxttl);
- }
-
-+ obj = NULL;
-+ result = ns_config_get(maps, "max-records", &obj);
-+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
-+ dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj));
-+ if (zone != mayberaw)
-+ dns_zone_setmaxrecords(zone, 0);
-+
- if (raw != NULL && filename != NULL) {
- #define SIGNED ".signed"
- size_t signedlen = strlen(filename) + sizeof(SIGNED);
-diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh
-index aaefc02..ea25545 100644
---- a/bin/tests/system/nsupdate/clean.sh
-+++ b/bin/tests/system/nsupdate/clean.sh
-@@ -32,6 +32,7 @@ rm -f ns3/example.db.jnl ns3/example.db
- rm -f ns3/nsec3param.test.db.signed.jnl ns3/nsec3param.test.db ns3/nsec3param.test.db.signed ns3/dsset-nsec3param.test.
- rm -f ns3/dnskey.test.db.signed.jnl ns3/dnskey.test.db ns3/dnskey.test.db.signed ns3/dsset-dnskey.test.
- rm -f ns3/K*
-+rm -f ns3/too-big.test.db
- rm -f dig.out.*
- rm -f jp.out.ns3.*
- rm -f Kxxx.*
-diff --git a/bin/tests/system/nsupdate/ns3/named.conf b/bin/tests/system/nsupdate/ns3/named.conf
-index 2abd522..68ff27a 100644
---- a/bin/tests/system/nsupdate/ns3/named.conf
-+++ b/bin/tests/system/nsupdate/ns3/named.conf
-@@ -60,3 +60,10 @@ zone "dnskey.test" {
- allow-update { any; };
- file "dnskey.test.db.signed";
- };
-+
-+zone "too-big.test" {
-+ type master;
-+ allow-update { any; };
-+ max-records 3;
-+ file "too-big.test.db";
-+};
-diff --git a/bin/tests/system/nsupdate/ns3/too-big.test.db.in b/bin/tests/system/nsupdate/ns3/too-big.test.db.in
-new file mode 100644
-index 0000000..7ff1e4a
---- /dev/null
-+++ b/bin/tests/system/nsupdate/ns3/too-big.test.db.in
-@@ -0,0 +1,10 @@
-+; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
-+;
-+; This Source Code Form is subject to the terms of the Mozilla Public
-+; License, v. 2.0. If a copy of the MPL was not distributed with this
-+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+$TTL 10
-+too-big.test. IN SOA too-big.test. hostmaster.too-big.test. 1 3600 900 2419200 3600
-+too-big.test. IN NS too-big.test.
-+too-big.test. IN A 10.53.0.3
-diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh
-index 828255e..43c4094 100644
---- a/bin/tests/system/nsupdate/setup.sh
-+++ b/bin/tests/system/nsupdate/setup.sh
-@@ -27,12 +27,14 @@ test -r $RANDFILE || $GENRANDOM 400 $RANDFILE
- rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk
- rm -f ns2/update.bk ns2/update.alt.bk
- rm -f ns3/example.db.jnl
-+rm -f ns3/too-big.test.db.jnl
-
- cp -f ns1/example1.db ns1/example.db
- sed 's/example.nil/other.nil/g' ns1/example1.db > ns1/other.db
- sed 's/example.nil/unixtime.nil/g' ns1/example1.db > ns1/unixtime.db
- sed 's/example.nil/keytests.nil/g' ns1/example1.db > ns1/keytests.db
- cp -f ns3/example.db.in ns3/example.db
-+cp -f ns3/too-big.test.db.in ns3/too-big.test.db
-
- # update_test.pl has its own zone file because it
- # requires a specific NS record set.
-diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
-index 78d501e..0a6bbd3 100755
---- a/bin/tests/system/nsupdate/tests.sh
-+++ b/bin/tests/system/nsupdate/tests.sh
-@@ -581,5 +581,20 @@ if [ $ret -ne 0 ]; then
- status=1
- fi
-
-+n=`expr $n + 1`
-+echo "I:check that adding too many records is blocked ($n)"
-+ret=0
-+$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 && ret=1
-+server 10.53.0.3 5300
-+zone too-big.test.
-+update add r1.too-big.test 3600 IN TXT r1.too-big.test
-+send
-+EOF
-+grep "update failed: SERVFAIL" nsupdate.out-$n > /dev/null || ret=1
-+DIG +tcp @10.53.0.3 -p 5300 r1.too-big.test TXT > dig.out.ns3.test$n
-+grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
-+grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1
-+[ $ret = 0 ] || { echo I:failed; status=1; }
-+
- echo "I:exit status: $status"
- exit $status
-diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh
-index 48aa159..da62a33 100644
---- a/bin/tests/system/xfer/clean.sh
-+++ b/bin/tests/system/xfer/clean.sh
-@@ -36,3 +36,4 @@ rm -f ns7/*.db ns7/*.bk ns7/*.jnl
- rm -f */named.memstats
- rm -f */named.run
- rm -f */ans.run
-+rm -f ns1/ixfr-too-big.db ns1/ixfr-too-big.db.jnl
-diff --git a/bin/tests/system/xfer/ns1/axfr-too-big.db b/bin/tests/system/xfer/ns1/axfr-too-big.db
-new file mode 100644
-index 0000000..d43760d
---- /dev/null
-+++ b/bin/tests/system/xfer/ns1/axfr-too-big.db
-@@ -0,0 +1,10 @@
-+; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
-+;
-+; This Source Code Form is subject to the terms of the Mozilla Public
-+; License, v. 2.0. If a copy of the MPL was not distributed with this
-+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+$TTL 3600
-+@ IN SOA . . 0 0 0 0 0
-+@ IN NS .
-+$GENERATE 1-29 host$ A 1.2.3.$
-diff --git a/bin/tests/system/xfer/ns1/ixfr-too-big.db.in b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
-new file mode 100644
-index 0000000..318bb77
---- /dev/null
-+++ b/bin/tests/system/xfer/ns1/ixfr-too-big.db.in
-@@ -0,0 +1,13 @@
-+; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
-+;
-+; This Source Code Form is subject to the terms of the Mozilla Public
-+; License, v. 2.0. If a copy of the MPL was not distributed with this
-+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+$TTL 3600
-+@ IN SOA . . 0 0 0 0 0
-+@ IN NS ns1
-+@ IN NS ns6
-+ns1 IN A 10.53.0.1
-+ns6 IN A 10.53.0.6
-+$GENERATE 1-25 host$ A 1.2.3.$
-diff --git a/bin/tests/system/xfer/ns1/named.conf b/bin/tests/system/xfer/ns1/named.conf
-index 07dad85..1d29292 100644
---- a/bin/tests/system/xfer/ns1/named.conf
-+++ b/bin/tests/system/xfer/ns1/named.conf
-@@ -44,3 +44,14 @@ zone "slave" {
- type master;
- file "slave.db";
- };
-+
-+zone "axfr-too-big" {
-+ type master;
-+ file "axfr-too-big.db";
-+};
-+
-+zone "ixfr-too-big" {
-+ type master;
-+ allow-update { any; };
-+ file "ixfr-too-big.db";
-+};
-diff --git a/bin/tests/system/xfer/ns6/named.conf b/bin/tests/system/xfer/ns6/named.conf
-index c9421b1..a12a92c 100644
---- a/bin/tests/system/xfer/ns6/named.conf
-+++ b/bin/tests/system/xfer/ns6/named.conf
-@@ -52,3 +52,17 @@ zone "slave" {
- masters { 10.53.0.1; };
- file "slave.bk";
- };
-+
-+zone "axfr-too-big" {
-+ type slave;
-+ max-records 30;
-+ masters { 10.53.0.1; };
-+ file "axfr-too-big.bk";
-+};
-+
-+zone "ixfr-too-big" {
-+ type slave;
-+ max-records 30;
-+ masters { 10.53.0.1; };
-+ file "ixfr-too-big.bk";
-+};
-diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh
-index 56ca901..c55abf8 100644
---- a/bin/tests/system/xfer/setup.sh
-+++ b/bin/tests/system/xfer/setup.sh
-@@ -33,3 +33,5 @@ cp -f ns4/named.conf.base ns4/named.conf
-
- cp ns2/slave.db.in ns2/slave.db
- touch -t 200101010000 ns2/slave.db
-+
-+cp -f ns1/ixfr-too-big.db.in ns1/ixfr-too-big.db
-diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh
-index 67b2a1a..fe33f0a 100644
---- a/bin/tests/system/xfer/tests.sh
-+++ b/bin/tests/system/xfer/tests.sh
-@@ -368,5 +368,31 @@ $DIGCMD nil. TXT | grep 'incorrect key AXFR' >/dev/null && {
- status=1
- }
-
-+n=`expr $n + 1`
-+echo "I:test that a zone with too many records is rejected (AXFR) ($n)"
-+tmp=0
-+grep "'axfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1
-+if test $tmp != 0 ; then echo "I:failed"; fi
-+status=`expr $status + $tmp`
-+
-+n=`expr $n + 1`
-+echo "I:test that a zone with too many records is rejected (IXFR) ($n)"
-+tmp=0
-+grep "'ixfr-too-big./IN.*: too many records" ns6/named.run >/dev/null && tmp=1
-+$NSUPDATE << EOF
-+zone ixfr-too-big
-+server 10.53.0.1 5300
-+update add the-31st-record.ixfr-too-big 0 TXT this is it
-+send
-+EOF
-+for i in 1 2 3 4 5 6 7 8
-+do
-+ grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null && break
-+ sleep 1
-+done
-+grep "'ixfr-too-big/IN'.*: too many records" ns6/named.run >/dev/null || tmp=1
-+if test $tmp != 0 ; then echo "I:failed"; fi
-+status=`expr $status + $tmp`
-+
- echo "I:exit status: $status"
- exit $status
-diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
-index 848b582..0369505 100644
---- a/doc/arm/Bv9ARM-book.xml
-+++ b/doc/arm/Bv9ARM-book.xml
-@@ -4858,6 +4858,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
- <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
- <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
- <optional> queryport-pool-updateinterval <replaceable>number</replaceable>; </optional>
-+ <optional> max-records <replaceable>number</replaceable>; </optional>
- <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional>
- <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional>
- <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
-@@ -8164,6 +8165,16 @@ avoid-v6-udp-ports { 40000; range 50000 60000; };
- </varlistentry>
-
- <varlistentry>
-+ <term><command>max-records</command></term>
-+ <listitem>
-+ <para>
-+ The maximum number of records permitted in a zone.
-+ The default is zero which means unlimited.
-+ </para>
-+ </listitem>
-+ </varlistentry>
-+
-+ <varlistentry>
- <term><command>host-statistics-max</command></term>
- <listitem>
- <para>
-@@ -12056,6 +12067,16 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
- </varlistentry>
-
- <varlistentry>
-+ <term><command>max-records</command></term>
-+ <listitem>
-+ <para>
-+ See the description of
-+ <command>max-records</command> in <xref linkend="server_resource_limits"/>.
-+ </para>
-+ </listitem>
-+ </varlistentry>
-+
-+ <varlistentry>
- <term><command>max-transfer-time-in</command></term>
- <listitem>
- <para>
-diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
-index 095eb5b..36495e7 100644
---- a/doc/arm/notes.xml
-+++ b/doc/arm/notes.xml
-@@ -52,6 +52,15 @@
- <itemizedlist>
- <listitem>
- <para>
-+ Added the ability to specify the maximum number of records
-+ permitted in a zone (max-records #;). This provides a mechanism
-+ to block overly large zone transfers, which is a potential risk
-+ with slave zones from other parties, as described in CVE-2016-6170.
-+ [RT #42143]
-+ </para>
-+ </listitem>
-+ <listitem>
-+ <para>
- Duplicate EDNS COOKIE options in a response could trigger
- an assertion failure. This flaw is disclosed in CVE-2016-2088.
- [RT #41809]
-diff --git a/lib/bind9/check.c b/lib/bind9/check.c
-index b8c05dd..edb7534 100644
---- a/lib/bind9/check.c
-+++ b/lib/bind9/check.c
-@@ -1510,6 +1510,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
- REDIRECTZONE },
- { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE },
- { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
-+ { "max-records", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE |
-+ STATICSTUBZONE | REDIRECTZONE },
- { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
- { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
- { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE },
-diff --git a/lib/dns/db.c b/lib/dns/db.c
-index 7e4f357..ced94a5 100644
---- a/lib/dns/db.c
-+++ b/lib/dns/db.c
-@@ -999,6 +999,19 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
- }
-
- isc_result_t
-+dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records,
-+ isc_uint64_t *bytes)
-+{
-+ REQUIRE(DNS_DB_VALID(db));
-+ REQUIRE(dns_db_iszone(db) == ISC_TRUE);
-+
-+ if (db->methods->getsize != NULL)
-+ return ((db->methods->getsize)(db, version, records, bytes));
-+
-+ return (ISC_R_NOTFOUND);
-+}
-+
-+isc_result_t
- dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
- isc_stdtime_t resign)
- {
-diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c
-index 553a339..b5d04d2 100644
---- a/lib/dns/ecdb.c
-+++ b/lib/dns/ecdb.c
-@@ -587,7 +587,8 @@ static dns_dbmethods_t ecdb_methods = {
- NULL, /* findnodeext */
- NULL, /* findext */
- NULL, /* setcachestats */
-- NULL /* hashsize */
-+ NULL, /* hashsize */
-+ NULL /* getsize */
- };
-
- static isc_result_t
-diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h
-index a4a4482..aff42d6 100644
---- a/lib/dns/include/dns/db.h
-+++ b/lib/dns/include/dns/db.h
-@@ -195,6 +195,8 @@ typedef struct dns_dbmethods {
- dns_rdataset_t *sigrdataset);
- isc_result_t (*setcachestats)(dns_db_t *db, isc_stats_t *stats);
- unsigned int (*hashsize)(dns_db_t *db);
-+ isc_result_t (*getsize)(dns_db_t *db, dns_dbversion_t *version,
-+ isc_uint64_t *records, isc_uint64_t *bytes);
- } dns_dbmethods_t;
-
- typedef isc_result_t
-@@ -1485,6 +1487,24 @@ dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
- */
-
- isc_result_t
-+dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records,
-+ isc_uint64_t *bytes);
-+/*%<
-+ * Get the number of records in the given version of the database as well
-+ * as the number bytes used to store those records.
-+ *
-+ * Requires:
-+ * \li 'db' is a valid zone database.
-+ * \li 'version' is NULL or a valid version.
-+ * \li 'records' is NULL or a pointer to return the record count in.
-+ * \li 'bytes' is NULL or a pointer to return the byte count in.
-+ *
-+ * Returns:
-+ * \li #ISC_R_SUCCESS
-+ * \li #ISC_R_NOTIMPLEMENTED
-+ */
-+
-+isc_result_t
- dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
- isc_boolean_t create, dns_dbnode_t **nodep);
- /*%<
-diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h
-index 3ac44b8..2e1e759 100644
---- a/lib/dns/include/dns/rdataslab.h
-+++ b/lib/dns/include/dns/rdataslab.h
-@@ -104,6 +104,7 @@ dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
- * Ensures:
- *\li 'rdataset' is associated and points to a valid rdataest.
- */
-+
- unsigned int
- dns_rdataslab_size(unsigned char *slab, unsigned int reservelen);
- /*%<
-@@ -116,6 +117,18 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen);
- *\li The number of bytes in the slab, including the reservelen.
- */
-
-+unsigned int
-+dns_rdataslab_count(unsigned char *slab, unsigned int reservelen);
-+/*%<
-+ * Return the number of records in the rdataslab
-+ *
-+ * Requires:
-+ *\li 'slab' points to a slab.
-+ *
-+ * Returns:
-+ *\li The number of records in the slab.
-+ */
-+
- isc_result_t
- dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
- unsigned int reservelen, isc_mem_t *mctx,
-diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h
-index 7d11c2b..93d1fd5 100644
---- a/lib/dns/include/dns/result.h
-+++ b/lib/dns/include/dns/result.h
-@@ -157,8 +157,12 @@
- #define DNS_R_BADCDS (ISC_RESULTCLASS_DNS + 111)
- #define DNS_R_BADCDNSKEY (ISC_RESULTCLASS_DNS + 112)
- #define DNS_R_OPTERR (ISC_RESULTCLASS_DNS + 113)
-+#define DNS_R_BADDNSTAP (ISC_RESULTCLASS_DNS + 114)
-+#define DNS_R_BADTSIG (ISC_RESULTCLASS_DNS + 115)
-+#define DNS_R_BADSIG0 (ISC_RESULTCLASS_DNS + 116)
-+#define DNS_R_TOOMANYRECORDS (ISC_RESULTCLASS_DNS + 117)
-
--#define DNS_R_NRESULTS 114 /*%< Number of results */
-+#define DNS_R_NRESULTS 118 /*%< Number of results */
-
- /*
- * DNS wire format rcodes.
-diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
-index a9367f1..227540b 100644
---- a/lib/dns/include/dns/zone.h
-+++ b/lib/dns/include/dns/zone.h
-@@ -296,6 +296,32 @@ dns_zone_getfile(dns_zone_t *zone);
- */
-
- void
-+dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t records);
-+/*%<
-+ * Sets the maximim number of records permitted in a zone.
-+ * 0 implies unlimited.
-+ *
-+ * Requires:
-+ *\li 'zone' to be valid initialised zone.
-+ *
-+ * Returns:
-+ *\li void
-+ */
-+
-+isc_uint32_t
-+dns_zone_getmaxrecords(dns_zone_t *zone);
-+/*%<
-+ * Gets the maximim number of records permitted in a zone.
-+ * 0 implies unlimited.
-+ *
-+ * Requires:
-+ *\li 'zone' to be valid initialised zone.
-+ *
-+ * Returns:
-+ *\li isc_uint32_t maxrecords.
-+ */
-+
-+void
- dns_zone_setmaxttl(dns_zone_t *zone, isc_uint32_t maxttl);
- /*%<
- * Sets the max ttl of the zone.
-@@ -316,7 +342,7 @@ dns_zone_getmaxttl(dns_zone_t *zone);
- *\li 'zone' to be valid initialised zone.
- *
- * Returns:
-- *\li isc_uint32_t maxttl.
-+ *\li dns_ttl_t maxttl.
- */
-
- isc_result_t
-diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
-index 62becfc..72d722f 100644
---- a/lib/dns/rbtdb.c
-+++ b/lib/dns/rbtdb.c
-@@ -209,6 +209,7 @@ typedef isc_uint64_t rbtdb_serial_t;
- #define free_rbtdb_callback free_rbtdb_callback64
- #define free_rdataset free_rdataset64
- #define getnsec3parameters getnsec3parameters64
-+#define getsize getsize64
- #define getoriginnode getoriginnode64
- #define getrrsetstats getrrsetstats64
- #define getsigningtime getsigningtime64
-@@ -589,6 +590,13 @@ typedef struct rbtdb_version {
- isc_uint16_t iterations;
- isc_uint8_t salt_length;
- unsigned char salt[DNS_NSEC3_SALTSIZE];
-+
-+ /*
-+ * records and bytes are covered by rwlock.
-+ */
-+ isc_rwlock_t rwlock;
-+ isc_uint64_t records;
-+ isc_uint64_t bytes;
- } rbtdb_version_t;
-
- typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
-@@ -1130,6 +1138,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
- INSIST(refs == 0);
- UNLINK(rbtdb->open_versions, rbtdb->current_version, link);
- isc_refcount_destroy(&rbtdb->current_version->references);
-+ isc_rwlock_destroy(&rbtdb->current_version->rwlock);
- isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
- sizeof(rbtdb_version_t));
- }
-@@ -1383,6 +1392,7 @@ allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
-
- static isc_result_t
- newversion(dns_db_t *db, dns_dbversion_t **versionp) {
-+ isc_result_t result;
- dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
- rbtdb_version_t *version;
-
-@@ -1415,13 +1425,28 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) {
- version->salt_length = 0;
- memset(version->salt, 0, sizeof(version->salt));
- }
-- rbtdb->next_serial++;
-- rbtdb->future_version = version;
-- }
-+ result = isc_rwlock_init(&version->rwlock, 0, 0);
-+ if (result != ISC_R_SUCCESS) {
-+ isc_refcount_destroy(&version->references);
-+ isc_mem_put(rbtdb->common.mctx, version,
-+ sizeof(*version));
-+ version = NULL;
-+ } else {
-+ RWLOCK(&rbtdb->current_version->rwlock,
-+ isc_rwlocktype_read);
-+ version->records = rbtdb->current_version->records;
-+ version->bytes = rbtdb->current_version->bytes;
-+ RWUNLOCK(&rbtdb->current_version->rwlock,
-+ isc_rwlocktype_read);
-+ rbtdb->next_serial++;
-+ rbtdb->future_version = version;
-+ }
-+ } else
-+ result = ISC_R_NOMEMORY;
- RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
-
- if (version == NULL)
-- return (ISC_R_NOMEMORY);
-+ return (result);
-
- *versionp = version;
-
-@@ -2681,6 +2706,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
-
- if (cleanup_version != NULL) {
- INSIST(EMPTY(cleanup_version->changed_list));
-+ isc_rwlock_destroy(&cleanup_version->rwlock);
- isc_mem_put(rbtdb->common.mctx, cleanup_version,
- sizeof(*cleanup_version));
- }
-@@ -6254,6 +6280,26 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
- else
- rbtnode->data = newheader;
- newheader->next = topheader->next;
-+ if (rbtversion != NULL)
-+ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
-+ if (rbtversion != NULL && !header_nx) {
-+ rbtversion->records -=
-+ dns_rdataslab_count((unsigned char *)header,
-+ sizeof(*header));
-+ rbtversion->bytes -=
-+ dns_rdataslab_size((unsigned char *)header,
-+ sizeof(*header));
-+ }
-+ if (rbtversion != NULL && !newheader_nx) {
-+ rbtversion->records +=
-+ dns_rdataslab_count((unsigned char *)newheader,
-+ sizeof(*newheader));
-+ rbtversion->bytes +=
-+ dns_rdataslab_size((unsigned char *)newheader,
-+ sizeof(*newheader));
-+ }
-+ if (rbtversion != NULL)
-+ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
- if (loading) {
- /*
- * There are no other references to 'header' when
-@@ -6355,6 +6401,16 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
- newheader->down = NULL;
- rbtnode->data = newheader;
- }
-+ if (rbtversion != NULL && !newheader_nx) {
-+ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
-+ rbtversion->records +=
-+ dns_rdataslab_count((unsigned char *)newheader,
-+ sizeof(*newheader));
-+ rbtversion->bytes +=
-+ dns_rdataslab_size((unsigned char *)newheader,
-+ sizeof(*newheader));
-+ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
-+ }
- idx = newheader->node->locknum;
- if (IS_CACHE(rbtdb)) {
- ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
-@@ -6811,6 +6867,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
- */
- newheader->additional_auth = NULL;
- newheader->additional_glue = NULL;
-+ rbtversion->records +=
-+ dns_rdataslab_count((unsigned char *)newheader,
-+ sizeof(*newheader));
-+ rbtversion->bytes +=
-+ dns_rdataslab_size((unsigned char *)newheader,
-+ sizeof(*newheader));
- } else if (result == DNS_R_NXRRSET) {
- /*
- * This subtraction would remove all of the rdata;
-@@ -6846,6 +6908,12 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
- * topheader.
- */
- INSIST(rbtversion->serial >= topheader->serial);
-+ rbtversion->records -=
-+ dns_rdataslab_count((unsigned char *)header,
-+ sizeof(*header));
-+ rbtversion->bytes -=
-+ dns_rdataslab_size((unsigned char *)header,
-+ sizeof(*header));
- if (topheader_prev != NULL)
- topheader_prev->next = newheader;
- else
-@@ -7172,6 +7240,7 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize,
- unsigned char *limit = ((unsigned char *) base) + filesize;
- unsigned char *p;
- size_t size;
-+ unsigned int count;
-
- REQUIRE(rbtnode != NULL);
-
-@@ -7179,6 +7248,9 @@ rbt_datafixer(dns_rbtnode_t *rbtnode, void *base, size_t filesize,
- p = (unsigned char *) header;
-
- size = dns_rdataslab_size(p, sizeof(*header));
-+ count = dns_rdataslab_count(p, sizeof(*header));;
-+ rbtdb->current_version->records += count;
-+ rbtdb->current_version->bytes += size;
- isc_crc64_update(crc, p, size);
- #ifdef DEBUG
- hexdump("hashing header", p, sizeof(rdatasetheader_t));
-@@ -7777,6 +7849,33 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
- }
-
- static isc_result_t
-+getsize(dns_db_t *db, dns_dbversion_t *version, isc_uint64_t *records,
-+ isc_uint64_t *bytes)
-+{
-+ dns_rbtdb_t *rbtdb;
-+ isc_result_t result = ISC_R_SUCCESS;
-+ rbtdb_version_t *rbtversion = version;
-+
-+ rbtdb = (dns_rbtdb_t *)db;
-+
-+ REQUIRE(VALID_RBTDB(rbtdb));
-+ INSIST(rbtversion == NULL || rbtversion->rbtdb == rbtdb);
-+
-+ if (rbtversion == NULL)
-+ rbtversion = rbtdb->current_version;
-+
-+ RWLOCK(&rbtversion->rwlock, isc_rwlocktype_read);
-+ if (records != NULL)
-+ *records = rbtversion->records;
-+
-+ if (bytes != NULL)
-+ *bytes = rbtversion->bytes;
-+ RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_read);
-+
-+ return (result);
-+}
-+
-+static isc_result_t
- setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
- dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
- isc_stdtime_t oldresign;
-@@ -7972,7 +8071,8 @@ static dns_dbmethods_t zone_methods = {
- NULL,
- NULL,
- NULL,
-- hashsize
-+ hashsize,
-+ getsize
- };
-
- static dns_dbmethods_t cache_methods = {
-@@ -8018,7 +8118,8 @@ static dns_dbmethods_t cache_methods = {
- NULL,
- NULL,
- setcachestats,
-- hashsize
-+ hashsize,
-+ NULL
- };
-
- isc_result_t
-@@ -8310,6 +8411,20 @@ dns_rbtdb_create
- rbtdb->current_version->salt_length = 0;
- memset(rbtdb->current_version->salt, 0,
- sizeof(rbtdb->current_version->salt));
-+ result = isc_rwlock_init(&rbtdb->current_version->rwlock, 0, 0);
-+ if (result != ISC_R_SUCCESS) {
-+ isc_refcount_destroy(&rbtdb->current_version->references);
-+ isc_mem_put(mctx, rbtdb->current_version,
-+ sizeof(*rbtdb->current_version));
-+ rbtdb->current_version = NULL;
-+ isc_refcount_decrement(&rbtdb->references, NULL);
-+ isc_refcount_destroy(&rbtdb->references);
-+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
-+ return (result);
-+ }
-+
-+ rbtdb->current_version->records = 0;
-+ rbtdb->current_version->bytes = 0;
- rbtdb->future_version = NULL;
- ISC_LIST_INIT(rbtdb->open_versions);
- /*
-diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
-index e29dc84..63e3728 100644
---- a/lib/dns/rdataslab.c
-+++ b/lib/dns/rdataslab.c
-@@ -523,6 +523,19 @@ dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) {
- return ((unsigned int)(current - slab));
- }
-
-+unsigned int
-+dns_rdataslab_count(unsigned char *slab, unsigned int reservelen) {
-+ unsigned int count;
-+ unsigned char *current;
-+
-+ REQUIRE(slab != NULL);
-+
-+ current = slab + reservelen;
-+ count = *current++ * 256;
-+ count += *current++;
-+ return (count);
-+}
-+
- /*
- * Make the dns_rdata_t 'rdata' refer to the slab item
- * beginning at '*current', which is part of a slab of type
-diff --git a/lib/dns/result.c b/lib/dns/result.c
-index 7be4f57..a621909 100644
---- a/lib/dns/result.c
-+++ b/lib/dns/result.c
-@@ -167,11 +167,16 @@ static const char *text[DNS_R_NRESULTS] = {
- "covered by negative trust anchor", /*%< 110 DNS_R_NTACOVERED */
- "bad CDS", /*%< 111 DNS_R_BADCSD */
- "bad CDNSKEY", /*%< 112 DNS_R_BADCDNSKEY */
-- "malformed OPT option" /*%< 113 DNS_R_OPTERR */
-+ "malformed OPT option", /*%< 113 DNS_R_OPTERR */
-+ "malformed DNSTAP data", /*%< 114 DNS_R_BADDNSTAP */
-+
-+ "TSIG in wrong location", /*%< 115 DNS_R_BADTSIG */
-+ "SIG(0) in wrong location", /*%< 116 DNS_R_BADSIG0 */
-+ "too many records", /*%< 117 DNS_R_TOOMANYRECORDS */
- };
-
- static const char *rcode_text[DNS_R_NRCODERESULTS] = {
-- "NOERROR", /*%< 0 DNS_R_NOEROR */
-+ "NOERROR", /*%< 0 DNS_R_NOERROR */
- "FORMERR", /*%< 1 DNS_R_FORMERR */
- "SERVFAIL", /*%< 2 DNS_R_SERVFAIL */
- "NXDOMAIN", /*%< 3 DNS_R_NXDOMAIN */
-diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
-index abfeeb0..19397e0 100644
---- a/lib/dns/sdb.c
-+++ b/lib/dns/sdb.c
-@@ -1298,7 +1298,8 @@ static dns_dbmethods_t sdb_methods = {
- findnodeext,
- findext,
- NULL, /* setcachestats */
-- NULL /* hashsize */
-+ NULL, /* hashsize */
-+ NULL /* getsize */
- };
-
- static isc_result_t
-diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
-index b1198a4..0e3163d 100644
---- a/lib/dns/sdlz.c
-+++ b/lib/dns/sdlz.c
-@@ -1269,7 +1269,8 @@ static dns_dbmethods_t sdlzdb_methods = {
- findnodeext,
- findext,
- NULL, /* setcachestats */
-- NULL /* hashsize */
-+ NULL, /* hashsize */
-+ NULL /* getsize */
- };
-
- /*
-diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
-index 2a6c1b4..ac566e1 100644
---- a/lib/dns/xfrin.c
-+++ b/lib/dns/xfrin.c
-@@ -149,6 +149,9 @@ struct dns_xfrin_ctx {
- unsigned int nrecs; /*%< Number of records recvd */
- isc_uint64_t nbytes; /*%< Number of bytes received */
-
-+ unsigned int maxrecords; /*%< The maximum number of
-+ records set for the zone */
-+
- isc_time_t start; /*%< Start time of the transfer */
- isc_time_t end; /*%< End time of the transfer */
-
-@@ -309,10 +312,18 @@ axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
- static isc_result_t
- axfr_apply(dns_xfrin_ctx_t *xfr) {
- isc_result_t result;
-+ isc_uint64_t records;
-
- CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private));
- xfr->difflen = 0;
- dns_diff_clear(&xfr->diff);
-+ if (xfr->maxrecords != 0U) {
-+ result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL);
-+ if (result == ISC_R_SUCCESS && records > xfr->maxrecords) {
-+ result = DNS_R_TOOMANYRECORDS;
-+ goto failure;
-+ }
-+ }
- result = ISC_R_SUCCESS;
- failure:
- return (result);
-@@ -396,6 +407,7 @@ ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
- static isc_result_t
- ixfr_apply(dns_xfrin_ctx_t *xfr) {
- isc_result_t result;
-+ isc_uint64_t records;
-
- if (xfr->ver == NULL) {
- CHECK(dns_db_newversion(xfr->db, &xfr->ver));
-@@ -403,6 +415,13 @@ ixfr_apply(dns_xfrin_ctx_t *xfr) {
- CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
- }
- CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
-+ if (xfr->maxrecords != 0U) {
-+ result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL);
-+ if (result == ISC_R_SUCCESS && records > xfr->maxrecords) {
-+ result = DNS_R_TOOMANYRECORDS;
-+ goto failure;
-+ }
-+ }
- if (xfr->ixfr.journal != NULL) {
- result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
- if (result != ISC_R_SUCCESS)
-@@ -759,7 +778,7 @@ xfrin_reset(dns_xfrin_ctx_t *xfr) {
-
- static void
- xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
-- if (result != DNS_R_UPTODATE) {
-+ if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) {
- xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
- msg, isc_result_totext(result));
- if (xfr->is_ixfr)
-@@ -852,6 +871,7 @@ xfrin_create(isc_mem_t *mctx,
- xfr->nmsg = 0;
- xfr->nrecs = 0;
- xfr->nbytes = 0;
-+ xfr->maxrecords = dns_zone_getmaxrecords(zone);
- isc_time_now(&xfr->start);
-
- xfr->tsigkey = NULL;
-diff --git a/lib/dns/zone.c b/lib/dns/zone.c
-index 90e558d..2b0d8e4 100644
---- a/lib/dns/zone.c
-+++ b/lib/dns/zone.c
-@@ -253,6 +253,8 @@ struct dns_zone {
- isc_uint32_t maxretry;
- isc_uint32_t minretry;
-
-+ isc_uint32_t maxrecords;
-+
- isc_sockaddr_t *masters;
- isc_dscp_t *masterdscps;
- dns_name_t **masterkeynames;
-@@ -10088,6 +10090,20 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
- zone->maxretry = val;
- }
-
-+isc_uint32_t
-+dns_zone_getmaxrecords(dns_zone_t *zone) {
-+ REQUIRE(DNS_ZONE_VALID(zone));
-+
-+ return (zone->maxrecords);
-+}
-+
-+void
-+dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t val) {
-+ REQUIRE(DNS_ZONE_VALID(zone));
-+
-+ zone->maxrecords = val;
-+}
-+
- static isc_boolean_t
- notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
- isc_sockaddr_t *addr, dns_tsigkey_t *key)
-@@ -14431,7 +14447,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
- DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
-
- TIME_NOW(&now);
-- switch (result) {
-+ switch (xfrresult) {
- case ISC_R_SUCCESS:
- DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
- /*FALLTHROUGH*/
-@@ -14558,6 +14574,11 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
- DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
- goto same_master;
-
-+ case DNS_R_TOOMANYRECORDS:
-+ DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
-+ inc_stats(zone, dns_zonestatscounter_xfrfail);
-+ break;
-+
- default:
- next_master:
- /*
-diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
-index 780ab46..e7ff1cc 100644
---- a/lib/isccfg/namedconf.c
-+++ b/lib/isccfg/namedconf.c
-@@ -1679,6 +1679,7 @@ zone_clauses[] = {
- { "masterfile-format", &cfg_type_masterformat, 0 },
- { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE },
- { "max-journal-size", &cfg_type_sizenodefault, 0 },
-+ { "max-records", &cfg_type_uint32, 0 },
- { "max-refresh-time", &cfg_type_uint32, 0 },
- { "max-retry-time", &cfg_type_uint32, 0 },
- { "max-transfer-idle-in", &cfg_type_uint32, 0 },
---
-2.7.4
-