]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add a limit to the number of RRs in RRSets
authorOndřej Surý <ondrej@isc.org>
Fri, 1 Mar 2024 07:26:07 +0000 (08:26 +0100)
committerOndřej Surý <ondrej@isc.org>
Sun, 28 Jul 2024 14:55:28 +0000 (16:55 +0200)
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)

30 files changed:
bin/named/config.c
bin/named/server.c
bin/named/zoneconf.c
bin/tests/system/dyndb/driver/db.c
doc/arm/reference.rst
doc/misc/master.zoneopt
doc/misc/mirror.zoneopt
doc/misc/options
doc/misc/options.active
doc/misc/redirect.zoneopt
doc/misc/slave.zoneopt
doc/misc/static-stub.zoneopt
doc/misc/stub.zoneopt
lib/dns/cache.c
lib/dns/db.c
lib/dns/dnsrps.c
lib/dns/ecdb.c
lib/dns/include/dns/cache.h
lib/dns/include/dns/db.h
lib/dns/include/dns/rdataslab.h
lib/dns/include/dns/view.h
lib/dns/include/dns/zone.h
lib/dns/rbtdb.c
lib/dns/rdataslab.c
lib/dns/sdb.c
lib/dns/sdlz.c
lib/dns/view.c
lib/dns/xfrin.c
lib/dns/zone.c
lib/isccfg/namedconf.c

index 522798a882fbe093dfd7c9553bc9b819df5e9a4f..72dec1adef24d022fd2ee445c1314ccff3cc4b44 100644 (file)
@@ -226,6 +226,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\
index 5290fcc35d7c612be98385b4299f15fe473d04bf..72de0e23526b08904004e553cad145620e65aca8 100644 (file)
@@ -5452,6 +5452,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);
index 2e614aa6db2fdc55c27ac470bd634c37a5825627..81f68797babe609698e3400290d36470ced58693 100644 (file)
@@ -1072,6 +1072,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);
index 5f01185dd88a258a72e088f465b00927afc52308..727268fc3942b71fdf44f64614d413b84f7e7639 100644 (file)
@@ -622,7 +622,8 @@ static dns_dbmethods_t sampledb_methods = {
        NULL, /* setservestalerefresh */
        NULL, /* getservestalerefresh */
        NULL, /* setgluecachestats */
-       NULL  /* adjusthashsize */
+       NULL, /* adjusthashsize */
+       NULL  /* setmaxrrperset */
 };
 
 /* Auxiliary driver functions. */
index f982e0ac3a5292071d4ead73ce16b6393fa70565..fbd8edb3bfcd67d985c62692a93366eb4b69d9b0 100644 (file)
@@ -2945,6 +2945,18 @@ system.
    This sets the maximum number of records permitted in a zone. The default is
    zero, which means the maximum is unlimited.
 
+``max-records-per-type``
+   This sets the maximum number of resource records that can be stored
+   in an RRset in a database. When configured in ``options``
+   or ``view``, it controls the cache database; it also sets
+   the default value for zone databases, which can be overridden by setting
+   it at the ``zone`` level.
+
+   If set to a positive value, any attempt to cache or to add to a zone
+   an RRset with more than the specified number of records will result in
+   a failure.  If set to 0, there is no cap on RRset size.  The default is
+   100.
+
 ``recursive-clients``
    This sets the maximum number (a "hard quota") of simultaneous recursive lookups
    the server performs on behalf of clients. The default is
