1153 lines
42 KiB
Diff
1153 lines
42 KiB
Diff
|
From 2df11e5a549a71a8f792ac5207254b6a9e09859c Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
|
||
|
Date: Fri, 1 Mar 2024 08:26:07 +0100
|
||
|
Subject: [PATCH] Add a limit to the number of RRs in RRSets
|
||
|
|
||
|
Previously, the number of RRs in the RRSets were internally unlimited.
|
||
|
As the data structure that holds the RRs is just a linked list, and
|
||
|
there are places where we just walk through all of the RRs, adding an
|
||
|
RRSet with huge number of RRs inside would slow down processing of said
|
||
|
RRSets.
|
||
|
|
||
|
Add a configurable limit to cap the number of the RRs in a single RRSet.
|
||
|
This is enforced at the database (rbtdb, qpzone, qpcache) level and
|
||
|
configured with new max-records-per-type configuration option that can
|
||
|
be configured globally, per-view and per-zone.
|
||
|
|
||
|
(cherry picked from commit 3fbd21f69a1bcbd26c4c00920e7b0a419e8762fc)
|
||
|
(cherry picked from commit f63d72fb7e5813585c92d7f92bdcc5885cd04edc)
|
||
|
---
|
||
|
bin/named/config.c | 1 +
|
||
|
bin/named/server.c | 9 ++++
|
||
|
bin/named/zoneconf.c | 8 ++++
|
||
|
bin/tests/system/dyndb/driver/db.c | 3 +-
|
||
|
doc/arm/reference.rst | 12 +++++
|
||
|
doc/misc/master.zoneopt | 2 +
|
||
|
doc/misc/mirror.zoneopt | 2 +
|
||
|
doc/misc/options | 44 +++++++++++-------
|
||
|
doc/misc/options.active | 44 +++++++++++-------
|
||
|
doc/misc/redirect.zoneopt | 2 +
|
||
|
doc/misc/slave.zoneopt | 2 +
|
||
|
doc/misc/static-stub.zoneopt | 2 +
|
||
|
doc/misc/stub.zoneopt | 2 +
|
||
|
lib/dns/cache.c | 13 ++++++
|
||
|
lib/dns/db.c | 9 ++++
|
||
|
lib/dns/dnsrps.c | 3 +-
|
||
|
lib/dns/ecdb.c | 8 +++-
|
||
|
lib/dns/include/dns/cache.h | 6 +++
|
||
|
lib/dns/include/dns/db.h | 8 ++++
|
||
|
lib/dns/include/dns/rdataslab.h | 6 ++-
|
||
|
lib/dns/include/dns/view.h | 7 +++
|
||
|
lib/dns/include/dns/zone.h | 26 +++++++++++
|
||
|
lib/dns/rbtdb.c | 45 ++++++++++++------
|
||
|
lib/dns/rdataslab.c | 10 ++--
|
||
|
lib/dns/sdb.c | 3 +-
|
||
|
lib/dns/sdlz.c | 3 +-
|
||
|
lib/dns/view.c | 11 +++++
|
||
|
lib/dns/xfrin.c | 24 ++--------
|
||
|
lib/dns/zone.c | 74 ++++++++++++++++++++++--------
|
||
|
lib/isccfg/namedconf.c | 3 ++
|
||
|
30 files changed, 296 insertions(+), 96 deletions(-)
|
||
|
|
||
|
diff --git a/bin/named/config.c b/bin/named/config.c
|
||
|
index c37015f3b2..9cba6f588b 100644
|
||
|
--- a/bin/named/config.c
|
||
|
+++ b/bin/named/config.c
|
||
|
@@ -215,6 +215,7 @@ options {\n\
|
||
|
ixfr-from-differences false;\n\
|
||
|
max-journal-size default;\n\
|
||
|
max-records 0;\n\
|
||
|
+ max-records-per-type 100;\n\
|
||
|
max-refresh-time 2419200; /* 4 weeks */\n\
|
||
|
max-retry-time 1209600; /* 2 weeks */\n\
|
||
|
max-transfer-idle-in 60;\n\
|
||
|
diff --git a/bin/named/server.c b/bin/named/server.c
|
||
|
index 8fd9ee7e5a..7bf5f2664d 100644
|
||
|
--- a/bin/named/server.c
|
||
|
+++ b/bin/named/server.c
|
||
|
@@ -5418,6 +5418,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||
|
dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj),
|
||
|
max_clients_per_query);
|
||
|
|
||
|
+ /*
|
||
|
+ * This is used for the cache and also as a default value
|
||
|
+ * for zone databases.
|
||
|
+ */
|
||
|
+ obj = NULL;
|
||
|
+ result = named_config_get(maps, "max-records-per-type", &obj);
|
||
|
+ INSIST(result == ISC_R_SUCCESS);
|
||
|
+ dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj));
|
||
|
+
|
||
|
obj = NULL;
|
||
|
result = named_config_get(maps, "max-recursion-depth", &obj);
|
||
|
INSIST(result == ISC_R_SUCCESS);
|
||
|
diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
|
||
|
index 97c2094ca2..ae5cc656ee 100644
|
||
|
--- a/bin/named/zoneconf.c
|
||
|
+++ b/bin/named/zoneconf.c
|
||
|
@@ -1092,6 +1092,14 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||
|
dns_zone_setmaxrecords(zone, 0);
|
||
|
}
|
||
|
|
||
|
+ obj = NULL;
|
||
|
+ result = named_config_get(maps, "max-records-per-type", &obj);
|
||
|
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||
|
+ dns_zone_setmaxrrperset(mayberaw, cfg_obj_asuint32(obj));
|
||
|
+ if (zone != mayberaw) {
|
||
|
+ dns_zone_setmaxrrperset(zone, 0);
|
||
|
+ }
|
||
|
+
|
||
|
if (raw != NULL && filename != NULL) {
|
||
|
#define SIGNED ".signed"
|
||
|
size_t signedlen = strlen(filename) + sizeof(SIGNED);
|
||
|
diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c
|
||
|
index 77d335e2ea..6725a3bacd 100644
|
||
|
--- a/bin/tests/system/dyndb/driver/db.c
|
||
|
+++ b/bin/tests/system/dyndb/driver/db.c
|
||
|
@@ -592,7 +592,8 @@ static dns_dbmethods_t sampledb_methods = {
|
||
|
NULL, /* setservestalerefresh */
|
||
|
NULL, /* getservestalerefresh */
|
||
|
NULL, /* setgluecachestats */
|
||
|
- NULL /* adjusthashsize */
|
||
|
+ NULL, /* adjusthashsize */
|
||
|
+ NULL /* setmaxrrperset */
|
||
|
};
|
||
|
|
||
|
/* Auxiliary driver functions. */
|
||
|
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
|
||
|
index ad7ff2761a..b1983ef30d 100644
|
||
|
--- a/doc/arm/reference.rst
|
||
|
+++ b/doc/arm/reference.rst
|
||
|
@@ -2890,6 +2890,18 @@ system.
|
||
|
This sets the maximum number of records permitted in a zone. The default is
|
||
|
zero, which means the maximum is unlimited.
|
||
|
|
||
|
+``max-records-per-type``
|
||
|
+ This sets the maximum number of resource records that can be stored
|
||
|
+ in an RRset in a database. When configured in ``options``
|
||
|
+ or ``view``, it controls the cache database; it also sets
|
||
|
+ the default value for zone databases, which can be overridden by setting
|
||
|
+ it at the ``zone`` level.
|
||
|
+
|
||
|
+ If set to a positive value, any attempt to cache or to add to a zone
|
||
|
+ an RRset with more than the specified number of records will result in
|
||
|
+ a failure. If set to 0, there is no cap on RRset size. The default is
|
||
|
+ 100.
|
||
|
+
|
||
|
``recursive-clients``
|
||
|
This sets the maximum number (a "hard quota") of simultaneous recursive lookups
|
||
|
the server performs on behalf of clients. The default is
|
||
|
diff --git a/doc/misc/master.zoneopt b/doc/misc/master.zoneopt
|
||
|
index cc8a33b56f..864a852ef4 100644
|
||
|
--- a/doc/misc/master.zoneopt
|
||
|
+++ b/doc/misc/master.zoneopt
|
||
|
@@ -38,8 +38,10 @@ zone <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
notify ( explicit | master-only | primary-only | <boolean> );
|
||
|
notify-delay <integer>;
|
||
|
diff --git a/doc/misc/mirror.zoneopt b/doc/misc/mirror.zoneopt
|
||
|
index 3d45a3d1e5..701edce540 100644
|
||
|
--- a/doc/misc/mirror.zoneopt
|
||
|
+++ b/doc/misc/mirror.zoneopt
|
||
|
@@ -19,12 +19,14 @@ zone <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
multi-master <boolean>;
|
||
|
diff --git a/doc/misc/options b/doc/misc/options
|
||
|
index 90d07f5a56..ee152b8179 100644
|
||
|
--- a/doc/misc/options
|
||
|
+++ b/doc/misc/options
|
||
|
@@ -170,13 +170,16 @@ options {
|
||
|
dnssec-secure-to-insecure <boolean>;
|
||
|
dnssec-update-mode ( maintain | no-resign );
|
||
|
dnssec-validation ( yes | no | auto );
|
||
|
- dnstap { ( all | auth | client | forwarder | resolver | update ) [
|
||
|
- ( query | response ) ]; ... };
|
||
|
- dnstap-identity ( <quoted_string> | none | hostname );
|
||
|
- dnstap-output ( file | unix ) <quoted_string> [ size ( unlimited |
|
||
|
- <size> ) ] [ versions ( unlimited | <integer> ) ] [ suffix (
|
||
|
- increment | timestamp ) ];
|
||
|
- dnstap-version ( <quoted_string> | none );
|
||
|
+ dnstap { ( all | auth | client | forwarder |
|
||
|
+ resolver | update ) [ ( query | response ) ];
|
||
|
+ ... }; // not configured
|
||
|
+ dnstap-identity ( <quoted_string> | none |
|
||
|
+ hostname ); // not configured
|
||
|
+ dnstap-output ( file | unix ) <quoted_string> [
|
||
|
+ size ( unlimited | <size> ) ] [ versions (
|
||
|
+ unlimited | <integer> ) ] [ suffix ( increment
|
||
|
+ | timestamp ) ]; // not configured
|
||
|
+ dnstap-version ( <quoted_string> | none ); // not configured
|
||
|
dscp <integer>;
|
||
|
dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv4_address> [ port
|
||
|
@@ -200,13 +203,13 @@ options {
|
||
|
forward ( first | only );
|
||
|
forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
|
||
|
| <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
|
||
|
- fstrm-set-buffer-hint <integer>;
|
||
|
- fstrm-set-flush-timeout <integer>;
|
||
|
- fstrm-set-input-queue-size <integer>;
|
||
|
- fstrm-set-output-notify-threshold <integer>;
|
||
|
- fstrm-set-output-queue-model ( mpsc | spsc );
|
||
|
- fstrm-set-output-queue-size <integer>;
|
||
|
- fstrm-set-reopen-interval <duration>;
|
||
|
+ fstrm-set-buffer-hint <integer>; // not configured
|
||
|
+ fstrm-set-flush-timeout <integer>; // not configured
|
||
|
+ fstrm-set-input-queue-size <integer>; // not configured
|
||
|
+ fstrm-set-output-notify-threshold <integer>; // not configured
|
||
|
+ fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
|
||
|
+ fstrm-set-output-queue-size <integer>; // not configured
|
||
|
+ fstrm-set-reopen-interval <duration>; // not configured
|
||
|
geoip-directory ( <quoted_string> | none );
|
||
|
geoip-use-ecs <boolean>; // obsolete
|
||
|
glue-cache <boolean>;
|
||
|
@@ -243,6 +246,7 @@ options {
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-ncache-ttl <duration>;
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-recursion-depth <integer>;
|
||
|
max-recursion-queries <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
@@ -253,6 +257,7 @@ options {
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-udp-size <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
memstatistics <boolean>;
|
||
|
@@ -569,8 +574,9 @@ view <string> [ <class> ] {
|
||
|
dnssec-secure-to-insecure <boolean>;
|
||
|
dnssec-update-mode ( maintain | no-resign );
|
||
|
dnssec-validation ( yes | no | auto );
|
||
|
- dnstap { ( all | auth | client | forwarder | resolver | update ) [
|
||
|
- ( query | response ) ]; ... };
|
||
|
+ dnstap { ( all | auth | client | forwarder |
|
||
|
+ resolver | update ) [ ( query | response ) ];
|
||
|
+ ... }; // not configured
|
||
|
dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv4_address> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv6_address> [ port
|
||
|
@@ -622,6 +628,7 @@ view <string> [ <class> ] {
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-ncache-ttl <duration>;
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-recursion-depth <integer>;
|
||
|
max-recursion-queries <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
@@ -631,6 +638,7 @@ view <string> [ <class> ] {
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-udp-size <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
message-compression <boolean>;
|
||
|
@@ -854,12 +862,14 @@ view <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
@@ -971,12 +981,14 @@ zone <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
diff --git a/doc/misc/options.active b/doc/misc/options.active
|
||
|
index 0229d8da6d..ad4e29a9ba 100644
|
||
|
--- a/doc/misc/options.active
|
||
|
+++ b/doc/misc/options.active
|
||
|
@@ -156,13 +156,16 @@ options {
|
||
|
dnssec-secure-to-insecure <boolean>;
|
||
|
dnssec-update-mode ( maintain | no-resign );
|
||
|
dnssec-validation ( yes | no | auto );
|
||
|
- dnstap { ( all | auth | client | forwarder | resolver | update ) [
|
||
|
- ( query | response ) ]; ... };
|
||
|
- dnstap-identity ( <quoted_string> | none | hostname );
|
||
|
- dnstap-output ( file | unix ) <quoted_string> [ size ( unlimited |
|
||
|
- <size> ) ] [ versions ( unlimited | <integer> ) ] [ suffix (
|
||
|
- increment | timestamp ) ];
|
||
|
- dnstap-version ( <quoted_string> | none );
|
||
|
+ dnstap { ( all | auth | client | forwarder |
|
||
|
+ resolver | update ) [ ( query | response ) ];
|
||
|
+ ... }; // not configured
|
||
|
+ dnstap-identity ( <quoted_string> | none |
|
||
|
+ hostname ); // not configured
|
||
|
+ dnstap-output ( file | unix ) <quoted_string> [
|
||
|
+ size ( unlimited | <size> ) ] [ versions (
|
||
|
+ unlimited | <integer> ) ] [ suffix ( increment
|
||
|
+ | timestamp ) ]; // not configured
|
||
|
+ dnstap-version ( <quoted_string> | none ); // not configured
|
||
|
dscp <integer>;
|
||
|
dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv4_address> [ port
|
||
|
@@ -181,13 +184,13 @@ options {
|
||
|
forward ( first | only );
|
||
|
forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
|
||
|
| <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
|
||
|
- fstrm-set-buffer-hint <integer>;
|
||
|
- fstrm-set-flush-timeout <integer>;
|
||
|
- fstrm-set-input-queue-size <integer>;
|
||
|
- fstrm-set-output-notify-threshold <integer>;
|
||
|
- fstrm-set-output-queue-model ( mpsc | spsc );
|
||
|
- fstrm-set-output-queue-size <integer>;
|
||
|
- fstrm-set-reopen-interval <duration>;
|
||
|
+ fstrm-set-buffer-hint <integer>; // not configured
|
||
|
+ fstrm-set-flush-timeout <integer>; // not configured
|
||
|
+ fstrm-set-input-queue-size <integer>; // not configured
|
||
|
+ fstrm-set-output-notify-threshold <integer>; // not configured
|
||
|
+ fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
|
||
|
+ fstrm-set-output-queue-size <integer>; // not configured
|
||
|
+ fstrm-set-reopen-interval <duration>; // not configured
|
||
|
geoip-directory ( <quoted_string> | none );
|
||
|
glue-cache <boolean>;
|
||
|
heartbeat-interval <integer>;
|
||
|
@@ -217,6 +220,7 @@ options {
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-ncache-ttl <duration>;
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-recursion-depth <integer>;
|
||
|
max-recursion-queries <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
@@ -227,6 +231,7 @@ options {
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-udp-size <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
memstatistics <boolean>;
|
||
|
@@ -513,8 +518,9 @@ view <string> [ <class> ] {
|
||
|
dnssec-secure-to-insecure <boolean>;
|
||
|
dnssec-update-mode ( maintain | no-resign );
|
||
|
dnssec-validation ( yes | no | auto );
|
||
|
- dnstap { ( all | auth | client | forwarder | resolver | update ) [
|
||
|
- ( query | response ) ]; ... };
|
||
|
+ dnstap { ( all | auth | client | forwarder |
|
||
|
+ resolver | update ) [ ( query | response ) ];
|
||
|
+ ... }; // not configured
|
||
|
dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv4_address> [ port
|
||
|
<integer> ] [ dscp <integer> ] | <ipv6_address> [ port
|
||
|
@@ -559,6 +565,7 @@ view <string> [ <class> ] {
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-ncache-ttl <duration>;
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-recursion-depth <integer>;
|
||
|
max-recursion-queries <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
@@ -568,6 +575,7 @@ view <string> [ <class> ] {
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-udp-size <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
message-compression <boolean>;
|
||
|
@@ -774,12 +782,14 @@ view <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
@@ -884,12 +894,14 @@ zone <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
diff --git a/doc/misc/redirect.zoneopt b/doc/misc/redirect.zoneopt
|
||
|
index 6a5ef660a2..c4ab59ddad 100644
|
||
|
--- a/doc/misc/redirect.zoneopt
|
||
|
+++ b/doc/misc/redirect.zoneopt
|
||
|
@@ -8,6 +8,8 @@ zone <string> [ <class> ] {
|
||
|
masterfile-style ( full | relative );
|
||
|
masters [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
primaries [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
|
||
|
zone-statistics ( full | terse | none | <boolean> );
|
||
|
diff --git a/doc/misc/slave.zoneopt b/doc/misc/slave.zoneopt
|
||
|
index 8cb7c3143f..ccd88e5c15 100644
|
||
|
--- a/doc/misc/slave.zoneopt
|
||
|
+++ b/doc/misc/slave.zoneopt
|
||
|
@@ -31,12 +31,14 @@ zone <string> [ <class> ] {
|
||
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||
|
max-journal-size ( default | unlimited | <sizeval> );
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-idle-out <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
max-transfer-time-out <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
multi-master <boolean>;
|
||
|
diff --git a/doc/misc/static-stub.zoneopt b/doc/misc/static-stub.zoneopt
|
||
|
index f89d46248a..102b980c7a 100644
|
||
|
--- a/doc/misc/static-stub.zoneopt
|
||
|
+++ b/doc/misc/static-stub.zoneopt
|
||
|
@@ -5,6 +5,8 @@ zone <string> [ <class> ] {
|
||
|
forward ( first | only );
|
||
|
forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
|
||
|
server-names { <string>; ... };
|
||
|
zone-statistics ( full | terse | none | <boolean> );
|
||
|
diff --git a/doc/misc/stub.zoneopt b/doc/misc/stub.zoneopt
|
||
|
index 2db604dae6..ca4bf1ce39 100644
|
||
|
--- a/doc/misc/stub.zoneopt
|
||
|
+++ b/doc/misc/stub.zoneopt
|
||
|
@@ -13,10 +13,12 @@ zone <string> [ <class> ] {
|
||
|
masterfile-style ( full | relative );
|
||
|
masters [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
|
||
|
max-records <integer>;
|
||
|
+ max-records-per-type <integer>;
|
||
|
max-refresh-time <integer>;
|
||
|
max-retry-time <integer>;
|
||
|
max-transfer-idle-in <integer>;
|
||
|
max-transfer-time-in <integer>;
|
||
|
+ max-types-per-name <integer>;
|
||
|
min-refresh-time <integer>;
|
||
|
min-retry-time <integer>;
|
||
|
multi-master <boolean>;
|
||
|
diff --git a/lib/dns/cache.c b/lib/dns/cache.c
|
||
|
index ae173b86ab..9f0412dbe7 100644
|
||
|
--- a/lib/dns/cache.c
|
||
|
+++ b/lib/dns/cache.c
|
||
|
@@ -148,6 +148,8 @@ struct dns_cache {
|
||
|
/* Locked by 'filelock'. */
|
||
|
char *filename;
|
||
|
/* Access to the on-disk cache file is also locked by 'filelock'. */
|
||
|
+
|
||
|
+ uint32_t maxrrperset;
|
||
|
};
|
||
|
|
||
|
/***
|
||
|
@@ -175,6 +177,7 @@ cache_create_db(dns_cache_t *cache, dns_db_t **db) {
|
||
|
cache->db_argv, db);
|
||
|
if (result == ISC_R_SUCCESS) {
|
||
|
dns_db_setservestalettl(*db, cache->serve_stale_ttl);
|
||
|
+ dns_db_setmaxrrperset(*db, cache->maxrrperset);
|
||
|
}
|
||
|
return (result);
|
||
|
}
|
||
|
@@ -1277,6 +1280,16 @@ dns_cache_updatestats(dns_cache_t *cache, isc_result_t result) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+void
|
||
|
+dns_cache_setmaxrrperset(dns_cache_t *cache, uint32_t value) {
|
||
|
+ REQUIRE(VALID_CACHE(cache));
|
||
|
+
|
||
|
+ cache->maxrrperset = value;
|
||
|
+ if (cache->db != NULL) {
|
||
|
+ dns_db_setmaxrrperset(cache->db, value);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* XXX: Much of the following code has been copied in from statschannel.c.
|
||
|
* We should refactor this into a generic function in stats.c that can be
|
||
|
diff --git a/lib/dns/db.c b/lib/dns/db.c
|
||
|
index ec537486cb..8439265a7f 100644
|
||
|
--- a/lib/dns/db.c
|
||
|
+++ b/lib/dns/db.c
|
||
|
@@ -1122,3 +1122,12 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
||
|
|
||
|
return (ISC_R_NOTIMPLEMENTED);
|
||
|
}
|
||
|
+
|
||
|
+void
|
||
|
+dns_db_setmaxrrperset(dns_db_t *db, uint32_t value) {
|
||
|
+ REQUIRE(DNS_DB_VALID(db));
|
||
|
+
|
||
|
+ if (db->methods->setmaxrrperset != NULL) {
|
||
|
+ (db->methods->setmaxrrperset)(db, value);
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/lib/dns/dnsrps.c b/lib/dns/dnsrps.c
|
||
|
index 0f2ffb5f35..539090d1bd 100644
|
||
|
--- a/lib/dns/dnsrps.c
|
||
|
+++ b/lib/dns/dnsrps.c
|
||
|
@@ -970,7 +970,8 @@ static dns_dbmethods_t rpsdb_db_methods = {
|
||
|
NULL, /* setservestalerefresh */
|
||
|
NULL, /* getservestalerefresh */
|
||
|
NULL, /* setgluecachestats */
|
||
|
- NULL /* adjusthashsize */
|
||
|
+ NULL, /* adjusthashsize */
|
||
|
+ NULL /* setmaxrrperset */
|
||
|
};
|
||
|
|
||
|
static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
|
||
|
diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c
|
||
|
index 1d9343361d..bab5da5503 100644
|
||
|
--- a/lib/dns/ecdb.c
|
||
|
+++ b/lib/dns/ecdb.c
|
||
|
@@ -426,7 +426,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||
|
}
|
||
|
|
||
|
result = dns_rdataslab_fromrdataset(rdataset, mctx, &r,
|
||
|
- sizeof(rdatasetheader_t));
|
||
|
+ sizeof(rdatasetheader_t), 0);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
goto unlock;
|
||
|
}
|
||
|
@@ -556,7 +556,11 @@ static dns_dbmethods_t ecdb_methods = {
|
||
|
NULL, /* getsize */
|
||
|
NULL, /* setservestalettl */
|
||
|
NULL, /* getservestalettl */
|
||
|
- NULL /* setgluecachestats */
|
||
|
+ NULL, /* setservestalerefresh */
|
||
|
+ NULL, /* getservestalerefresh */
|
||
|
+ NULL, /* setgluecachestats */
|
||
|
+ NULL, /* adjusthashsize */
|
||
|
+ NULL /* setmaxrrperset */
|
||
|
};
|
||
|
|
||
|
static isc_result_t
|
||
|
diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h
|
||
|
index 22e94da9d5..3fa2a891e0 100644
|
||
|
--- a/lib/dns/include/dns/cache.h
|
||
|
+++ b/lib/dns/include/dns/cache.h
|
||
|
@@ -337,6 +337,12 @@ dns_cache_updatestats(dns_cache_t *cache, isc_result_t result);
|
||
|
* Update cache statistics based on result code in 'result'
|
||
|
*/
|
||
|
|
||
|
+void
|
||
|
+dns_cache_setmaxrrperset(dns_cache_t *cache, uint32_t value);
|
||
|
+/*%<
|
||
|
+ * Set the maximum resource records per RRSet that can be cached.
|
||
|
+ */
|
||
|
+
|
||
|
#ifdef HAVE_LIBXML2
|
||
|
int
|
||
|
dns_cache_renderxml(dns_cache_t *cache, void *writer0);
|
||
|
diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h
|
||
|
index 90bd7fb112..732bfe473d 100644
|
||
|
--- a/lib/dns/include/dns/db.h
|
||
|
+++ b/lib/dns/include/dns/db.h
|
||
|
@@ -182,6 +182,7 @@ typedef struct dns_dbmethods {
|
||
|
isc_result_t (*getservestalerefresh)(dns_db_t *db, uint32_t *interval);
|
||
|
isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
|
||
|
isc_result_t (*adjusthashsize)(dns_db_t *db, size_t size);
|
||
|
+ void (*setmaxrrperset)(dns_db_t *db, uint32_t value);
|
||
|
} dns_dbmethods_t;
|
||
|
|
||
|
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
|
||
|
@@ -1783,6 +1784,13 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats);
|
||
|
* dns_rdatasetstats_create(); otherwise NULL.
|
||
|
*/
|
||
|
|
||
|
+void
|
||
|
+dns_db_setmaxrrperset(dns_db_t *db, uint32_t value);
|
||
|
+/*%<
|
||
|
+ * Set the maximum permissible number of RRs per RRset. If 'value'
|
||
|
+ * is nonzero, then any subsequent attempt to add an rdataset with
|
||
|
+ * more than 'value' RRs will return ISC_R_NOSPACE.
|
||
|
+ */
|
||
|
ISC_LANG_ENDDECLS
|
||
|
|
||
|
#endif /* DNS_DB_H */
|
||
|
diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h
|
||
|
index 5a22f099c3..f2f3513a19 100644
|
||
|
--- a/lib/dns/include/dns/rdataslab.h
|
||
|
+++ b/lib/dns/include/dns/rdataslab.h
|
||
|
@@ -65,7 +65,8 @@ ISC_LANG_BEGINDECLS
|
||
|
|
||
|
isc_result_t
|
||
|
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||
|
- isc_region_t *region, unsigned int reservelen);
|
||
|
+ isc_region_t *region, unsigned int reservelen,
|
||
|
+ uint32_t limit);
|
||
|
/*%<
|
||
|
* Slabify a rdataset. The slab area will be allocated and returned
|
||
|
* in 'region'.
|
||
|
@@ -121,7 +122,8 @@ isc_result_t
|
||
|
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||
|
unsigned int reservelen, isc_mem_t *mctx,
|
||
|
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
||
|
- unsigned int flags, unsigned char **tslabp);
|
||
|
+ unsigned int flags, uint32_t maxrrperset,
|
||
|
+ unsigned char **tslabp);
|
||
|
/*%<
|
||
|
* Merge 'oslab' and 'nslab'.
|
||
|
*/
|
||
|
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
|
||
|
index 2cf7eced16..0d502f4dd2 100644
|
||
|
--- a/lib/dns/include/dns/view.h
|
||
|
+++ b/lib/dns/include/dns/view.h
|
||
|
@@ -186,6 +186,7 @@ struct dns_view {
|
||
|
dns_dlzdblist_t dlz_unsearched;
|
||
|
uint32_t fail_ttl;
|
||
|
dns_badcache_t *failcache;
|
||
|
+ uint32_t maxrrperset;
|
||
|
|
||
|
/*
|
||
|
* Configurable data for server use only,
|
||
|
@@ -1339,6 +1340,12 @@ dns_view_staleanswerenabled(dns_view_t *view);
|
||
|
*\li 'view' to be valid.
|
||
|
*/
|
||
|
|
||
|
+void
|
||
|
+dns_view_setmaxrrperset(dns_view_t *view, uint32_t value);
|
||
|
+/*%<
|
||
|
+ * Set the maximum resource records per RRSet that can be cached.
|
||
|
+ */
|
||
|
+
|
||
|
ISC_LANG_ENDDECLS
|
||
|
|
||
|
#endif /* DNS_VIEW_H */
|
||
|
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
|
||
|
index 08e2263c5b..e902043357 100644
|
||
|
--- a/lib/dns/include/dns/zone.h
|
||
|
+++ b/lib/dns/include/dns/zone.h
|
||
|
@@ -162,6 +162,19 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx);
|
||
|
*\li #ISC_R_UNEXPECTED
|
||
|
*/
|
||
|
|
||
|
+isc_result_t
|
||
|
+dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp);
|
||
|
+/*%<
|
||
|
+ * Creates a new empty database for the 'zone'.
|
||
|
+ *
|
||
|
+ * Requires:
|
||
|
+ *\li 'zone' to be a valid zone.
|
||
|
+ *\li 'dbp' to point to NULL pointer.
|
||
|
+ *
|
||
|
+ * Returns:
|
||
|
+ *\li dns_db_create() error codes.
|
||
|
+ */
|
||
|
+
|
||
|
void
|
||
|
dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass);
|
||
|
/*%<
|
||
|
@@ -330,6 +343,19 @@ dns_zone_getmaxrecords(dns_zone_t *zone);
|
||
|
*\li uint32_t maxrecords.
|
||
|
*/
|
||
|
|
||
|
+void
|
||
|
+dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t maxrrperset);
|
||
|
+/*%<
|
||
|
+ * Sets the maximum number of records per rrset permitted in a zone.
|
||
|
+ * 0 implies unlimited.
|
||
|
+ *
|
||
|
+ * Requires:
|
||
|
+ *\li 'zone' to be valid initialised zone.
|
||
|
+ *
|
||
|
+ * Returns:
|
||
|
+ *\li void
|
||
|
+ */
|
||
|
+
|
||
|
void
|
||
|
dns_zone_setmaxttl(dns_zone_t *zone, uint32_t maxttl);
|
||
|
/*%<
|
||
|
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
|
||
|
index e840c0665d..ca71bb9c03 100644
|
||
|
--- a/lib/dns/rbtdb.c
|
||
|
+++ b/lib/dns/rbtdb.c
|
||
|
@@ -482,6 +482,7 @@ struct dns_rbtdb {
|
||
|
rbtdb_serial_t current_serial;
|
||
|
rbtdb_serial_t least_serial;
|
||
|
rbtdb_serial_t next_serial;
|
||
|
+ uint32_t maxrrperset;
|
||
|
rbtdb_version_t *current_version;
|
||
|
rbtdb_version_t *future_version;
|
||
|
rbtdb_versionlist_t open_versions;
|
||
|
@@ -6495,7 +6496,7 @@ find_header:
|
||
|
rbtdb->common.mctx,
|
||
|
rbtdb->common.rdclass,
|
||
|
(dns_rdatatype_t)header->type, flags,
|
||
|
- &merged);
|
||
|
+ rbtdb->maxrrperset, &merged);
|
||
|
}
|
||
|
if (result == ISC_R_SUCCESS) {
|
||
|
/*
|
||
|
@@ -6880,7 +6881,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||
|
|
||
|
static inline isc_result_t
|
||
|
addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||
|
- dns_rdataset_t *rdataset) {
|
||
|
+ uint32_t maxrrperset, dns_rdataset_t *rdataset) {
|
||
|
struct noqname *noqname;
|
||
|
isc_mem_t *mctx = rbtdb->common.mctx;
|
||
|
dns_name_t name;
|
||
|
@@ -6901,12 +6902,12 @@ addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||
|
noqname->negsig = NULL;
|
||
|
noqname->type = neg.type;
|
||
|
dns_name_dup(&name, mctx, &noqname->name);
|
||
|
- result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
|
||
|
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0, maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
noqname->neg = r.base;
|
||
|
- result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
|
||
|
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0, maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
@@ -6925,7 +6926,7 @@ cleanup:
|
||
|
|
||
|
static inline isc_result_t
|
||
|
addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||
|
- dns_rdataset_t *rdataset) {
|
||
|
+ uint32_t maxrrperset, dns_rdataset_t *rdataset) {
|
||
|
struct noqname *closest;
|
||
|
isc_mem_t *mctx = rbtdb->common.mctx;
|
||
|
dns_name_t name;
|
||
|
@@ -6946,12 +6947,12 @@ addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
|
||
|
closest->negsig = NULL;
|
||
|
closest->type = neg.type;
|
||
|
dns_name_dup(&name, mctx, &closest->name);
|
||
|
- result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
|
||
|
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0, maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
closest->neg = r.base;
|
||
|
- result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
|
||
|
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0, maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
@@ -7028,7 +7029,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||
|
}
|
||
|
|
||
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||
|
- ®ion, sizeof(rdatasetheader_t));
|
||
|
+ ®ion, sizeof(rdatasetheader_t),
|
||
|
+ rbtdb->maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
return (result);
|
||
|
}
|
||
|
@@ -7086,7 +7088,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||
|
RDATASET_ATTR_SET(newheader, RDATASET_ATTR_OPTOUT);
|
||
|
}
|
||
|
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
|
||
|
- result = addnoqname(rbtdb, newheader, rdataset);
|
||
|
+ result = addnoqname(rbtdb, newheader,
|
||
|
+ rbtdb->maxrrperset, rdataset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
free_rdataset(rbtdb, rbtdb->common.mctx,
|
||
|
newheader);
|
||
|
@@ -7094,7 +7097,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||
|
}
|
||
|
}
|
||
|
if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
|
||
|
- result = addclosest(rbtdb, newheader, rdataset);
|
||
|
+ result = addclosest(rbtdb, newheader,
|
||
|
+ rbtdb->maxrrperset, rdataset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
free_rdataset(rbtdb, rbtdb->common.mctx,
|
||
|
newheader);
|
||
|
@@ -7261,7 +7265,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||
|
nodefullname(db, node, nodename);
|
||
|
|
||
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||
|
- ®ion, sizeof(rdatasetheader_t));
|
||
|
+ ®ion, sizeof(rdatasetheader_t),
|
||
|
+ 0);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
return (result);
|
||
|
}
|
||
|
@@ -7669,7 +7674,8 @@ loading_addrdataset(void *arg, const dns_name_t *name,
|
||
|
}
|
||
|
|
||
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||
|
- ®ion, sizeof(rdatasetheader_t));
|
||
|
+ ®ion, sizeof(rdatasetheader_t),
|
||
|
+ rbtdb->maxrrperset);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
return (result);
|
||
|
}
|
||
|
@@ -8608,6 +8614,15 @@ setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
||
|
return (ISC_R_SUCCESS);
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+setmaxrrperset(dns_db_t *db, uint32_t maxrrperset) {
|
||
|
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||
|
+
|
||
|
+ REQUIRE(VALID_RBTDB(rbtdb));
|
||
|
+
|
||
|
+ rbtdb->maxrrperset = maxrrperset;
|
||
|
+}
|
||
|
+
|
||
|
static dns_stats_t *
|
||
|
getrrsetstats(dns_db_t *db) {
|
||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||
|
@@ -8731,7 +8746,8 @@ static dns_dbmethods_t zone_methods = { attach,
|
||
|
NULL, /* setservestalerefresh */
|
||
|
NULL, /* getservestalerefresh */
|
||
|
setgluecachestats,
|
||
|
- adjusthashsize };
|
||
|
+ adjusthashsize,
|
||
|
+ setmaxrrperset };
|
||
|
|
||
|
static dns_dbmethods_t cache_methods = { attach,
|
||
|
detach,
|
||
|
@@ -8783,7 +8799,8 @@ static dns_dbmethods_t cache_methods = { attach,
|
||
|
setservestalerefresh,
|
||
|
getservestalerefresh,
|
||
|
NULL,
|
||
|
- adjusthashsize };
|
||
|
+ adjusthashsize,
|
||
|
+ setmaxrrperset };
|
||
|
|
||
|
isc_result_t
|
||
|
dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||
|
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
|
||
|
index dda903819a..b2d1e1cddb 100644
|
||
|
--- a/lib/dns/rdataslab.c
|
||
|
+++ b/lib/dns/rdataslab.c
|
||
|
@@ -116,7 +116,8 @@ fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
|
||
|
|
||
|
isc_result_t
|
||
|
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||
|
- isc_region_t *region, unsigned int reservelen) {
|
||
|
+ isc_region_t *region, unsigned int reservelen,
|
||
|
+ uint32_t maxrrperset) {
|
||
|
/*
|
||
|
* Use &removed as a sentinel pointer for duplicate
|
||
|
* rdata as rdata.data == NULL is valid.
|
||
|
@@ -158,7 +159,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||
|
return (ISC_R_SUCCESS);
|
||
|
}
|
||
|
|
||
|
- if (nitems > DNS_RDATASET_MAX_RECORDS) {
|
||
|
+ if (maxrrperset > 0 && nitems > maxrrperset) {
|
||
|
return (DNS_R_TOOMANYRECORDS);
|
||
|
}
|
||
|
|
||
|
@@ -488,7 +489,8 @@ isc_result_t
|
||
|
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||
|
unsigned int reservelen, isc_mem_t *mctx,
|
||
|
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
||
|
- unsigned int flags, unsigned char **tslabp) {
|
||
|
+ unsigned int flags, uint32_t maxrrperset,
|
||
|
+ unsigned char **tslabp) {
|
||
|
unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
|
||
|
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
|
||
|
dns_rdata_t ordata = DNS_RDATA_INIT;
|
||
|
@@ -528,7 +530,7 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||
|
#endif /* if DNS_RDATASET_FIXED */
|
||
|
INSIST(ocount > 0 && ncount > 0);
|
||
|
|
||
|
- if (ocount + ncount > DNS_RDATASET_MAX_RECORDS) {
|
||
|
+ if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
|
||
|
return (DNS_R_TOOMANYRECORDS);
|
||
|
}
|
||
|
|
||
|
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
|
||
|
index d9de422409..84cd324fb4 100644
|
||
|
--- a/lib/dns/sdb.c
|
||
|
+++ b/lib/dns/sdb.c
|
||
|
@@ -1312,7 +1312,8 @@ static dns_dbmethods_t sdb_methods = {
|
||
|
NULL, /* setservestalerefresh */
|
||
|
NULL, /* getservestalerefresh */
|
||
|
NULL, /* setgluecachestats */
|
||
|
- NULL /* adjusthashsize */
|
||
|
+ NULL, /* adjusthashsize */
|
||
|
+ NULL /* setmaxrrperset */
|
||
|
};
|
||
|
|
||
|
static isc_result_t
|
||
|
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
|
||
|
index c8a615a0f3..60a1d23b3b 100644
|
||
|
--- a/lib/dns/sdlz.c
|
||
|
+++ b/lib/dns/sdlz.c
|
||
|
@@ -1284,7 +1284,8 @@ static dns_dbmethods_t sdlzdb_methods = {
|
||
|
NULL, /* setservestalerefresh */
|
||
|
NULL, /* getservestalerefresh */
|
||
|
NULL, /* setgluecachestats */
|
||
|
- NULL /* adjusthashsize */
|
||
|
+ NULL, /* adjusthashsize */
|
||
|
+ NULL /* setmaxrrperset */
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
diff --git a/lib/dns/view.c b/lib/dns/view.c
|
||
|
index dcb0f1804e..a672aa8bc8 100644
|
||
|
--- a/lib/dns/view.c
|
||
|
+++ b/lib/dns/view.c
|
||
|
@@ -869,6 +869,8 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
|
||
|
dns_cache_attach(cache, &view->cache);
|
||
|
dns_cache_attachdb(cache, &view->cachedb);
|
||
|
INSIST(DNS_DB_VALID(view->cachedb));
|
||
|
+
|
||
|
+ dns_cache_setmaxrrperset(view->cache, view->maxrrperset);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
@@ -2544,3 +2546,12 @@ dns_view_staleanswerenabled(dns_view_t *view) {
|
||
|
|
||
|
return (result);
|
||
|
}
|
||
|
+
|
||
|
+void
|
||
|
+dns_view_setmaxrrperset(dns_view_t *view, uint32_t value) {
|
||
|
+ REQUIRE(DNS_VIEW_VALID(view));
|
||
|
+ view->maxrrperset = value;
|
||
|
+ if (view->cache != NULL) {
|
||
|
+ dns_cache_setmaxrrperset(view->cache, value);
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
|
||
|
index a4569f545c..c61e8f5f6b 100644
|
||
|
--- a/lib/dns/xfrin.c
|
||
|
+++ b/lib/dns/xfrin.c
|
||
|
@@ -203,8 +203,6 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task,
|
||
|
static isc_result_t
|
||
|
axfr_init(dns_xfrin_ctx_t *xfr);
|
||
|
static isc_result_t
|
||
|
-axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
|
||
|
-static isc_result_t
|
||
|
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
|
||
|
dns_ttl_t ttl, dns_rdata_t *rdata);
|
||
|
static isc_result_t
|
||
|
@@ -277,7 +275,11 @@ axfr_init(dns_xfrin_ctx_t *xfr) {
|
||
|
dns_db_detach(&xfr->db);
|
||
|
}
|
||
|
|
||
|
- CHECK(axfr_makedb(xfr, &xfr->db));
|
||
|
+ CHECK(dns_zone_makedb(xfr->zone, &xfr->db));
|
||
|
+
|
||
|
+ dns_zone_rpz_enable_db(xfr->zone, xfr->db);
|
||
|
+ dns_zone_catz_enable_db(xfr->zone, xfr->db);
|
||
|
+
|
||
|
dns_rdatacallbacks_init(&xfr->axfr);
|
||
|
CHECK(dns_db_beginload(xfr->db, &xfr->axfr));
|
||
|
result = ISC_R_SUCCESS;
|
||
|
@@ -285,22 +287,6 @@ failure:
|
||
|
return (result);
|
||
|
}
|
||
|
|
||
|
-static isc_result_t
|
||
|
-axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
|
||
|
- isc_result_t result;
|
||
|
-
|
||
|
- result = dns_db_create(xfr->mctx, /* XXX */
|
||
|
- "rbt", /* XXX guess */
|
||
|
- &xfr->name, dns_dbtype_zone, xfr->rdclass, 0,
|
||
|
- NULL, /* XXX guess */
|
||
|
- dbp);
|
||
|
- if (result == ISC_R_SUCCESS) {
|
||
|
- dns_zone_rpz_enable_db(xfr->zone, *dbp);
|
||
|
- dns_zone_catz_enable_db(xfr->zone, *dbp);
|
||
|
- }
|
||
|
- return (result);
|
||
|
-}
|
||
|
-
|
||
|
static isc_result_t
|
||
|
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
|
||
|
dns_ttl_t ttl, dns_rdata_t *rdata) {
|
||
|
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
|
||
|
index 65a3aacab7..5c8d97ed18 100644
|
||
|
--- a/lib/dns/zone.c
|
||
|
+++ b/lib/dns/zone.c
|
||
|
@@ -276,6 +276,7 @@ struct dns_zone {
|
||
|
uint32_t minretry;
|
||
|
|
||
|
uint32_t maxrecords;
|
||
|
+ uint32_t maxrrperset;
|
||
|
|
||
|
isc_sockaddr_t *masters;
|
||
|
isc_dscp_t *masterdscps;
|
||
|
@@ -2254,31 +2255,13 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
|
||
|
dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
|
||
|
"starting load");
|
||
|
|
||
|
- result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
|
||
|
- (zone->type == dns_zone_stub) ? dns_dbtype_stub
|
||
|
- : dns_dbtype_zone,
|
||
|
- zone->rdclass, zone->db_argc - 1,
|
||
|
- zone->db_argv + 1, &db);
|
||
|
-
|
||
|
+ result = dns_zone_makedb(zone, &db);
|
||
|
if (result != ISC_R_SUCCESS) {
|
||
|
dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
|
||
|
"loading zone: creating database: %s",
|
||
|
isc_result_totext(result));
|
||
|
goto cleanup;
|
||
|
}
|
||
|
- dns_db_settask(db, zone->task);
|
||
|
-
|
||
|
- if (zone->type == dns_zone_primary ||
|
||
|
- zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
|
||
|
- {
|
||
|
- result = dns_db_setgluecachestats(db, zone->gluecachestats);
|
||
|
- if (result == ISC_R_NOTIMPLEMENTED) {
|
||
|
- result = ISC_R_SUCCESS;
|
||
|
- }
|
||
|
- if (result != ISC_R_SUCCESS) {
|
||
|
- goto cleanup;
|
||
|
- }
|
||
|
- }
|
||
|
|
||
|
if (!dns_db_ispersistent(db)) {
|
||
|
if (zone->masterfile != NULL) {
|
||
|
@@ -12175,6 +12158,16 @@ dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
|
||
|
zone->maxrecords = val;
|
||
|
}
|
||
|
|
||
|
+void
|
||
|
+dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
|
||
|
+ REQUIRE(DNS_ZONE_VALID(zone));
|
||
|
+
|
||
|
+ zone->maxrrperset = val;
|
||
|
+ if (zone->db != NULL) {
|
||
|
+ dns_db_setmaxrrperset(zone->db, val);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
static bool
|
||
|
notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
|
||
|
isc_sockaddr_t *addr, dns_tsigkey_t *key) {
|
||
|
@@ -14579,6 +14572,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
dns_db_settask(stub->db, zone->task);
|
||
|
+ dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
|
||
|
}
|
||
|
|
||
|
result = dns_db_newversion(stub->db, &stub->version);
|
||
|
@@ -17300,6 +17294,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
|
||
|
}
|
||
|
zone_attachdb(zone, db);
|
||
|
dns_db_settask(zone->db, zone->task);
|
||
|
+ dns_db_setmaxrrperset(zone->db, zone->maxrrperset);
|
||
|
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
|
||
|
return (ISC_R_SUCCESS);
|
||
|
|
||
|
@@ -23413,3 +23408,44 @@ zone_nsecttl(dns_zone_t *zone) {
|
||
|
|
||
|
return (ISC_MIN(zone->minimum, zone->soattl));
|
||
|
}
|
||
|
+
|
||
|
+isc_result_t
|
||
|
+dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
|
||
|
+ REQUIRE(DNS_ZONE_VALID(zone));
|
||
|
+ REQUIRE(dbp != NULL && *dbp == NULL);
|
||
|
+
|
||
|
+ dns_db_t *db = NULL;
|
||
|
+
|
||
|
+ isc_result_t result = dns_db_create(
|
||
|
+ zone->mctx, zone->db_argv[0], &zone->origin,
|
||
|
+ (zone->type == dns_zone_stub) ? dns_dbtype_stub
|
||
|
+ : dns_dbtype_zone,
|
||
|
+ zone->rdclass, zone->db_argc - 1, zone->db_argv + 1, &db);
|
||
|
+ if (result != ISC_R_SUCCESS) {
|
||
|
+ return (result);
|
||
|
+ }
|
||
|
+
|
||
|
+ switch (zone->type) {
|
||
|
+ case dns_zone_primary:
|
||
|
+ case dns_zone_secondary:
|
||
|
+ case dns_zone_mirror:
|
||
|
+ result = dns_db_setgluecachestats(db, zone->gluecachestats);
|
||
|
+ if (result == ISC_R_NOTIMPLEMENTED) {
|
||
|
+ result = ISC_R_SUCCESS;
|
||
|
+ }
|
||
|
+ if (result != ISC_R_SUCCESS) {
|
||
|
+ dns_db_detach(&db);
|
||
|
+ return (result);
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ break;
|
||
|
+ }
|
||
|
+
|
||
|
+ dns_db_settask(db, zone->task);
|
||
|
+ dns_db_setmaxrrperset(db, zone->maxrrperset);
|
||
|
+
|
||
|
+ *dbp = db;
|
||
|
+
|
||
|
+ return (ISC_R_SUCCESS);
|
||
|
+}
|
||
|
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
|
||
|
index aab0462936..dce30537dd 100644
|
||
|
--- a/lib/isccfg/namedconf.c
|
||
|
+++ b/lib/isccfg/namedconf.c
|
||
|
@@ -2236,6 +2236,9 @@ static cfg_clausedef_t zone_clauses[] = {
|
||
|
{ "max-records", &cfg_type_uint32,
|
||
|
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||
|
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
||
|
+ { "max-records-per-type", &cfg_type_uint32,
|
||
|
+ CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||
|
+ CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
||
|
{ "max-refresh-time", &cfg_type_uint32,
|
||
|
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||
|
{ "max-retry-time", &cfg_type_uint32,
|
||
|
--
|
||
|
2.45.2
|
||
|
|