1501 lines
47 KiB
Diff
1501 lines
47 KiB
Diff
|
|
From 39d3e2a8ecc1cb4dccefa3ddea477a2887989485 Mon Sep 17 00:00:00 2001
|
||
|
|
From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org>
|
||
|
|
Date: Sat, 25 May 2024 11:46:56 +0200
|
||
|
|
Subject: [PATCH] Add a limit to the number of RR types for single name
|
||
|
|
|
||
|
|
Previously, the number of RR types for a single owner name was limited
|
||
|
|
only by the maximum number of the types (64k). As the data structure
|
||
|
|
that holds the RR types for the database node is just a linked list, and
|
||
|
|
there are places where we just walk through the whole list (again and
|
||
|
|
again), adding a large number of RR types for a single owner named with
|
||
|
|
would slow down processing of such name (database node).
|
||
|
|
|
||
|
|
Add a configurable limit to cap the number of the RR types for a single
|
||
|
|
owner. This is enforced at the database (rbtdb, qpzone, qpcache) level
|
||
|
|
and configured with new max-types-per-name configuration option that
|
||
|
|
can be configured globally, per-view and per-zone.
|
||
|
|
|
||
|
|
(cherry picked from commit 00d16211d6368b99f070c1182d8c76b3798ca1db)
|
||
|
|
|
||
|
|
Conflict:Adaptation of the dns_db_settask Function Context
|
||
|
|
Reference:https://downloads.isc.org/isc/bind9/9.18.28/patches/0002-CVE-2024-1737.patch
|
||
|
|
|
||
|
|
|
||
|
|
---
|
||
|
|
bin/named/config.c | 2 +
|
||
|
|
bin/named/server.c | 18 ++++
|
||
|
|
bin/named/zoneconf.c | 16 +++
|
||
|
|
bin/tests/system/doth/ns2/named.conf.in | 1 +
|
||
|
|
bin/tests/system/doth/ns3/named.conf.in | 1 +
|
||
|
|
bin/tests/system/doth/ns4/named.conf.in | 1 +
|
||
|
|
bin/tests/system/doth/ns5/named.conf.in | 1 +
|
||
|
|
bin/tests/system/dyndb/driver/db.c | 69 ++++++++----
|
||
|
|
doc/arm/reference.rst | 30 ++++++
|
||
|
|
doc/misc/mirror.zoneopt | 2 +
|
||
|
|
doc/misc/options | 4 +
|
||
|
|
doc/misc/primary.zoneopt | 2 +
|
||
|
|
doc/misc/redirect.zoneopt | 2 +
|
||
|
|
doc/misc/secondary.zoneopt | 2 +
|
||
|
|
doc/misc/static-stub.zoneopt | 2 +
|
||
|
|
doc/misc/stub.zoneopt | 2 +
|
||
|
|
lib/dns/cache.c | 24 +++++
|
||
|
|
lib/dns/db.c | 18 ++++
|
||
|
|
lib/dns/dnsrps.c | 2 +
|
||
|
|
lib/dns/include/dns/cache.h | 12 +++
|
||
|
|
lib/dns/include/dns/db.h | 19 ++++
|
||
|
|
lib/dns/include/dns/rdataslab.h | 6 +-
|
||
|
|
lib/dns/include/dns/view.h | 14 +++
|
||
|
|
lib/dns/include/dns/zone.h | 39 +++++++
|
||
|
|
lib/dns/rbtdb.c | 138 +++++++++++++++++++++---
|
||
|
|
lib/dns/rdataslab.c | 14 ++-
|
||
|
|
lib/dns/sdb.c | 46 +++++---
|
||
|
|
lib/dns/sdlz.c | 79 +++++++++-----
|
||
|
|
lib/dns/view.c | 21 ++++
|
||
|
|
lib/dns/xfrin.c | 24 +----
|
||
|
|
lib/dns/zone.c | 96 +++++++++++++----
|
||
|
|
lib/isccfg/namedconf.c | 6 ++
|
||
|
|
lib/ns/update.c | 15 ++-
|
||
|
|
33 files changed, 602 insertions(+), 126 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/bin/named/config.c b/bin/named/config.c
|
||
|
|
index f95e433..af8637e 100644
|
||
|
|
--- a/bin/named/config.c
|
||
|
|
+++ b/bin/named/config.c
|
||
|
|
@@ -233,8 +233,10 @@ 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-types-per-name 100;\n\
|
||
|
|
max-transfer-idle-in 60;\n\
|
||
|
|
max-transfer-idle-out 60;\n\
|
||
|
|
max-transfer-time-in 120;\n\
|
||
|
|
diff --git a/bin/named/server.c b/bin/named/server.c
|
||
|
|
index bfe6df3..8d7f56e 100644
|
||
|
|
--- a/bin/named/server.c
|
||
|
|
+++ b/bin/named/server.c
|
||
|
|
@@ -5563,6 +5563,24 @@ 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));
|
||
|
|
+
|
||
|
|
+ /*
|
||
|
|
+ * This is used for the cache and also as a default value
|
||
|
|
+ * for zone databases.
|
||
|
|
+ */
|
||
|
|
+ obj = NULL;
|
||
|
|
+ result = named_config_get(maps, "max-types-per-name", &obj);
|
||
|
|
+ INSIST(result == ISC_R_SUCCESS);
|
||
|
|
+ dns_view_setmaxtypepername(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 44c2242..384a81e 100644
|
||
|
|
--- a/bin/named/zoneconf.c
|
||
|
|
+++ b/bin/named/zoneconf.c
|
||
|
|
@@ -1083,6 +1083,22 @@ 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);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ obj = NULL;
|
||
|
|
+ result = named_config_get(maps, "max-types-per-name", &obj);
|
||
|
|
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||
|
|
+ dns_zone_setmaxtypepername(mayberaw, cfg_obj_asuint32(obj));
|
||
|
|
+ if (zone != mayberaw) {
|
||
|
|
+ dns_zone_setmaxtypepername(zone, 0);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
if (raw != NULL && filename != NULL) {
|
||
|
|
#define SIGNED ".signed"
|
||
|
|
size_t signedlen = strlen(filename) + sizeof(SIGNED);
|
||
|
|
diff --git a/bin/tests/system/doth/ns2/named.conf.in b/bin/tests/system/doth/ns2/named.conf.in
|
||
|
|
index e533f47..f10dac5 100644
|
||
|
|
--- a/bin/tests/system/doth/ns2/named.conf.in
|
||
|
|
+++ b/bin/tests/system/doth/ns2/named.conf.in
|
||
|
|
@@ -49,6 +49,7 @@ options {
|
||
|
|
ixfr-from-differences yes;
|
||
|
|
check-integrity no;
|
||
|
|
dnssec-validation yes;
|
||
|
|
+ max-records-per-type 0;
|
||
|
|
transfers-in 100;
|
||
|
|
transfers-out 100;
|
||
|
|
};
|
||
|
|
diff --git a/bin/tests/system/doth/ns3/named.conf.in b/bin/tests/system/doth/ns3/named.conf.in
|
||
|
|
index cd1ab9c..cd9fc63 100644
|
||
|
|
--- a/bin/tests/system/doth/ns3/named.conf.in
|
||
|
|
+++ b/bin/tests/system/doth/ns3/named.conf.in
|
||
|
|
@@ -44,6 +44,7 @@ options {
|
||
|
|
ixfr-from-differences yes;
|
||
|
|
check-integrity no;
|
||
|
|
dnssec-validation yes;
|
||
|
|
+ max-records-per-type 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
zone "." {
|
||
|
|
diff --git a/bin/tests/system/doth/ns4/named.conf.in b/bin/tests/system/doth/ns4/named.conf.in
|
||
|
|
index c7c6c91..43b7c78 100644
|
||
|
|
--- a/bin/tests/system/doth/ns4/named.conf.in
|
||
|
|
+++ b/bin/tests/system/doth/ns4/named.conf.in
|
||
|
|
@@ -52,6 +52,7 @@ options {
|
||
|
|
ixfr-from-differences yes;
|
||
|
|
check-integrity no;
|
||
|
|
dnssec-validation yes;
|
||
|
|
+ max-records-per-type 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
zone "." {
|
||
|
|
diff --git a/bin/tests/system/doth/ns5/named.conf.in b/bin/tests/system/doth/ns5/named.conf.in
|
||
|
|
index 6808618..9323637 100644
|
||
|
|
--- a/bin/tests/system/doth/ns5/named.conf.in
|
||
|
|
+++ b/bin/tests/system/doth/ns5/named.conf.in
|
||
|
|
@@ -40,6 +40,7 @@ options {
|
||
|
|
ixfr-from-differences yes;
|
||
|
|
check-integrity no;
|
||
|
|
dnssec-validation yes;
|
||
|
|
+ max-records-per-type 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
zone "." {
|
||
|
|
diff --git a/bin/tests/system/dyndb/driver/db.c b/bin/tests/system/dyndb/driver/db.c
|
||
|
|
index 334fd54..d34d1e0 100644
|
||
|
|
--- a/bin/tests/system/dyndb/driver/db.c
|
||
|
|
+++ b/bin/tests/system/dyndb/driver/db.c
|
||
|
|
@@ -563,28 +563,57 @@ hashsize(dns_db_t *db) {
|
||
|
|
* determine which implementation of dns_db_*() function to call.
|
||
|
|
*/
|
||
|
|
static dns_dbmethods_t sampledb_methods = {
|
||
|
|
- attach, detach, beginload,
|
||
|
|
- endload, dump, currentversion,
|
||
|
|
- newversion, attachversion, closeversion,
|
||
|
|
- findnode, find, findzonecut,
|
||
|
|
- attachnode, detachnode, expirenode,
|
||
|
|
- printnode, createiterator, findrdataset,
|
||
|
|
- allrdatasets, addrdataset, subtractrdataset,
|
||
|
|
- deleterdataset, issecure, nodecount,
|
||
|
|
- ispersistent, overmem, settask,
|
||
|
|
- getoriginnode, transfernode, getnsec3parameters,
|
||
|
|
- findnsec3node, setsigningtime, getsigningtime,
|
||
|
|
- resigned, isdnssec, getrrsetstats,
|
||
|
|
+ attach,
|
||
|
|
+ detach,
|
||
|
|
+ beginload,
|
||
|
|
+ endload,
|
||
|
|
+ dump,
|
||
|
|
+ currentversion,
|
||
|
|
+ newversion,
|
||
|
|
+ attachversion,
|
||
|
|
+ closeversion,
|
||
|
|
+ findnode,
|
||
|
|
+ find,
|
||
|
|
+ findzonecut,
|
||
|
|
+ attachnode,
|
||
|
|
+ detachnode,
|
||
|
|
+ expirenode,
|
||
|
|
+ printnode,
|
||
|
|
+ createiterator,
|
||
|
|
+ findrdataset,
|
||
|
|
+ allrdatasets,
|
||
|
|
+ addrdataset,
|
||
|
|
+ subtractrdataset,
|
||
|
|
+ deleterdataset,
|
||
|
|
+ issecure,
|
||
|
|
+ nodecount,
|
||
|
|
+ ispersistent,
|
||
|
|
+ overmem,
|
||
|
|
+ settask,
|
||
|
|
+ getoriginnode,
|
||
|
|
+ transfernode,
|
||
|
|
+ getnsec3parameters,
|
||
|
|
+ findnsec3node,
|
||
|
|
+ setsigningtime,
|
||
|
|
+ getsigningtime,
|
||
|
|
+ resigned,
|
||
|
|
+ isdnssec,
|
||
|
|
+ getrrsetstats,
|
||
|
|
NULL, /* rpz_attach */
|
||
|
|
NULL, /* rpz_ready */
|
||
|
|
- findnodeext, findext, setcachestats,
|
||
|
|
- hashsize, NULL, /* nodefullname */
|
||
|
|
- NULL, /* getsize */
|
||
|
|
- NULL, /* setservestalettl */
|
||
|
|
- NULL, /* getservestalettl */
|
||
|
|
- NULL, /* setservestalerefresh */
|
||
|
|
- NULL, /* getservestalerefresh */
|
||
|
|
- NULL, /* setgluecachestats */
|
||
|
|
+ findnodeext,
|
||
|
|
+ findext,
|
||
|
|
+ setcachestats,
|
||
|
|
+ hashsize,
|
||
|
|
+ NULL, /* nodefullname */
|
||
|
|
+ NULL, /* getsize */
|
||
|
|
+ NULL, /* setservestalettl */
|
||
|
|
+ NULL, /* getservestalettl */
|
||
|
|
+ NULL, /* setservestalerefresh */
|
||
|
|
+ NULL, /* getservestalerefresh */
|
||
|
|
+ NULL, /* setgluecachestats */
|
||
|
|
+ NULL, /* setmaxrrperset */
|
||
|
|
+ NULL /* setmaxtypepername */
|
||
|
|
};
|
||
|
|
|
||
|
|
/* Auxiliary driver functions. */
|
||
|
|
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
|
||
|
|
index e1b8228..29e246b 100644
|
||
|
|
--- a/doc/arm/reference.rst
|
||
|
|
+++ b/doc/arm/reference.rst
|
||
|
|
@@ -3766,6 +3766,36 @@ system.
|
||
|
|
This sets the maximum number of records permitted in a zone. The default is
|
||
|
|
zero, which means the maximum is unlimited.
|
||
|
|
|
||
|
|
+.. namedconf:statement:: max-records-per-type
|
||
|
|
+ :tags: server
|
||
|
|
+ :short: Sets the maximum number of records that can be stored in an RRset
|
||
|
|
+
|
||
|
|
+ This sets the maximum number of resource records that can be stored
|
||
|
|
+ in an RRset in a database. When configured in :namedconf:ref:`options`
|
||
|
|
+ or :namedconf:ref:`view`, it controls the cache database; it also sets
|
||
|
|
+ the default value for zone databases, which can be overridden by setting
|
||
|
|
+ it at the :namedconf:ref:`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.
|
||
|
|
+
|
||
|
|
+.. namedconf:statement:: max-types-per-name
|
||
|
|
+ :tags: server
|
||
|
|
+ :short: Sets the maximum number of RR types that can be stored for an owner name
|
||
|
|
+
|
||
|
|
+ This sets the maximum number of resource record types that can be stored
|
||
|
|
+ for a single owner name in a database. When configured in :namedconf:ref:`options`
|
||
|
|
+ or :namedconf:ref:`view`, it controls the cache database, and also sets
|
||
|
|
+ the default value for zone databases, which can be overridden by setting
|
||
|
|
+ it at the :namedconf:ref:`zone` level
|
||
|
|
+
|
||
|
|
+ If set to a positive value, any attempt to cache or to add to a zone an owner
|
||
|
|
+ name with more than the specified number of resource record types will result
|
||
|
|
+ in a failure. If set to 0, there is no cap on RR types number. The default is
|
||
|
|
+ 100.
|
||
|
|
+
|
||
|
|
.. namedconf:statement:: recursive-clients
|
||
|
|
:tags: query
|
||
|
|
:short: Specifies the maximum number of concurrent recursive queries the server can perform.
|
||
|
|
diff --git a/doc/misc/mirror.zoneopt b/doc/misc/mirror.zoneopt
|
||
|
|
index ac371cd..5f688ca 100644
|
||
|
|
--- a/doc/misc/mirror.zoneopt
|
||
|
|
+++ b/doc/misc/mirror.zoneopt
|
||
|
|
@@ -18,12 +18,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 a916701..5fe415d 100644
|
||
|
|
--- a/doc/misc/options
|
||
|
|
+++ b/doc/misc/options
|
||
|
|
@@ -180,6 +180,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>;
|
||
|
|
@@ -190,6 +191,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>;
|
||
|
|
@@ -470,6 +472,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>;
|
||
|
|
@@ -479,6 +482,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>;
|
||
|
|
diff --git a/doc/misc/primary.zoneopt b/doc/misc/primary.zoneopt
|
||
|
|
index 8f646e3..1de2f21 100644
|
||
|
|
--- a/doc/misc/primary.zoneopt
|
||
|
|
+++ b/doc/misc/primary.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/redirect.zoneopt b/doc/misc/redirect.zoneopt
|
||
|
|
index bcd9a57..9d238c1 100644
|
||
|
|
--- a/doc/misc/redirect.zoneopt
|
||
|
|
+++ b/doc/misc/redirect.zoneopt
|
||
|
|
@@ -7,6 +7,8 @@ zone <string> [ <class> ] {
|
||
|
|
masterfile-format ( raw | text );
|
||
|
|
masterfile-style ( full | relative );
|
||
|
|
max-records <integer>;
|
||
|
|
+ max-records-per-type <integer>;
|
||
|
|
+ max-types-per-name <integer>;
|
||
|
|
max-zone-ttl ( unlimited | <duration> );
|
||
|
|
primaries [ port <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||
|
|
zone-statistics ( full | terse | none | <boolean> );
|
||
|
|
diff --git a/doc/misc/secondary.zoneopt b/doc/misc/secondary.zoneopt
|
||
|
|
index 3237aab..169fa9b 100644
|
||
|
|
--- a/doc/misc/secondary.zoneopt
|
||
|
|
+++ b/doc/misc/secondary.zoneopt
|
||
|
|
@@ -30,12 +30,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 5357528..93a3220 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> ] { ( <ipv4_address> | <ipv6_address> ) [ port <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 29c1d56..2834682 100644
|
||
|
|
--- a/doc/misc/stub.zoneopt
|
||
|
|
+++ b/doc/misc/stub.zoneopt
|
||
|
|
@@ -12,10 +12,12 @@ zone <string> [ <class> ] {
|
||
|
|
masterfile-format ( raw | text );
|
||
|
|
masterfile-style ( full | relative );
|
||
|
|
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 7ffb6f8..782cf2b 100644
|
||
|
|
--- a/lib/dns/cache.c
|
||
|
|
+++ b/lib/dns/cache.c
|
||
|
|
@@ -144,6 +144,8 @@ struct dns_cache {
|
||
|
|
dns_ttl_t serve_stale_ttl;
|
||
|
|
dns_ttl_t serve_stale_refresh;
|
||
|
|
isc_stats_t *stats;
|
||
|
|
+ uint32_t maxrrperset;
|
||
|
|
+ uint32_t maxtypepername;
|
||
|
|
};
|
||
|
|
|
||
|
|
/***
|
||
|
|
@@ -175,6 +177,8 @@ cache_create_db(dns_cache_t *cache, dns_db_t **db) {
|
||
|
|
if (result == ISC_R_SUCCESS) {
|
||
|
|
dns_db_setservestalettl(*db, cache->serve_stale_ttl);
|
||
|
|
dns_db_setservestalerefresh(*db, cache->serve_stale_refresh);
|
||
|
|
+ dns_db_setmaxrrperset(*db, cache->maxrrperset);
|
||
|
|
+ dns_db_setmaxtypepername(*db, cache->maxtypepername);
|
||
|
|
}
|
||
|
|
return (result);
|
||
|
|
}
|
||
|
|
@@ -1194,6 +1198,26 @@ 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);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_cache_setmaxtypepername(dns_cache_t *cache, uint32_t value) {
|
||
|
|
+ REQUIRE(VALID_CACHE(cache));
|
||
|
|
+
|
||
|
|
+ cache->maxtypepername = value;
|
||
|
|
+ if (cache->db != NULL) {
|
||
|
|
+ dns_db_setmaxtypepername(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 c95d19a..85f6daa 100644
|
||
|
|
--- a/lib/dns/db.c
|
||
|
|
+++ b/lib/dns/db.c
|
||
|
|
@@ -1119,3 +1119,21 @@ 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);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_db_setmaxtypepername(dns_db_t *db, uint32_t value) {
|
||
|
|
+ REQUIRE(DNS_DB_VALID(db));
|
||
|
|
+
|
||
|
|
+ if (db->methods->setmaxtypepername != NULL) {
|
||
|
|
+ (db->methods->setmaxtypepername)(db, value);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
diff --git a/lib/dns/dnsrps.c b/lib/dns/dnsrps.c
|
||
|
|
index d4a1c65..73f11da 100644
|
||
|
|
--- a/lib/dns/dnsrps.c
|
||
|
|
+++ b/lib/dns/dnsrps.c
|
||
|
|
@@ -975,6 +975,8 @@ static dns_dbmethods_t rpsdb_db_methods = {
|
||
|
|
NULL, /* setservestalerefresh */
|
||
|
|
NULL, /* getservestalerefresh */
|
||
|
|
NULL, /* setgluecachestats */
|
||
|
|
+ NULL, /* setmaxrrperset */
|
||
|
|
+ NULL /* setmaxtypepername */
|
||
|
|
};
|
||
|
|
|
||
|
|
static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
|
||
|
|
diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h
|
||
|
|
index 8fc9657..91e94c0 100644
|
||
|
|
--- a/lib/dns/include/dns/cache.h
|
||
|
|
+++ b/lib/dns/include/dns/cache.h
|
||
|
|
@@ -283,6 +283,18 @@ 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.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_cache_setmaxtypepername(dns_cache_t *cache, uint32_t value);
|
||
|
|
+/*%<
|
||
|
|
+ * Set the maximum resource record types per owner name 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 9b53f04..b6e826b 100644
|
||
|
|
--- a/lib/dns/include/dns/db.h
|
||
|
|
+++ b/lib/dns/include/dns/db.h
|
||
|
|
@@ -185,6 +185,8 @@ typedef struct dns_dbmethods {
|
||
|
|
isc_result_t (*setservestalerefresh)(dns_db_t *db, uint32_t interval);
|
||
|
|
isc_result_t (*getservestalerefresh)(dns_db_t *db, uint32_t *interval);
|
||
|
|
isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
|
||
|
|
+ void (*setmaxrrperset)(dns_db_t *db, uint32_t value);
|
||
|
|
+ void (*setmaxtypepername)(dns_db_t *db, uint32_t value);
|
||
|
|
} dns_dbmethods_t;
|
||
|
|
|
||
|
|
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
|
||
|
|
@@ -1756,4 +1758,21 @@ 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.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_db_setmaxtypepername(dns_db_t *db, uint32_t value);
|
||
|
|
+/*%<
|
||
|
|
+ * Set the maximum permissible number of RR types per owner name.
|
||
|
|
+ *
|
||
|
|
+ * If 'value' is nonzero, then any subsequent attempt to add an rdataset with a
|
||
|
|
+ * RR type that would exceed the number of already stored RR types will return
|
||
|
|
+ * ISC_R_NOSPACE.
|
||
|
|
+ */
|
||
|
|
ISC_LANG_ENDDECLS
|
||
|
|
diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h
|
||
|
|
index 7364b8d..5729c00 100644
|
||
|
|
--- a/lib/dns/include/dns/rdataslab.h
|
||
|
|
+++ b/lib/dns/include/dns/rdataslab.h
|
||
|
|
@@ -66,7 +66,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'.
|
||
|
|
@@ -122,7 +123,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 18b0b33..516c209 100644
|
||
|
|
--- a/lib/dns/include/dns/view.h
|
||
|
|
+++ b/lib/dns/include/dns/view.h
|
||
|
|
@@ -191,6 +191,8 @@ struct dns_view {
|
||
|
|
dns_dlzdblist_t dlz_unsearched;
|
||
|
|
uint32_t fail_ttl;
|
||
|
|
dns_badcache_t *failcache;
|
||
|
|
+ uint32_t maxrrperset;
|
||
|
|
+ uint32_t maxtypepername;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Configurable data for server use only,
|
||
|
|
@@ -1413,4 +1415,16 @@ dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
|
||
|
|
*\li 'foundname' to be valid with a buffer sufficient to hold the name.
|
||
|
|
*/
|
||
|
|
|
||
|
|
+void
|
||
|
|
+dns_view_setmaxrrperset(dns_view_t *view, uint32_t value);
|
||
|
|
+/*%<
|
||
|
|
+ * Set the maximum resource records per RRSet that can be cached.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_view_setmaxtypepername(dns_view_t *view, uint32_t value);
|
||
|
|
+/*%<
|
||
|
|
+ * Set the maximum resource record types per owner name that can be cached.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
ISC_LANG_ENDDECLS
|
||
|
|
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
|
||
|
|
index 10ed86c..3449065 100644
|
||
|
|
--- a/lib/dns/include/dns/zone.h
|
||
|
|
+++ b/lib/dns/include/dns/zone.h
|
||
|
|
@@ -165,6 +165,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);
|
||
|
|
/*%<
|
||
|
|
@@ -350,6 +363,32 @@ 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_setmaxtypepername(dns_zone_t *zone, uint32_t maxtypepername);
|
||
|
|
+/*%<
|
||
|
|
+ * Sets the maximum number of resource record types per owner name
|
||
|
|
+ * 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 bc0f8d8..c22e021 100644
|
||
|
|
--- a/lib/dns/rbtdb.c
|
||
|
|
+++ b/lib/dns/rbtdb.c
|
||
|
|
@@ -450,6 +450,8 @@ struct dns_rbtdb {
|
||
|
|
rbtdb_serial_t current_serial;
|
||
|
|
rbtdb_serial_t least_serial;
|
||
|
|
rbtdb_serial_t next_serial;
|
||
|
|
+ uint32_t maxrrperset;
|
||
|
|
+ uint32_t maxtypepername;
|
||
|
|
rbtdb_version_t *current_version;
|
||
|
|
rbtdb_version_t *future_version;
|
||
|
|
rbtdb_versionlist_t open_versions;
|
||
|
|
@@ -913,6 +915,8 @@ prio_type(rbtdb_rdatatype_t type) {
|
||
|
|
case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_soa):
|
||
|
|
case dns_rdatatype_a:
|
||
|
|
case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_a):
|
||
|
|
+ case dns_rdatatype_mx:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_mx):
|
||
|
|
case dns_rdatatype_aaaa:
|
||
|
|
case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_aaaa):
|
||
|
|
case dns_rdatatype_nsec:
|
||
|
|
@@ -925,6 +929,22 @@ prio_type(rbtdb_rdatatype_t type) {
|
||
|
|
case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ds):
|
||
|
|
case dns_rdatatype_cname:
|
||
|
|
case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname):
|
||
|
|
+ case dns_rdatatype_dname:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname):
|
||
|
|
+ case dns_rdatatype_svcb:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_svcb):
|
||
|
|
+ case dns_rdatatype_https:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_https):
|
||
|
|
+ case dns_rdatatype_dnskey:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dnskey):
|
||
|
|
+ case dns_rdatatype_srv:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_srv):
|
||
|
|
+ case dns_rdatatype_txt:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_txt):
|
||
|
|
+ case dns_rdatatype_ptr:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ptr):
|
||
|
|
+ case dns_rdatatype_naptr:
|
||
|
|
+ case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_naptr):
|
||
|
|
return (true);
|
||
|
|
}
|
||
|
|
return (false);
|
||
|
|
@@ -6180,6 +6200,24 @@ update_recordsandxfrsize(bool add, rbtdb_version_t *rbtversion,
|
||
|
|
RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
|
||
|
|
}
|
||
|
|
|
||
|
|
+static bool
|
||
|
|
+overmaxtype(dns_rbtdb_t *rbtdb, uint32_t ntypes) {
|
||
|
|
+ if (rbtdb->maxtypepername == 0) {
|
||
|
|
+ return (false);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return (ntypes >= rbtdb->maxtypepername);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static bool
|
||
|
|
+prio_header(rdatasetheader_t *header) {
|
||
|
|
+ if (NEGATIVE(header) && prio_type(RBTDB_RDATATYPE_EXT(header->type))) {
|
||
|
|
+ return (true);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return (prio_type(header->type));
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/*
|
||
|
|
* write lock on rbtnode must be held.
|
||
|
|
*/
|
||
|
|
@@ -6191,7 +6229,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
|
||
|
|
rbtdb_changed_t *changed = NULL;
|
||
|
|
rdatasetheader_t *topheader = NULL, *topheader_prev = NULL;
|
||
|
|
rdatasetheader_t *header = NULL, *sigheader = NULL;
|
||
|
|
- rdatasetheader_t *prioheader = NULL;
|
||
|
|
+ rdatasetheader_t *prioheader = NULL, *expireheader = NULL;
|
||
|
|
unsigned char *merged = NULL;
|
||
|
|
isc_result_t result;
|
||
|
|
bool header_nx;
|
||
|
|
@@ -6201,6 +6239,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
|
||
|
|
rbtdb_rdatatype_t negtype, sigtype;
|
||
|
|
dns_trust_t trust;
|
||
|
|
int idx;
|
||
|
|
+ uint32_t ntypes = 0;
|
||
|
|
|
||
|
|
/*
|
||
|
|
* Add an rdatasetheader_t to a node.
|
||
|
|
@@ -6276,6 +6315,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
|
||
|
|
{
|
||
|
|
if (topheader->type == sigtype) {
|
||
|
|
sigheader = topheader;
|
||
|
|
+ break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
|
||
|
|
@@ -6338,7 +6378,13 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename,
|
||
|
|
for (topheader = rbtnode->data; topheader != NULL;
|
||
|
|
topheader = topheader->next)
|
||
|
|
{
|
||
|
|
- if (prio_type(topheader->type)) {
|
||
|
|
+ if (IS_CACHE(rbtdb) && ACTIVE(topheader, now)) {
|
||
|
|
+ ++ntypes;
|
||
|
|
+ expireheader = topheader;
|
||
|
|
+ } else if (!IS_CACHE(rbtdb)) {
|
||
|
|
+ ++ntypes;
|
||
|
|
+ }
|
||
|
|
+ if (prio_header(topheader)) {
|
||
|
|
prioheader = topheader;
|
||
|
|
}
|
||
|
|
if (topheader->type == newheader->type ||
|
||
|
|
@@ -6428,7 +6474,7 @@ find_header:
|
||
|
|
rbtdb->common.mctx,
|
||
|
|
rbtdb->common.rdclass,
|
||
|
|
(dns_rdatatype_t)header->type, flags,
|
||
|
|
- &merged);
|
||
|
|
+ rbtdb->maxrrperset, &merged);
|
||
|
|
}
|
||
|
|
if (result == ISC_R_SUCCESS) {
|
||
|
|
/*
|
||
|
|
@@ -6707,9 +6753,15 @@ find_header:
|
||
|
|
/*
|
||
|
|
* No rdatasets of the given type exist at the node.
|
||
|
|
*/
|
||
|
|
+ if (!IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) {
|
||
|
|
+ free_rdataset(rbtdb, rbtdb->common.mctx,
|
||
|
|
+ newheader);
|
||
|
|
+ return (DNS_R_TOOMANYRECORDS);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
newheader->down = NULL;
|
||
|
|
|
||
|
|
- if (prio_type(newheader->type)) {
|
||
|
|
+ if (prio_header(newheader)) {
|
||
|
|
/* This is a priority type, prepend it */
|
||
|
|
newheader->next = rbtnode->data;
|
||
|
|
rbtnode->data = newheader;
|
||
|
|
@@ -6722,6 +6774,31 @@ find_header:
|
||
|
|
newheader->next = rbtnode->data;
|
||
|
|
rbtnode->data = newheader;
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+ if (IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) {
|
||
|
|
+ if (expireheader == NULL) {
|
||
|
|
+ expireheader = newheader;
|
||
|
|
+ }
|
||
|
|
+ if (NEGATIVE(newheader) &&
|
||
|
|
+ !prio_header(newheader))
|
||
|
|
+ {
|
||
|
|
+ /*
|
||
|
|
+ * Add the new non-priority negative
|
||
|
|
+ * header to the database only
|
||
|
|
+ * temporarily.
|
||
|
|
+ */
|
||
|
|
+ expireheader = newheader;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ set_ttl(rbtdb, expireheader, 0);
|
||
|
|
+ mark_header_ancient(rbtdb, expireheader);
|
||
|
|
+ /*
|
||
|
|
+ * FIXME: In theory, we should mark the RRSIG
|
||
|
|
+ * and the header at the same time, but there is
|
||
|
|
+ * no direct link between those two header, so
|
||
|
|
+ * we would have to check the whole list again.
|
||
|
|
+ */
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -6767,7 +6844,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||
|
|
|
||
|
|
static 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;
|
||
|
|
@@ -6788,12 +6865,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;
|
||
|
|
}
|
||
|
|
@@ -6812,7 +6889,7 @@ cleanup:
|
||
|
|
|
||
|
|
static 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;
|
||
|
|
@@ -6833,12 +6910,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;
|
||
|
|
}
|
||
|
|
@@ -6916,7 +6993,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);
|
||
|
|
}
|
||
|
|
@@ -6974,7 +7052,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);
|
||
|
|
@@ -6982,7 +7061,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);
|
||
|
|
@@ -7148,7 +7228,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);
|
||
|
|
}
|
||
|
|
@@ -7552,7 +7633,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);
|
||
|
|
}
|
||
|
|
@@ -8088,6 +8170,24 @@ 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 void
|
||
|
|
+setmaxtypepername(dns_db_t *db, uint32_t maxtypepername) {
|
||
|
|
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||
|
|
+
|
||
|
|
+ REQUIRE(VALID_RBTDB(rbtdb));
|
||
|
|
+
|
||
|
|
+ rbtdb->maxtypepername = maxtypepername;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
static dns_stats_t *
|
||
|
|
getrrsetstats(dns_db_t *db) {
|
||
|
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||
|
|
@@ -8209,7 +8309,9 @@ static dns_dbmethods_t zone_methods = { attach,
|
||
|
|
NULL, /* getservestalettl */
|
||
|
|
NULL, /* setservestalerefresh */
|
||
|
|
NULL, /* getservestalerefresh */
|
||
|
|
- setgluecachestats };
|
||
|
|
+ setgluecachestats,
|
||
|
|
+ setmaxrrperset,
|
||
|
|
+ setmaxtypepername };
|
||
|
|
|
||
|
|
static dns_dbmethods_t cache_methods = { attach,
|
||
|
|
detach,
|
||
|
|
@@ -8259,7 +8361,9 @@ static dns_dbmethods_t cache_methods = { attach,
|
||
|
|
getservestalettl,
|
||
|
|
setservestalerefresh,
|
||
|
|
getservestalerefresh,
|
||
|
|
- NULL };
|
||
|
|
+ NULL,
|
||
|
|
+ setmaxrrperset,
|
||
|
|
+ setmaxtypepername };
|
||
|
|
|
||
|
|
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 24fdaa8..5c30d44 100644
|
||
|
|
--- a/lib/dns/rdataslab.c
|
||
|
|
+++ b/lib/dns/rdataslab.c
|
||
|
|
@@ -114,7 +114,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.
|
||
|
|
@@ -156,6 +157,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
||
|
|
return (ISC_R_SUCCESS);
|
||
|
|
}
|
||
|
|
|
||
|
|
+ if (maxrrperset > 0 && nitems > maxrrperset) {
|
||
|
|
+ return (DNS_R_TOOMANYRECORDS);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
if (nitems > 0xffff) {
|
||
|
|
return (ISC_R_NOSPACE);
|
||
|
|
}
|
||
|
|
@@ -482,7 +487,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;
|
||
|
|
@@ -522,6 +528,10 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||
|
|
#endif /* if DNS_RDATASET_FIXED */
|
||
|
|
INSIST(ocount > 0 && ncount > 0);
|
||
|
|
|
||
|
|
+ if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
|
||
|
|
+ return (DNS_R_TOOMANYRECORDS);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
#if DNS_RDATASET_FIXED
|
||
|
|
oncount = ncount;
|
||
|
|
#endif /* if DNS_RDATASET_FIXED */
|
||
|
|
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
|
||
|
|
index 317eeb0..07d720e 100644
|
||
|
|
--- a/lib/dns/sdb.c
|
||
|
|
+++ b/lib/dns/sdb.c
|
||
|
|
@@ -1269,20 +1269,33 @@ settask(dns_db_t *db, isc_task_t *task) {
|
||
|
|
}
|
||
|
|
|
||
|
|
static dns_dbmethods_t sdb_methods = {
|
||
|
|
- attach, detach,
|
||
|
|
- beginload, endload,
|
||
|
|
- dump, currentversion,
|
||
|
|
- newversion, attachversion,
|
||
|
|
- closeversion, NULL, /* findnode */
|
||
|
|
- NULL, /* find */
|
||
|
|
- findzonecut, attachnode,
|
||
|
|
- detachnode, expirenode,
|
||
|
|
- printnode, createiterator,
|
||
|
|
- findrdataset, allrdatasets,
|
||
|
|
- addrdataset, subtractrdataset,
|
||
|
|
- deleterdataset, issecure,
|
||
|
|
- nodecount, ispersistent,
|
||
|
|
- overmem, settask,
|
||
|
|
+ attach,
|
||
|
|
+ detach,
|
||
|
|
+ beginload,
|
||
|
|
+ endload,
|
||
|
|
+ dump,
|
||
|
|
+ currentversion,
|
||
|
|
+ newversion,
|
||
|
|
+ attachversion,
|
||
|
|
+ closeversion,
|
||
|
|
+ NULL, /* findnode */
|
||
|
|
+ NULL, /* find */
|
||
|
|
+ findzonecut,
|
||
|
|
+ attachnode,
|
||
|
|
+ detachnode,
|
||
|
|
+ expirenode,
|
||
|
|
+ printnode,
|
||
|
|
+ createiterator,
|
||
|
|
+ findrdataset,
|
||
|
|
+ allrdatasets,
|
||
|
|
+ addrdataset,
|
||
|
|
+ subtractrdataset,
|
||
|
|
+ deleterdataset,
|
||
|
|
+ issecure,
|
||
|
|
+ nodecount,
|
||
|
|
+ ispersistent,
|
||
|
|
+ overmem,
|
||
|
|
+ settask,
|
||
|
|
getoriginnode, /* getoriginnode */
|
||
|
|
NULL, /* transfernode */
|
||
|
|
NULL, /* getnsec3parameters */
|
||
|
|
@@ -1294,7 +1307,8 @@ static dns_dbmethods_t sdb_methods = {
|
||
|
|
NULL, /* getrrsetstats */
|
||
|
|
NULL, /* rpz_attach */
|
||
|
|
NULL, /* rpz_ready */
|
||
|
|
- findnodeext, findext,
|
||
|
|
+ findnodeext,
|
||
|
|
+ findext,
|
||
|
|
NULL, /* setcachestats */
|
||
|
|
NULL, /* hashsize */
|
||
|
|
NULL, /* nodefullname */
|
||
|
|
@@ -1304,6 +1318,8 @@ static dns_dbmethods_t sdb_methods = {
|
||
|
|
NULL, /* setservestalerefresh */
|
||
|
|
NULL, /* getservestalerefresh */
|
||
|
|
NULL, /* setgluecachestats */
|
||
|
|
+ NULL, /* setmaxrrperset */
|
||
|
|
+ NULL /* setmaxtypepername */
|
||
|
|
};
|
||
|
|
|
||
|
|
static isc_result_t
|
||
|
|
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
|
||
|
|
index 7ab08f6..f9d123d 100644
|
||
|
|
--- a/lib/dns/sdlz.c
|
||
|
|
+++ b/lib/dns/sdlz.c
|
||
|
|
@@ -1242,34 +1242,57 @@ getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
|
||
|
|
}
|
||
|
|
|
||
|
|
static dns_dbmethods_t sdlzdb_methods = {
|
||
|
|
- attach, detach, beginload,
|
||
|
|
- endload, dump, currentversion,
|
||
|
|
- newversion, attachversion, closeversion,
|
||
|
|
- findnode, find, findzonecut,
|
||
|
|
- attachnode, detachnode, expirenode,
|
||
|
|
- printnode, createiterator, findrdataset,
|
||
|
|
- allrdatasets, addrdataset, subtractrdataset,
|
||
|
|
- deleterdataset, issecure, nodecount,
|
||
|
|
- ispersistent, overmem, settask,
|
||
|
|
- getoriginnode, NULL, /* transfernode */
|
||
|
|
- NULL, /* getnsec3parameters */
|
||
|
|
- NULL, /* findnsec3node */
|
||
|
|
- NULL, /* setsigningtime */
|
||
|
|
- NULL, /* getsigningtime */
|
||
|
|
- NULL, /* resigned */
|
||
|
|
- NULL, /* isdnssec */
|
||
|
|
- NULL, /* getrrsetstats */
|
||
|
|
- NULL, /* rpz_attach */
|
||
|
|
- NULL, /* rpz_ready */
|
||
|
|
- findnodeext, findext, NULL, /* setcachestats */
|
||
|
|
- NULL, /* hashsize */
|
||
|
|
- NULL, /* nodefullname */
|
||
|
|
- NULL, /* getsize */
|
||
|
|
- NULL, /* setservestalettl */
|
||
|
|
- NULL, /* getservestalettl */
|
||
|
|
- NULL, /* setservestalerefresh */
|
||
|
|
- NULL, /* getservestalerefresh */
|
||
|
|
- NULL, /* setgluecachestats */
|
||
|
|
+ attach,
|
||
|
|
+ detach,
|
||
|
|
+ beginload,
|
||
|
|
+ endload,
|
||
|
|
+ dump,
|
||
|
|
+ currentversion,
|
||
|
|
+ newversion,
|
||
|
|
+ attachversion,
|
||
|
|
+ closeversion,
|
||
|
|
+ findnode,
|
||
|
|
+ find,
|
||
|
|
+ findzonecut,
|
||
|
|
+ attachnode,
|
||
|
|
+ detachnode,
|
||
|
|
+ expirenode,
|
||
|
|
+ printnode,
|
||
|
|
+ createiterator,
|
||
|
|
+ findrdataset,
|
||
|
|
+ allrdatasets,
|
||
|
|
+ addrdataset,
|
||
|
|
+ subtractrdataset,
|
||
|
|
+ deleterdataset,
|
||
|
|
+ issecure,
|
||
|
|
+ nodecount,
|
||
|
|
+ ispersistent,
|
||
|
|
+ overmem,
|
||
|
|
+ settask,
|
||
|
|
+ getoriginnode,
|
||
|
|
+ NULL, /* transfernode */
|
||
|
|
+ NULL, /* getnsec3parameters */
|
||
|
|
+ NULL, /* findnsec3node */
|
||
|
|
+ NULL, /* setsigningtime */
|
||
|
|
+ NULL, /* getsigningtime */
|
||
|
|
+ NULL, /* resigned */
|
||
|
|
+ NULL, /* isdnssec */
|
||
|
|
+ NULL, /* getrrsetstats */
|
||
|
|
+ NULL, /* rpz_attach */
|
||
|
|
+ NULL, /* rpz_ready */
|
||
|
|
+ findnodeext,
|
||
|
|
+ findext,
|
||
|
|
+ NULL, /* setcachestats */
|
||
|
|
+ NULL, /* hashsize */
|
||
|
|
+ NULL, /* nodefullname */
|
||
|
|
+ NULL, /* getsize */
|
||
|
|
+ NULL, /* setservestalettl */
|
||
|
|
+ NULL, /* getservestalettl */
|
||
|
|
+ NULL, /* setservestalerefresh */
|
||
|
|
+ NULL, /* getservestalerefresh */
|
||
|
|
+ NULL, /* setgluecachestats */
|
||
|
|
+ NULL, /* setmaxrrperset */
|
||
|
|
+ NULL /* setmaxtypepername */
|
||
|
|
};
|
||
|
|
|
||
|
|
/*
|
||
|
|
diff --git a/lib/dns/view.c b/lib/dns/view.c
|
||
|
|
index 49c9aee..231041e 100644
|
||
|
|
--- a/lib/dns/view.c
|
||
|
|
+++ b/lib/dns/view.c
|
||
|
|
@@ -892,6 +892,9 @@ 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);
|
||
|
|
+ dns_cache_setmaxtypepername(view->cache, view->maxtypepername);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool
|
||
|
|
@@ -2759,3 +2762,21 @@ dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
|
||
|
|
dns_name_copy(dns_rootname, foundname);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+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);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_view_setmaxtypepername(dns_view_t *view, uint32_t value) {
|
||
|
|
+ REQUIRE(DNS_VIEW_VALID(view));
|
||
|
|
+ view->maxtypepername = value;
|
||
|
|
+ if (view->cache != NULL) {
|
||
|
|
+ dns_cache_setmaxtypepername(view->cache, value);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
|
||
|
|
index 1aa982a..e5f1e0b 100644
|
||
|
|
--- a/lib/dns/xfrin.c
|
||
|
|
+++ b/lib/dns/xfrin.c
|
||
|
|
@@ -211,8 +211,6 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
|
||
|
|
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
|
||
|
|
@@ -288,7 +286,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;
|
||
|
|
@@ -296,22 +298,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 3b95136..f14a166 100644
|
||
|
|
--- a/lib/dns/zone.c
|
||
|
|
+++ b/lib/dns/zone.c
|
||
|
|
@@ -309,6 +309,8 @@ struct dns_zone {
|
||
|
|
uint32_t minretry;
|
||
|
|
|
||
|
|
uint32_t maxrecords;
|
||
|
|
+ uint32_t maxrrperset;
|
||
|
|
+ uint32_t maxtypepername;
|
||
|
|
|
||
|
|
isc_sockaddr_t *primaries;
|
||
|
|
dns_name_t **primarykeynames;
|
||
|
|
@@ -2327,31 +2329,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 || zone->stream != NULL) {
|
||
|
|
@@ -10063,6 +10047,7 @@ cleanup:
|
||
|
|
}
|
||
|
|
|
||
|
|
dns_diff_clear(&_sig_diff);
|
||
|
|
+ dns_diff_clear(&post_diff);
|
||
|
|
|
||
|
|
for (i = 0; i < nkeys; i++) {
|
||
|
|
dst_key_free(&zone_keys[i]);
|
||
|
|
@@ -12332,6 +12317,26 @@ 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);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
|
||
|
|
+ REQUIRE(DNS_ZONE_VALID(zone));
|
||
|
|
+
|
||
|
|
+ zone->maxtypepername = val;
|
||
|
|
+ if (zone->db != NULL) {
|
||
|
|
+ dns_db_setmaxtypepername(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,
|
||
|
|
@@ -14799,6 +14804,9 @@ 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);
|
||
|
|
+ dns_db_setmaxtypepername(stub->db,
|
||
|
|
+ zone->maxtypepername);
|
||
|
|
}
|
||
|
|
|
||
|
|
result = dns_db_newversion(stub->db, &stub->version);
|
||
|
|
@@ -17516,6 +17524,8 @@ 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_db_setmaxtypepername(zone->db, zone->maxtypepername);
|
||
|
|
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
|
||
|
|
return (ISC_R_SUCCESS);
|
||
|
|
|
||
|
|
@@ -22045,7 +22055,11 @@ failure:
|
||
|
|
* Something went wrong; try again in ten minutes or
|
||
|
|
* after a key refresh interval, whichever is shorter.
|
||
|
|
*/
|
||
|
|
- dnssec_log(zone, ISC_LOG_DEBUG(3),
|
||
|
|
+ int loglevel = ISC_LOG_DEBUG(3);
|
||
|
|
+ if (result != DNS_R_NOTLOADED) {
|
||
|
|
+ loglevel = ISC_LOG_ERROR;
|
||
|
|
+ }
|
||
|
|
+ dnssec_log(zone, loglevel,
|
||
|
|
"zone_rekey failure: %s (retry in %u seconds)",
|
||
|
|
isc_result_totext(result),
|
||
|
|
ISC_MIN(zone->refreshkeyinterval, 600));
|
||
|
|
@@ -23706,3 +23720,45 @@ zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
|
||
|
|
|
||
|
|
RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+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);
|
||
|
|
+ dns_db_setmaxtypepername(db, zone->maxtypepername);
|
||
|
|
+
|
||
|
|
+ *dbp = db;
|
||
|
|
+
|
||
|
|
+ return (ISC_R_SUCCESS);
|
||
|
|
+}
|
||
|
|
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
|
||
|
|
index 5a8ccb2..7938bcb 100644
|
||
|
|
--- a/lib/isccfg/namedconf.c
|
||
|
|
+++ b/lib/isccfg/namedconf.c
|
||
|
|
@@ -2300,6 +2300,12 @@ 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-types-per-name", &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,
|
||
|
|
diff --git a/lib/ns/update.c b/lib/ns/update.c
|
||
|
|
index 983ca84..5d72686 100644
|
||
|
|
--- a/lib/ns/update.c
|
||
|
|
+++ b/lib/ns/update.c
|
||
|
|
@@ -3302,9 +3302,18 @@ update_action(isc_task_t *task, isc_event_t *event) {
|
||
|
|
dns_diff_clear(&ctx.add_diff);
|
||
|
|
goto failure;
|
||
|
|
}
|
||
|
|
- CHECK(update_one_rr(db, ver, &diff,
|
||
|
|
- DNS_DIFFOP_ADD,
|
||
|
|
- name, ttl, &rdata));
|
||
|
|
+ result = update_one_rr(
|
||
|
|
+ db, ver, &diff, DNS_DIFFOP_ADD,
|
||
|
|
+ name, ttl, &rdata);
|
||
|
|
+ if (result != ISC_R_SUCCESS) {
|
||
|
|
+ update_log(client, zone,
|
||
|
|
+ LOGLEVEL_PROTOCOL,
|
||
|
|
+ "adding an RR "
|
||
|
|
+ "failed: %s",
|
||
|
|
+ isc_result_totext(
|
||
|
|
+ result));
|
||
|
|
+ goto failure;
|
||
|
|
+ }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (update_class == dns_rdataclass_any) {
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|