index 953e3a2829fc05a1ff9beb754d1e0296465eb000..b2fc2c8b75f1dcd8150de9706c809f5af7e434d0 100644 (file)
@@ -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>;
index 3d45a3d1e52ab864f217a9a6cc722d6e39b8b8e2..701edce5407c2e920c758e2094d1163bef741194 100644 (file)
@@ -19,12 +19,14 @@ zone <string> [ <class> ] {
        max-ixfr-ratio ( unlimited | <percentage> );
        max-journal-size ( default | unlimited | <sizeval> );
        max-records <integer>;
+       max-records-per-type <integer>;
        max-refresh-time <integer>;
        max-retry-time <integer>;
        max-transfer-idle-in <integer>;
        max-transfer-idle-out <integer>;
        max-transfer-time-in <integer>;
        max-transfer-time-out <integer>;
+       max-types-per-name <integer>;
        min-refresh-time <integer>;
        min-retry-time <integer>;
        multi-master <boolean>;
index 0dbcf101e1c3ed05b0e5228a0b3490c0a7df2b64..93eb156beb090d6249275f943d983f8d69a68262 100644 (file)
@@ -170,13 +170,16 @@ options {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder | resolver | update ) [
-            ( query | response ) ]; ... };
-        dnstap-identity ( <quoted_string> | none | hostname );
-        dnstap-output ( file | unix ) <quoted_string> [ size ( unlimited |
-            <size> ) ] [ versions ( unlimited | <integer> ) ] [ suffix (
-            increment | timestamp ) ];
-        dnstap-version ( <quoted_string> | none );
+        dnstap { ( all | auth | client | forwarder |
+            resolver | update ) [ ( query | response ) ];
+            ... }; // not configured
+        dnstap-identity ( <quoted_string> | none |
+            hostname ); // not configured
+        dnstap-output ( file | unix ) <quoted_string> [
+            size ( unlimited | <size> ) ] [ versions (
+            unlimited | <integer> ) ] [ suffix ( increment
+            | timestamp ) ]; // not configured
+        dnstap-version ( <quoted_string> | none ); // not configured
         dscp <integer>; // deprecated
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
@@ -200,13 +203,13 @@ options {
         forward ( first | only );
         forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
             | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
-        fstrm-set-buffer-hint <integer>;
-        fstrm-set-flush-timeout <integer>;
-        fstrm-set-input-queue-size <integer>;
-        fstrm-set-output-notify-threshold <integer>;
-        fstrm-set-output-queue-model ( mpsc | spsc );
-        fstrm-set-output-queue-size <integer>;
-        fstrm-set-reopen-interval <duration>;
+        fstrm-set-buffer-hint <integer>; // not configured
+        fstrm-set-flush-timeout <integer>; // not configured
+        fstrm-set-input-queue-size <integer>; // not configured
+        fstrm-set-output-notify-threshold <integer>; // not configured
+        fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
+        fstrm-set-output-queue-size <integer>; // not configured
+        fstrm-set-reopen-interval <duration>; // not configured
         geoip-directory ( <quoted_string> | none );
         geoip-use-ecs <boolean>; // obsolete
         glue-cache <boolean>;
@@ -243,6 +246,7 @@ options {
         max-journal-size ( default | unlimited | <sizeval> );
         max-ncache-ttl <duration>;
         max-records <integer>;
+        max-records-per-type <integer>;
         max-recursion-depth <integer>;
         max-recursion-queries <integer>;
         max-refresh-time <integer>;
@@ -253,6 +257,7 @@ options {
         max-transfer-idle-out <integer>;
         max-transfer-time-in <integer>;
         max-transfer-time-out <integer>;
+        max-types-per-name <integer>;
         max-udp-size <integer>;
         max-zone-ttl ( unlimited | <duration> );
         memstatistics <boolean>;
@@ -570,8 +575,9 @@ view <string> [ <class> ] {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder | resolver | update ) [
-            ( query | response ) ]; ... };
+        dnstap { ( all | auth | client | forwarder |
+            resolver | update ) [ ( query | response ) ];
+            ... }; // not configured
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
             <integer> ] [ dscp <integer> ] | <ipv6_address> [ port
@@ -623,6 +629,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>;
@@ -632,6 +639,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>;
@@ -855,12 +863,14 @@ view <string> [ <class> ] {
                 max-ixfr-ratio ( unlimited | <percentage> );
                 max-journal-size ( default | unlimited | <sizeval> );
                 max-records <integer>;
+                max-records-per-type <integer>;
                 max-refresh-time <integer>;
                 max-retry-time <integer>;
                 max-transfer-idle-in <integer>;
                 max-transfer-idle-out <integer>;
                 max-transfer-time-in <integer>;
                 max-transfer-time-out <integer>;
+                max-types-per-name <integer>;
                 max-zone-ttl ( unlimited | <duration> );
                 min-refresh-time <integer>;
                 min-retry-time <integer>;
@@ -972,12 +982,14 @@ zone <string> [ <class> ] {
         max-ixfr-ratio ( unlimited | <percentage> );
         max-journal-size ( default | unlimited | <sizeval> );
         max-records <integer>;
+        max-records-per-type <integer>;
         max-refresh-time <integer>;
         max-retry-time <integer>;
         max-transfer-idle-in <integer>;
         max-transfer-idle-out <integer>;
         max-transfer-time-in <integer>;
         max-transfer-time-out <integer>;
+        max-types-per-name <integer>;
         max-zone-ttl ( unlimited | <duration> );
         min-refresh-time <integer>;
         min-retry-time <integer>;
index eb75a86eae9517ccefbed5f279b358e88575fea2..1b748d96ad4a4354276990fb6345110acbb8ca5f 100644 (file)
@@ -156,13 +156,16 @@ options {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder | resolver | update ) [
-            ( query | response ) ]; ... };
-        dnstap-identity ( <quoted_string> | none | hostname );
-        dnstap-output ( file | unix ) <quoted_string> [ size ( unlimited |
-            <size> ) ] [ versions ( unlimited | <integer> ) ] [ suffix (
-            increment | timestamp ) ];
-        dnstap-version ( <quoted_string> | none );
+        dnstap { ( all | auth | client | forwarder |
+            resolver | update ) [ ( query | response ) ];
+            ... }; // not configured
+        dnstap-identity ( <quoted_string> | none |
+            hostname ); // not configured
+        dnstap-output ( file | unix ) <quoted_string> [
+            size ( unlimited | <size> ) ] [ versions (
+            unlimited | <integer> ) ] [ suffix ( increment
+            | timestamp ) ]; // not configured
+        dnstap-version ( <quoted_string> | none ); // not configured
         dscp <integer>; // deprecated
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
@@ -181,13 +184,13 @@ options {
         forward ( first | only );
         forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address>
             | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
-        fstrm-set-buffer-hint <integer>;
-        fstrm-set-flush-timeout <integer>;
-        fstrm-set-input-queue-size <integer>;
-        fstrm-set-output-notify-threshold <integer>;
-        fstrm-set-output-queue-model ( mpsc | spsc );
-        fstrm-set-output-queue-size <integer>;
-        fstrm-set-reopen-interval <duration>;
+        fstrm-set-buffer-hint <integer>; // not configured
+        fstrm-set-flush-timeout <integer>; // not configured
+        fstrm-set-input-queue-size <integer>; // not configured
+        fstrm-set-output-notify-threshold <integer>; // not configured
+        fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
+        fstrm-set-output-queue-size <integer>; // not configured
+        fstrm-set-reopen-interval <duration>; // not configured
         geoip-directory ( <quoted_string> | none );
         glue-cache <boolean>;
         heartbeat-interval <integer>;
@@ -217,6 +220,7 @@ options {
         max-journal-size ( default | unlimited | <sizeval> );
         max-ncache-ttl <duration>;
         max-records <integer>;
+        max-records-per-type <integer>;
         max-recursion-depth <integer>;
         max-recursion-queries <integer>;
         max-refresh-time <integer>;
@@ -227,6 +231,7 @@ options {
         max-transfer-idle-out <integer>;
         max-transfer-time-in <integer>;
         max-transfer-time-out <integer>;
+        max-types-per-name <integer>;
         max-udp-size <integer>;
         max-zone-ttl ( unlimited | <duration> );
         memstatistics <boolean>;
@@ -514,8 +519,9 @@ view <string> [ <class> ] {
         dnssec-secure-to-insecure <boolean>;
         dnssec-update-mode ( maintain | no-resign );
         dnssec-validation ( yes | no | auto );
-        dnstap { ( all | auth | client | forwarder | resolver | update ) [
-            ( query | response ) ]; ... };
+        dnstap { ( all | auth | client | forwarder |
+            resolver | update ) [ ( query | response ) ];
+            ... }; // not configured
         dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
             <integer> ] [ dscp <integer> ] | <ipv4_address> [ port
             <integer> ] [ dscp <integer> ] | <ipv6_address> [ port
@@ -560,6 +566,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>;
@@ -569,6 +576,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>;
@@ -775,12 +783,14 @@ view <string> [ <class> ] {
                 max-ixfr-ratio ( unlimited | <percentage> );
                 max-journal-size ( default | unlimited | <sizeval> );
                 max-records <integer>;
+                max-records-per-type <integer>;
                 max-refresh-time <integer>;
                 max-retry-time <integer>;
                 max-transfer-idle-in <integer>;
                 max-transfer-idle-out <integer>;
                 max-transfer-time-in <integer>;
                 max-transfer-time-out <integer>;
+                max-types-per-name <integer>;
                 max-zone-ttl ( unlimited | <duration> );
                 min-refresh-time <integer>;
                 min-retry-time <integer>;
@@ -885,12 +895,14 @@ zone <string> [ <class> ] {
         max-ixfr-ratio ( unlimited | <percentage> );
         max-journal-size ( default | unlimited | <sizeval> );
         max-records <integer>;
+        max-records-per-type <integer>;
         max-refresh-time <integer>;
         max-retry-time <integer>;
         max-transfer-idle-in <integer>;
         max-transfer-idle-out <integer>;
         max-transfer-time-in <integer>;
         max-transfer-time-out <integer>;
+        max-types-per-name <integer>;
         max-zone-ttl ( unlimited | <duration> );
         min-refresh-time <integer>;
         min-retry-time <integer>;
index 6a5ef660a2d09d4606d3389ffd20441145e84593..c4ab59ddadf21618933e84413745d4489cc620a0 100644 (file)
@@ -8,6 +8,8 @@ zone <string> [ <class> ] {
        masterfile-style ( full | relative );
        masters [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
        max-records <integer>;
+       max-records-per-type <integer>;
+       max-types-per-name <integer>;
        max-zone-ttl ( unlimited | <duration> );
        primaries [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
        zone-statistics ( full | terse | none | <boolean> );
index c46202dc5819f99f2fec284623cbaa7557b6ad72..52ce7cf81c5197277addd52a5bb40076f3698d44 100644 (file)
@@ -31,12 +31,14 @@ zone <string> [ <class> ] {
        max-ixfr-ratio ( unlimited | <percentage> );
        max-journal-size ( default | unlimited | <sizeval> );
        max-records <integer>;
+       max-records-per-type <integer>;
        max-refresh-time <integer>;
        max-retry-time <integer>;
        max-transfer-idle-in <integer>;
        max-transfer-idle-out <integer>;
        max-transfer-time-in <integer>;
        max-transfer-time-out <integer>;
+       max-types-per-name <integer>;
        min-refresh-time <integer>;
        min-retry-time <integer>;
        multi-master <boolean>;
index f89d46248a43473e9a06b6d43d2500a54bc496b8..102b980c7a6bd8c94064849cc8fac81e8572487b 100644 (file)
@@ -5,6 +5,8 @@ zone <string> [ <class> ] {
        forward ( first | only );
        forwarders [ port <integer> ] [ dscp <integer> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
        max-records <integer>;
+       max-records-per-type <integer>;
+       max-types-per-name <integer>;
        server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
        server-names { <string>; ... };
        zone-statistics ( full | terse | none | <boolean> );
index 2db604dae6d510564e6f2299ec449c5f6365c569..ca4bf1ce396a55f2a766a077f841064272b8b6a8 100644 (file)
@@ -13,10 +13,12 @@ zone <string> [ <class> ] {
        masterfile-style ( full | relative );
        masters [ port <integer> ] [ dscp <integer> ] { ( <remote-servers> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
        max-records <integer>;
+       max-records-per-type <integer>;
        max-refresh-time <integer>;
        max-retry-time <integer>;
        max-transfer-idle-in <integer>;
        max-transfer-time-in <integer>;
+       max-types-per-name <integer>;
        min-refresh-time <integer>;
        min-retry-time <integer>;
        multi-master <boolean>;
index b5d2b0995f230a439a8f89e75b049dc6529c8192..8cb442b45170396b40c2e291e4d3dabba6718718 100644 (file)
@@ -151,6 +151,8 @@ struct dns_cache {
        /* Locked by 'filelock'. */
        char *filename;
        /* Access to the on-disk cache file is also locked by 'filelock'. */
+
+       uint32_t maxrrperset;
 };
 
 /***
@@ -184,6 +186,7 @@ cache_create_db(dns_cache_t *cache, dns_db_t **db) {
        }
 
        dns_db_setservestalettl(*db, cache->serve_stale_ttl);
+       dns_db_setmaxrrperset(*db, cache->maxrrperset);
 
        if (cache->taskmgr == NULL) {
                return (ISC_R_SUCCESS);
@@ -1316,6 +1319,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
index f90add170e7f29f70ff302d3e4607cea4b1f386a..a575d6208fca620772853457e5f2b6c1e2eae46b 100644 (file)
@@ -1137,3 +1137,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);
+       }
+}
index 8c04337786d88f18543ee70bc6c6cc33c4567a1e..f4d9bae5f05f97c82b8f81f0fb0b45a2444c2091 100644 (file)
@@ -975,7 +975,8 @@ static dns_dbmethods_t rpsdb_db_methods = {
        NULL, /* setservestalerefresh */
        NULL, /* getservestalerefresh */
        NULL, /* setgluecachestats */
-       NULL  /* adjusthashsize */
+       NULL, /* adjusthashsize */
+       NULL  /* setmaxrrperset */
 };
 
 static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
index abbb8d9697fe79876dcf325b94db5bfd8ec9a561..42a1248790c5266708834598b81443c2ec542064 100644 (file)
@@ -428,7 +428,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
        }
 
        result = dns_rdataslab_fromrdataset(rdataset, mctx, &r,
-                                           sizeof(rdatasetheader_t));
+                                           sizeof(rdatasetheader_t), 0);
        if (result != ISC_R_SUCCESS) {
                goto unlock;
        }
@@ -560,7 +560,11 @@ static dns_dbmethods_t ecdb_methods = {
        NULL, /* getsize */
        NULL, /* setservestalettl */
        NULL, /* getservestalettl */
-       NULL  /* setgluecachestats */
+       NULL, /* setservestalerefresh */
+       NULL, /* getservestalerefresh */
+       NULL, /* setgluecachestats */
+       NULL, /* adjusthashsize */
+       NULL  /* setmaxrrperset */
 };
 
 static isc_result_t
index 02dd1ac4d04a4f02e67aacf337852a8ef502fb09..34539eb9791652eb43c88375b3940ee9501372a0 100644 (file)
@@ -334,6 +334,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);
index ae276393c2c48355ef699bf31619d1a9e729eaf6..e0d17f26321621682f6712640e9db2a0c2dfd036 100644 (file)
@@ -184,6 +184,7 @@ typedef struct dns_dbmethods {
        isc_result_t (*getservestalerefresh)(dns_db_t *db, uint32_t *interval);
        isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
        isc_result_t (*adjusthashsize)(dns_db_t *db, size_t size);
+       void (*setmaxrrperset)(dns_db_t *db, uint32_t value);
 } dns_dbmethods_t;
 
 typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t       *mctx,
@@ -1796,6 +1797,13 @@ dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats);
  *     dns_rdatasetstats_create(); otherwise NULL.
  */
 
+void
+dns_db_setmaxrrperset(dns_db_t *db, uint32_t value);
+/*%<
+ * Set the maximum permissible number of RRs per RRset. If 'value'
+ * is nonzero, then any subsequent attempt to add an rdataset with
+ * more than 'value' RRs will return ISC_R_NOSPACE.
+ */
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_DB_H */
index 5a1c30f9e44c88467d1ac32b0006274000f1e213..89c8fc25f5570fbde18be889abd6fc9cfc7368d5 100644 (file)
@@ -67,7 +67,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'.
@@ -123,7 +124,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'.
  */
index d6e7f10e1893395001e93c3494c16257b89465f6..b7cf663cb58880c2381b20dffe478632ed3e8ad9 100644 (file)
@@ -188,6 +188,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,
@@ -1354,6 +1355,12 @@ dns_view_staleanswerenabled(dns_view_t *view);
  *\li  'view' to be valid.
  */
 
+void
+dns_view_setmaxrrperset(dns_view_t *view, uint32_t value);
+/*%<
+ * Set the maximum resource records per RRSet that can be cached.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_VIEW_H */
index 4bdc936949a48a1ce9b7bee5b961e6b051684679..a98b28f225583504b9ed99896de285be3f2f9473 100644 (file)
@@ -164,6 +164,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);
 /*%<
@@ -332,6 +345,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);
 /*%<
index 9670671d1e3817337e919af22f0ff5e2a987804d..06228c910e3add3bb01f39b324a502a6fdf8786b 100644 (file)
@@ -496,6 +496,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;
@@ -6538,7 +6539,7 @@ find_header:
                                        rbtdb->common.mctx,
                                        rbtdb->common.rdclass,
                                        (dns_rdatatype_t)header->type, flags,
-                                       &merged);
+                                       rbtdb->maxrrperset, &merged);
                        }
                        if (result == ISC_R_SUCCESS) {
                                /*
@@ -6896,7 +6897,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;
@@ -6917,12 +6918,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;
        }
@@ -6941,7 +6942,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;
@@ -6962,12 +6963,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;
        }
@@ -7048,7 +7049,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);
        }
@@ -7106,7 +7108,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);
@@ -7114,7 +7117,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);
@@ -7268,7 +7272,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);
        }
@@ -7672,7 +7677,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);
        }
@@ -8612,6 +8618,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;
@@ -8735,7 +8750,8 @@ static dns_dbmethods_t zone_methods = { attach,
                                        NULL, /* setservestalerefresh */
                                        NULL, /* getservestalerefresh */
                                        setgluecachestats,
-                                       adjusthashsize };
+                                       adjusthashsize,
+                                       setmaxrrperset };
 
 static dns_dbmethods_t cache_methods = { attach,
                                         detach,
@@ -8787,7 +8803,8 @@ static dns_dbmethods_t cache_methods = { attach,
                                         setservestalerefresh,
                                         getservestalerefresh,
                                         NULL,
-                                        adjusthashsize };
+                                        adjusthashsize,
+                                        setmaxrrperset };
 
 isc_result_t
 dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
index d74e84ce4a6cfff7c7b90ca3f86ab074fe20ab24..bf4e0453caced3a68113a0d1f1f15615d864d2a0 100644 (file)
@@ -118,7 +118,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.
@@ -160,7 +161,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
                return (ISC_R_SUCCESS);
        }
 
-       if (nitems > DNS_RDATASET_MAX_RECORDS) {
+       if (maxrrperset > 0 && nitems > maxrrperset) {
                return (DNS_R_TOOMANYRECORDS);
        }
 
@@ -492,7 +493,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;
@@ -532,7 +534,7 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
 #endif /* if DNS_RDATASET_FIXED */
        INSIST(ocount > 0 && ncount > 0);
 
-       if (ocount + ncount > DNS_RDATASET_MAX_RECORDS) {
+       if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
                return (DNS_R_TOOMANYRECORDS);
        }
 
index 7822d6ef14398a2a9028a9b52e8088f2c3447b9d..282c3271f5bccca83d5a03f7fa7e41bc9ac67f60 100644 (file)
@@ -1319,7 +1319,8 @@ static dns_dbmethods_t sdb_methods = {
        NULL, /* setservestalerefresh */
        NULL, /* getservestalerefresh */
        NULL, /* setgluecachestats */
-       NULL  /* adjusthashsize */
+       NULL, /* adjusthashsize */
+       NULL  /* setmaxrrperset */
 };
 
 static isc_result_t
index 106e24ba704ca58ea6ff8707f5f4c219d24d3c07..299c7d857d84dd2f709cf7cfe1c67bbb8a6090ae 100644 (file)
@@ -1292,7 +1292,8 @@ static dns_dbmethods_t sdlzdb_methods = {
        NULL, /* setservestalerefresh */
        NULL, /* getservestalerefresh */
        NULL, /* setgluecachestats */
-       NULL  /* adjusthashsize */
+       NULL, /* adjusthashsize */
+       NULL  /* setmaxrrperset */
 };
 
 /*
index a67dd73a3ca73366fcdc7cc6537d518a14de3d73..9f5daf793bb9d035fcbfdb09d68c3e9b75f2b5af 100644 (file)
@@ -871,6 +871,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
@@ -2640,3 +2642,12 @@ dns_view_staleanswerenabled(dns_view_t *view) {
 
        return (result);
 }
+
+void
+dns_view_setmaxrrperset(dns_view_t *view, uint32_t value) {
+       REQUIRE(DNS_VIEW_VALID(view));
+       view->maxrrperset = value;
+       if (view->cache != NULL) {
+               dns_cache_setmaxrrperset(view->cache, value);
+       }
+}
index a54d0d84a266b94ff526b6ba7efc3a8d3f8b3a13..9d72b8240a2a7630e112b31d645b4d85171e3e64 100644 (file)
@@ -205,8 +205,6 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task,
 static isc_result_t
 axfr_init(dns_xfrin_ctx_t *xfr);
 static isc_result_t
-axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
-static isc_result_t
 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
             dns_ttl_t ttl, dns_rdata_t *rdata);
 static isc_result_t
@@ -279,7 +277,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;
@@ -287,22 +289,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) {
index e31916fcfc98b085562dbb23c9ed8cc03bd0ada5..ff06849cd93f772bbffacc1d86445ede9f836883 100644 (file)
@@ -307,6 +307,7 @@ struct dns_zone {
        uint32_t minretry;
 
        uint32_t maxrecords;
+       uint32_t maxrrperset;
 
        isc_sockaddr_t *masters;
        isc_dscp_t *masterdscps;
@@ -2304,31 +2305,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, 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) {
@@ -12313,6 +12296,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) {
@@ -14726,6 +14719,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);
@@ -17468,6 +17462,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);
 
@@ -23615,3 +23610,44 @@ zone_nsecttl(dns_zone_t *zone) {
 
        return (ISC_MIN(zone->minimum, zone->soattl));
 }
+
+isc_result_t
+dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(dbp != NULL && *dbp == NULL);
+
+       dns_db_t *db = NULL;
+
+       isc_result_t result = dns_db_create(
+               zone->mctx, zone->db_argv[0], &zone->origin,
+               (zone->type == dns_zone_stub) ? dns_dbtype_stub
+                                             : dns_dbtype_zone,
+               zone->rdclass, zone->db_argc - 1, zone->db_argv + 1, &db);
+       if (result != ISC_R_SUCCESS) {
+               return (result);
+       }
+
+       switch (zone->type) {
+       case dns_zone_primary:
+       case dns_zone_secondary:
+       case dns_zone_mirror:
+               result = dns_db_setgluecachestats(db, zone->gluecachestats);
+               if (result == ISC_R_NOTIMPLEMENTED) {
+                       result = ISC_R_SUCCESS;
+               }
+               if (result != ISC_R_SUCCESS) {
+                       dns_db_detach(&db);
+                       return (result);
+               }
+               break;
+       default:
+               break;
+       }
+
+       dns_db_settask(db, zone->task, zone->task);
+       dns_db_setmaxrrperset(db, zone->maxrrperset);
+
+       *dbp = db;
+
+       return (ISC_R_SUCCESS);
+}
index 6e63d86816e164a38ca4f2331d4790f1a03de223..ffe22b39c4f924c92ee9d7124ea5c7a2c19a4e1f 100644 (file)
@@ -2241,6 +2241,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,