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)
This commit is contained in:
Ondřej Surý 2024-03-01 08:26:07 +01:00 committed by Nicki Křížek
parent 3492c0deda
commit e699ef939e
No known key found for this signature in database
GPG key ID: 01623B9B652A20A7
31 changed files with 304 additions and 81 deletions

View file

@ -233,6 +233,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\

View file

@ -5556,6 +5556,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);

View file

@ -1083,6 +1083,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);

View file

@ -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;
};

View file

@ -44,6 +44,7 @@ options {
ixfr-from-differences yes;
check-integrity no;
dnssec-validation yes;
max-records-per-type 0;
};
zone "." {

View file

@ -52,6 +52,7 @@ options {
ixfr-from-differences yes;
check-integrity no;
dnssec-validation yes;
max-records-per-type 0;
};
zone "." {

View file

@ -40,6 +40,7 @@ options {
ixfr-from-differences yes;
check-integrity no;
dnssec-validation yes;
max-records-per-type 0;
};
zone "." {

View file

@ -563,28 +563,56 @@ 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 */
};
/* Auxiliary driver functions. */

View file

@ -3766,6 +3766,21 @@ 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:: recursive-clients
:tags: query
:short: Specifies the maximum number of concurrent recursive queries the server can perform.

View file

@ -18,6 +18,7 @@ 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>;

View file

@ -181,6 +181,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>;
@ -471,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>;

View file

@ -38,6 +38,7 @@ 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-zone-ttl ( unlimited | <duration> );

View file

@ -7,6 +7,7 @@ zone <string> [ <class> ] {
masterfile-format ( raw | text );
masterfile-style ( full | relative );
max-records <integer>;
max-records-per-type <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> );

View file

@ -30,6 +30,7 @@ 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>;

View file

@ -5,6 +5,7 @@ zone <string> [ <class> ] {
forward ( first | only );
forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ]; ... };
max-records <integer>;
max-records-per-type <integer>;
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
server-names { <string>; ... };
zone-statistics ( full | terse | none | <boolean> );

View file

@ -12,6 +12,7 @@ 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>;

View file

@ -146,6 +146,7 @@ struct dns_cache {
dns_ttl_t serve_stale_ttl;
dns_ttl_t serve_stale_refresh;
isc_stats_t *stats;
uint32_t maxrrperset;
};
/***
@ -210,6 +211,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);
if (cache->taskmgr == NULL) {
*dbp = db;
@ -1239,6 +1241,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

View file

@ -1121,3 +1121,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);
}
}

View file

@ -975,6 +975,7 @@ static dns_dbmethods_t rpsdb_db_methods = {
NULL, /* setservestalerefresh */
NULL, /* getservestalerefresh */
NULL, /* setgluecachestats */
NULL /* setmaxrrperset */
};
static dns_rdatasetmethods_t rpsdb_rdataset_methods = {

View file

@ -280,6 +280,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);

View file

@ -185,6 +185,7 @@ 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);
} dns_dbmethods_t;
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
@ -1759,4 +1760,11 @@ 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

View file

@ -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'.
*/

View file

@ -191,6 +191,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,
@ -1413,4 +1414,10 @@ 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.
*/
ISC_LANG_ENDDECLS

View file

@ -363,6 +363,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);
/*%<

View file

@ -462,6 +462,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;
@ -6486,7 +6487,7 @@ find_header:
rbtdb->common.mctx,
rbtdb->common.rdclass,
(dns_rdatatype_t)header->type, flags,
&merged);
rbtdb->maxrrperset, &merged);
}
if (result == ISC_R_SUCCESS) {
/*
@ -6825,7 +6826,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;
@ -6846,12 +6847,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;
}
@ -6870,7 +6871,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;
@ -6891,12 +6892,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;
}
@ -6977,7 +6978,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
}
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
&region, sizeof(rdatasetheader_t));
&region, sizeof(rdatasetheader_t),
rbtdb->maxrrperset);
if (result != ISC_R_SUCCESS) {
return (result);
}
@ -7035,7 +7037,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);
@ -7043,7 +7046,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);
@ -7188,7 +7192,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,
&region, sizeof(rdatasetheader_t));
&region, sizeof(rdatasetheader_t),
0);
if (result != ISC_R_SUCCESS) {
return (result);
}
@ -7570,7 +7575,8 @@ loading_addrdataset(void *arg, const dns_name_t *name,
}
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
&region, sizeof(rdatasetheader_t));
&region, sizeof(rdatasetheader_t),
rbtdb->maxrrperset);
if (result != ISC_R_SUCCESS) {
return (result);
}
@ -8112,6 +8118,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;
@ -8233,7 +8248,8 @@ static dns_dbmethods_t zone_methods = { attach,
NULL, /* getservestalettl */
NULL, /* setservestalerefresh */
NULL, /* getservestalerefresh */
setgluecachestats };
setgluecachestats,
setmaxrrperset };
static dns_dbmethods_t cache_methods = { attach,
detach,
@ -8283,7 +8299,8 @@ static dns_dbmethods_t cache_methods = { attach,
getservestalettl,
setservestalerefresh,
getservestalerefresh,
NULL };
NULL,
setmaxrrperset };
isc_result_t
dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,

View file

@ -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);
}
@ -484,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;
@ -524,6 +530,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 */

View file

@ -1270,20 +1270,33 @@ settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
}
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 */
@ -1295,7 +1308,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 */
@ -1305,6 +1319,7 @@ static dns_dbmethods_t sdb_methods = {
NULL, /* setservestalerefresh */
NULL, /* getservestalerefresh */
NULL, /* setgluecachestats */
NULL /* setmaxrrperset */
};
static isc_result_t

View file

@ -1243,34 +1243,56 @@ 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 */
};
/*

View file

@ -892,6 +892,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
@ -2759,3 +2761,12 @@ 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);
}
}

View file

@ -309,6 +309,7 @@ struct dns_zone {
uint32_t minretry;
uint32_t maxrecords;
uint32_t maxrrperset;
isc_sockaddr_t *primaries;
dns_name_t **primarykeynames;
@ -12298,6 +12299,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,
@ -14786,6 +14797,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
goto cleanup;
}
dns_db_settask(stub->db, zone->task, zone->task);
dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
}
result = dns_db_newversion(stub->db, &stub->version);
@ -17890,6 +17902,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
}
zone_attachdb(zone, db);
dns_db_settask(zone->db, zone->task, zone->task);
dns_db_setmaxrrperset(zone->db, zone->maxrrperset);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
return (ISC_R_SUCCESS);
@ -24315,6 +24328,7 @@ dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
}
dns_db_settask(db, zone->task, zone->task);
dns_db_setmaxrrperset(db, zone->maxrrperset);
*dbp = db;

View file

@ -2300,6 +2300,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,