mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
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.
This commit is contained in:
parent
3dc4388f4a
commit
52b3d86ef0
26 changed files with 214 additions and 6 deletions
|
|
@ -225,6 +225,7 @@ options {\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\
|
||||
|
|
|
|||
|
|
@ -5463,6 +5463,15 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -1082,6 +1082,14 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -3696,6 +3696,21 @@ system.
|
|||
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.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ zone <string> [ <class> ] {
|
|||
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>;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,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-validation-failures-per-fetch <integer>; // experimental
|
||||
max-validations-per-fetch <integer>; // experimental
|
||||
|
|
@ -479,6 +480,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-validation-failures-per-fetch <integer>; // experimental
|
||||
max-validations-per-fetch <integer>; // experimental
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ zone <string> [ <class> ] {
|
|||
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> ); // deprecated
|
||||
notify ( explicit | master-only | primary-only | <boolean> );
|
||||
notify-delay <integer>;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ zone <string> [ <class> ] {
|
|||
masterfile-style ( full | relative );
|
||||
max-records <integer>;
|
||||
max-records-per-type <integer>;
|
||||
max-types-per-name <integer>;
|
||||
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
||||
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
zone-statistics ( full | terse | none | <boolean> );
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ zone <string> [ <class> ] {
|
|||
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>;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ zone <string> [ <class> ] {
|
|||
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
||||
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> );
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ zone <string> [ <class> ] {
|
|||
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>;
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ struct dns_cache {
|
|||
dns_ttl_t serve_stale_refresh;
|
||||
isc_stats_t *stats;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxtypepername;
|
||||
};
|
||||
|
||||
/***
|
||||
|
|
@ -130,6 +131,7 @@ cache_create_db(dns_cache_t *cache, dns_db_t **dbp, isc_mem_t **tmctxp,
|
|||
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);
|
||||
|
||||
/*
|
||||
* XXX this is only used by the RBT cache, and can
|
||||
|
|
@ -558,6 +560,16 @@ dns_cache_setmaxrrperset(dns_cache_t *cache, uint32_t 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
|
||||
|
|
|
|||
|
|
@ -1179,3 +1179,12 @@ dns_db_setmaxrrperset(dns_db_t *db, uint32_t value) {
|
|||
(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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,6 +252,12 @@ 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);
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ typedef struct dns_dbmethods {
|
|||
isc_result_t (*nodefullname)(dns_db_t *db, dns_dbnode_t *node,
|
||||
dns_name_t *name);
|
||||
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,
|
||||
|
|
@ -1805,8 +1806,19 @@ dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name);
|
|||
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_TOOMANYRECORDS.
|
||||
* 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_TOOMANYRECORDS.
|
||||
*/
|
||||
|
||||
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, and if there are already 'value' RR types
|
||||
* stored at a given node, then any subsequent attempt to add an rdataset
|
||||
* with a new RR type will return ISC_R_TOOMANYRECORDS.
|
||||
*/
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ struct dns_view {
|
|||
dns_badcache_t *failcache;
|
||||
unsigned int udpsize;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxtypepername;
|
||||
|
||||
/*
|
||||
* Configurable data for server use only,
|
||||
|
|
@ -1249,6 +1250,12 @@ 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.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -379,6 +379,19 @@ dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t maxrrperset);
|
|||
*\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);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -217,7 +217,8 @@ struct qpcache {
|
|||
/* Locked by lock. */
|
||||
unsigned int active;
|
||||
|
||||
uint32_t maxrrperset; /* Maximum RRs per RRset */
|
||||
uint32_t maxrrperset; /* Maximum RRs per RRset */
|
||||
uint32_t maxtypepername; /* Maximum number of RR types per owner */
|
||||
|
||||
/*
|
||||
* The time after a failed lookup, where stale answers from cache
|
||||
|
|
@ -2885,6 +2886,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
dns_typepair_t negtype = 0, sigtype;
|
||||
dns_trust_t trust;
|
||||
int idx;
|
||||
uint32_t ntypes;
|
||||
|
||||
if ((options & DNS_DBADD_FORCE) != 0) {
|
||||
trust = dns_trust_ultimate;
|
||||
|
|
@ -2917,6 +2919,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
{
|
||||
mark_ancient(topheader);
|
||||
}
|
||||
ntypes = 0; /* Always add the negative entry */
|
||||
goto find_header;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2940,9 +2943,11 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
* check for an extant non-ancient NODATA ncache
|
||||
* entry which covers the same type as the RRSIG.
|
||||
*/
|
||||
ntypes = 0;
|
||||
for (topheader = qpnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||
(newheader->type == sigtype &&
|
||||
topheader->type ==
|
||||
|
|
@ -2985,9 +2990,12 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
}
|
||||
}
|
||||
|
||||
ntypes = 0;
|
||||
for (topheader = qpnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
|
||||
if (prio_type(topheader->type)) {
|
||||
prioheader = topheader;
|
||||
}
|
||||
|
|
@ -3255,6 +3263,14 @@ find_header:
|
|||
/*
|
||||
* No rdatasets of the given type exist at the node.
|
||||
*/
|
||||
if (trust != dns_trust_ultimate &&
|
||||
qpdb->maxtypepername > 0 &&
|
||||
ntypes >= qpdb->maxtypepername)
|
||||
{
|
||||
dns_slabheader_destroy(&newheader);
|
||||
return (DNS_R_TOOMANYRECORDS);
|
||||
}
|
||||
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (prio_type(newheader->type)) {
|
||||
|
|
@ -4344,6 +4360,15 @@ setmaxrrperset(dns_db_t *db, uint32_t value) {
|
|||
qpdb->maxrrperset = value;
|
||||
}
|
||||
|
||||
static void
|
||||
setmaxtypepername(dns_db_t *db, uint32_t value) {
|
||||
qpcache_t *qpdb = (qpcache_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPDB(qpdb));
|
||||
|
||||
qpdb->maxtypepername = value;
|
||||
}
|
||||
|
||||
static dns_dbmethods_t qpdb_cachemethods = {
|
||||
.destroy = qpdb_destroy,
|
||||
.findnode = findnode,
|
||||
|
|
@ -4369,6 +4394,7 @@ static dns_dbmethods_t qpdb_cachemethods = {
|
|||
.expiredata = expiredata,
|
||||
.deletedata = deletedata,
|
||||
.setmaxrrperset = setmaxrrperset,
|
||||
.setmaxtypepername = setmaxtypepername,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -178,7 +178,8 @@ struct qpzonedb {
|
|||
uint32_t current_serial;
|
||||
uint32_t least_serial;
|
||||
uint32_t next_serial;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxrrperset; /* Maximum RRs per RRset */
|
||||
uint32_t maxtypepername; /* Maximum number of RR types per owner */
|
||||
qpz_version_t *current_version;
|
||||
qpz_version_t *future_version;
|
||||
qpz_versionlist_t open_versions;
|
||||
|
|
@ -1834,6 +1835,7 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||
unsigned char *merged = NULL;
|
||||
isc_result_t result;
|
||||
bool merge = false;
|
||||
uint32_t ntypes;
|
||||
|
||||
if ((options & DNS_DBADD_MERGE) != 0) {
|
||||
REQUIRE(version != NULL);
|
||||
|
|
@ -1849,9 +1851,11 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
|
||||
}
|
||||
|
||||
ntypes = 0;
|
||||
for (topheader = node->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if (prio_type(topheader->type)) {
|
||||
prioheader = topheader;
|
||||
}
|
||||
|
|
@ -2018,6 +2022,14 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||
/*
|
||||
* No rdatasets of the given type exist at the node.
|
||||
*/
|
||||
|
||||
if (qpdb->maxtypepername > 0 &&
|
||||
ntypes >= qpdb->maxtypepername)
|
||||
{
|
||||
dns_slabheader_destroy(&newheader);
|
||||
return (DNS_R_TOOMANYRECORDS);
|
||||
}
|
||||
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (prio_type(newheader->type)) {
|
||||
|
|
@ -5290,6 +5302,15 @@ setmaxrrperset(dns_db_t *db, uint32_t value) {
|
|||
qpdb->maxrrperset = value;
|
||||
}
|
||||
|
||||
static void
|
||||
setmaxtypepername(dns_db_t *db, uint32_t value) {
|
||||
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||
|
||||
REQUIRE(VALID_QPZONE(qpdb));
|
||||
|
||||
qpdb->maxtypepername = value;
|
||||
}
|
||||
|
||||
static dns_dbmethods_t qpdb_zonemethods = {
|
||||
.destroy = qpdb_destroy,
|
||||
.beginload = beginload,
|
||||
|
|
@ -5324,6 +5345,7 @@ static dns_dbmethods_t qpdb_zonemethods = {
|
|||
.deletedata = deletedata,
|
||||
.nodefullname = nodefullname,
|
||||
.setmaxrrperset = setmaxrrperset,
|
||||
.setmaxtypepername = setmaxtypepername,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -1583,6 +1583,7 @@ dns_dbmethods_t dns__rbtdb_cachemethods = {
|
|||
.expiredata = expiredata,
|
||||
.deletedata = dns__rbtdb_deletedata,
|
||||
.setmaxrrperset = dns__rbtdb_setmaxrrperset,
|
||||
.setmaxtypepername = dns__rbtdb_setmaxtypepername,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2420,6 +2420,7 @@ dns_dbmethods_t dns__rbtdb_zonemethods = {
|
|||
.deletedata = dns__rbtdb_deletedata,
|
||||
.nodefullname = dns__rbtdb_nodefullname,
|
||||
.setmaxrrperset = dns__rbtdb_setmaxrrperset,
|
||||
.setmaxtypepername = dns__rbtdb_setmaxtypepername,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -2566,6 +2566,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
dns_typepair_t negtype = 0, sigtype;
|
||||
dns_trust_t trust;
|
||||
int idx;
|
||||
uint32_t ntypes = 0;
|
||||
|
||||
if ((options & DNS_DBADD_MERGE) != 0) {
|
||||
REQUIRE(rbtversion != NULL);
|
||||
|
|
@ -2618,6 +2619,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
{
|
||||
mark_ancient(topheader);
|
||||
}
|
||||
ntypes = 0; /* Always add the negative entry */
|
||||
goto find_header;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2641,9 +2643,11 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
* check for an extant non-ancient NODATA ncache
|
||||
* entry which covers the same type as the RRSIG.
|
||||
*/
|
||||
ntypes = 0;
|
||||
for (topheader = rbtnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||
(newheader->type == sigtype &&
|
||||
topheader->type ==
|
||||
|
|
@ -2686,9 +2690,11 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
}
|
||||
}
|
||||
|
||||
ntypes = 0;
|
||||
for (topheader = rbtnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if (prio_type(topheader->type)) {
|
||||
prioheader = topheader;
|
||||
}
|
||||
|
|
@ -3082,6 +3088,14 @@ find_header:
|
|||
/*
|
||||
* No rdatasets of the given type exist at the node.
|
||||
*/
|
||||
|
||||
if (rbtdb->maxtypepername > 0 &&
|
||||
ntypes >= rbtdb->maxtypepername)
|
||||
{
|
||||
dns_slabheader_destroy(&newheader);
|
||||
return (DNS_R_TOOMANYRECORDS);
|
||||
}
|
||||
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (prio_type(newheader->type)) {
|
||||
|
|
@ -4968,3 +4982,12 @@ dns__rbtdb_setmaxrrperset(dns_db_t *db, uint32_t value) {
|
|||
|
||||
rbtdb->maxrrperset = value;
|
||||
}
|
||||
|
||||
void
|
||||
dns__rbtdb_setmaxtypepername(dns_db_t *db, uint32_t maxtypepername) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
|
||||
rbtdb->maxtypepername = maxtypepername;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ struct dns_rbtdb {
|
|||
uint32_t least_serial;
|
||||
uint32_t next_serial;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxtypepername;
|
||||
dns_rbtdb_version_t *current_version;
|
||||
dns_rbtdb_version_t *future_version;
|
||||
rbtdb_versionlist_t open_versions;
|
||||
|
|
@ -429,7 +430,13 @@ dns__rbtdb_setttl(dns_slabheader_t *header, dns_ttl_t newttl);
|
|||
*/
|
||||
|
||||
void
|
||||
dns__rbtdb_setmaxrrperset(dns_db_t *db, uint32_t value);
|
||||
dns__rbtdb_setmaxrrperset(dns_db_t *db, uint32_t maxrrperset);
|
||||
/*%<
|
||||
* Set the max RRs per RRset limit.
|
||||
*/
|
||||
|
||||
void
|
||||
dns__rbtdb_setmaxtypepername(dns_db_t *db, uint32_t maxtypepername);
|
||||
/*%<
|
||||
* Set the max RRs per RRset limit.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -645,6 +645,7 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
|
|||
INSIST(DNS_DB_VALID(view->cachedb));
|
||||
|
||||
dns_cache_setmaxrrperset(view->cache, view->maxrrperset);
|
||||
dns_cache_setmaxtypepername(view->cache, view->maxtypepername);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -2347,6 +2348,15 @@ dns_view_setmaxrrperset(dns_view_t *view, uint32_t 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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize) {
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ struct dns_zone {
|
|||
|
||||
uint32_t maxrecords;
|
||||
uint32_t maxrrperset;
|
||||
uint32_t maxtypepername;
|
||||
|
||||
dns_remote_t primaries;
|
||||
|
||||
|
|
@ -12068,6 +12069,16 @@ dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t 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,
|
||||
|
|
@ -14470,6 +14481,8 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
|||
}
|
||||
dns_db_setloop(stub->db, zone->loop);
|
||||
dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
|
||||
dns_db_setmaxtypepername(stub->db,
|
||||
zone->maxtypepername);
|
||||
}
|
||||
|
||||
result = dns_db_newversion(stub->db, &stub->version);
|
||||
|
|
@ -17527,6 +17540,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
|
|||
zone_attachdb(zone, db);
|
||||
dns_db_setloop(zone->db, zone->loop);
|
||||
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);
|
||||
|
||||
|
|
@ -24167,6 +24181,7 @@ dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
|
|||
|
||||
dns_db_setloop(db, zone->loop);
|
||||
dns_db_setmaxrrperset(db, zone->maxrrperset);
|
||||
dns_db_setmaxtypepername(db, zone->maxtypepername);
|
||||
|
||||
*dbp = db;
|
||||
|
||||
|
|
|
|||
|
|
@ -2375,6 +2375,9 @@ static cfg_clausedef_t zone_clauses[] = {
|
|||
{ "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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue