mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-29 13:38:26 +00:00
Merge branch '3405-security-limit-the-number-of-resource-records-in-rrset' into 'v9.20.0-release'
Limit the number of RRs in RRSets See merge request isc-private/bind9!694
This commit is contained in:
commit
24e8cc7b38
16
CHANGES
16
CHANGES
@ -1,3 +1,19 @@
|
|||||||
|
6401. [security] An excessively large number of rrtypes per owner can
|
||||||
|
slow down database query processing, so a limit has been
|
||||||
|
placed on the number of rrtypes that can be stored per
|
||||||
|
owner (node) in a cache or zone database. This is
|
||||||
|
configured with the new "max-rrtypes-per-name" option,
|
||||||
|
and defaults to 100. (CVE-2024-1737)
|
||||||
|
[GL #3403] [GL #4548]
|
||||||
|
|
||||||
|
6400. [security] Excessively large rdatasets can slow down database
|
||||||
|
query processing, so a limit has been placed on the
|
||||||
|
number of records that can be stored per rdataset
|
||||||
|
in a cache or zone database. This is configured
|
||||||
|
with the new "max-records-per-type" option, and
|
||||||
|
defaults to 100. (CVE-2024-1737)
|
||||||
|
[GL #497] [GL #3405]
|
||||||
|
|
||||||
6399. [security] Malicious DNS client that sends many queries over
|
6399. [security] Malicious DNS client that sends many queries over
|
||||||
TCP but never reads responses can cause server to
|
TCP but never reads responses can cause server to
|
||||||
respond slowly or not respond at all for other
|
respond slowly or not respond at all for other
|
||||||
|
@ -222,8 +222,10 @@ options {\n\
|
|||||||
ixfr-from-differences false;\n\
|
ixfr-from-differences false;\n\
|
||||||
max-journal-size default;\n\
|
max-journal-size default;\n\
|
||||||
max-records 0;\n\
|
max-records 0;\n\
|
||||||
|
max-records-per-type 100;\n\
|
||||||
max-refresh-time 2419200; /* 4 weeks */\n\
|
max-refresh-time 2419200; /* 4 weeks */\n\
|
||||||
max-retry-time 1209600; /* 2 weeks */\n\
|
max-retry-time 1209600; /* 2 weeks */\n\
|
||||||
|
max-types-per-name 100;\n\
|
||||||
max-transfer-idle-in 60;\n\
|
max-transfer-idle-in 60;\n\
|
||||||
max-transfer-idle-out 60;\n\
|
max-transfer-idle-out 60;\n\
|
||||||
max-transfer-time-in 120;\n\
|
max-transfer-time-in 120;\n\
|
||||||
|
@ -5454,6 +5454,24 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||||||
dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj),
|
dns_resolver_setclientsperquery(view->resolver, cfg_obj_asuint32(obj),
|
||||||
max_clients_per_query);
|
max_clients_per_query);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is used for the cache and also as a default value
|
||||||
|
* for zone databases.
|
||||||
|
*/
|
||||||
|
obj = NULL;
|
||||||
|
result = named_config_get(maps, "max-records-per-type", &obj);
|
||||||
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
|
dns_view_setmaxrrperset(view, cfg_obj_asuint32(obj));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is used for the cache and also as a default value
|
||||||
|
* for zone databases.
|
||||||
|
*/
|
||||||
|
obj = NULL;
|
||||||
|
result = named_config_get(maps, "max-types-per-name", &obj);
|
||||||
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
|
dns_view_setmaxtypepername(view, cfg_obj_asuint32(obj));
|
||||||
|
|
||||||
obj = NULL;
|
obj = NULL;
|
||||||
result = named_config_get(maps, "max-recursion-depth", &obj);
|
result = named_config_get(maps, "max-recursion-depth", &obj);
|
||||||
INSIST(result == ISC_R_SUCCESS);
|
INSIST(result == ISC_R_SUCCESS);
|
||||||
|
@ -1074,6 +1074,22 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||||||
dns_zone_setmaxrecords(zone, 0);
|
dns_zone_setmaxrecords(zone, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj = NULL;
|
||||||
|
result = named_config_get(maps, "max-records-per-type", &obj);
|
||||||
|
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||||
|
dns_zone_setmaxrrperset(mayberaw, cfg_obj_asuint32(obj));
|
||||||
|
if (zone != mayberaw) {
|
||||||
|
dns_zone_setmaxrrperset(zone, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = NULL;
|
||||||
|
result = named_config_get(maps, "max-types-per-name", &obj);
|
||||||
|
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||||
|
dns_zone_setmaxtypepername(mayberaw, cfg_obj_asuint32(obj));
|
||||||
|
if (zone != mayberaw) {
|
||||||
|
dns_zone_setmaxtypepername(zone, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (raw != NULL && filename != NULL) {
|
if (raw != NULL && filename != NULL) {
|
||||||
#define SIGNED ".signed"
|
#define SIGNED ".signed"
|
||||||
size_t signedlen = strlen(filename) + sizeof(SIGNED);
|
size_t signedlen = strlen(filename) + sizeof(SIGNED);
|
||||||
|
@ -98,6 +98,7 @@ options {
|
|||||||
tcp-initial-timeout 1200;
|
tcp-initial-timeout 1200;
|
||||||
transfers-in 100;
|
transfers-in 100;
|
||||||
transfers-out 100;
|
transfers-out 100;
|
||||||
|
max-records-per-type 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
trust-anchors { };
|
trust-anchors { };
|
||||||
|
@ -52,6 +52,7 @@ options {
|
|||||||
ixfr-from-differences yes;
|
ixfr-from-differences yes;
|
||||||
check-integrity no;
|
check-integrity no;
|
||||||
dnssec-validation yes;
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
transfers-in 100;
|
transfers-in 100;
|
||||||
transfers-out 100;
|
transfers-out 100;
|
||||||
};
|
};
|
||||||
|
@ -44,6 +44,7 @@ options {
|
|||||||
ixfr-from-differences yes;
|
ixfr-from-differences yes;
|
||||||
check-integrity no;
|
check-integrity no;
|
||||||
dnssec-validation yes;
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
trust-anchors { };
|
trust-anchors { };
|
||||||
|
@ -52,6 +52,7 @@ options {
|
|||||||
ixfr-from-differences yes;
|
ixfr-from-differences yes;
|
||||||
check-integrity no;
|
check-integrity no;
|
||||||
dnssec-validation yes;
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
trust-anchors { };
|
trust-anchors { };
|
||||||
|
@ -40,6 +40,7 @@ options {
|
|||||||
ixfr-from-differences yes;
|
ixfr-from-differences yes;
|
||||||
check-integrity no;
|
check-integrity no;
|
||||||
dnssec-validation yes;
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
trust-anchors { };
|
trust-anchors { };
|
||||||
|
@ -23,6 +23,7 @@ options {
|
|||||||
notify yes;
|
notify yes;
|
||||||
minimal-responses no;
|
minimal-responses no;
|
||||||
dnssec-validation no;
|
dnssec-validation no;
|
||||||
|
max-records-per-type 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
zone "." {
|
zone "." {
|
||||||
|
@ -26,7 +26,12 @@ $CHECKZONE -D -F raw=0 -o example.db.compat example-compat \
|
|||||||
example.db >/dev/null 2>&1
|
example.db >/dev/null 2>&1
|
||||||
$CHECKZONE -D -F raw -L 3333 -o example.db.serial.raw example \
|
$CHECKZONE -D -F raw -L 3333 -o example.db.serial.raw example \
|
||||||
example.db >/dev/null 2>&1
|
example.db >/dev/null 2>&1
|
||||||
$CHECKZONE -D -F raw -o large.db.raw large large.db >/dev/null 2>&1
|
$CHECKZONE -D -F raw -o under-limit.db.raw under-limit under-limit.db >/dev/null 2>&1
|
||||||
|
$CHECKZONE -D -F raw -o under-limit-kasp.db.raw under-limit-kasp under-limit-kasp.db >/dev/null 2>&1
|
||||||
|
$CHECKZONE -D -F raw -o on-limit.db.raw on-limit on-limit.db >/dev/null 2>&1
|
||||||
|
$CHECKZONE -D -F raw -o on-limit-kasp.db.raw on-limit-kasp on-limit-kasp.db >/dev/null 2>&1
|
||||||
|
$CHECKZONE -D -F raw -o over-limit.db.raw over-limit over-limit.db >/dev/null 2>&1
|
||||||
|
$CHECKZONE -D -F raw -o 255types.db.raw 255types 255types.db >/dev/null 2>&1
|
||||||
|
|
||||||
$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed >/dev/null 2>&1
|
$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed >/dev/null 2>&1
|
||||||
$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed >/dev/null 2>&1
|
$KEYGEN -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed >/dev/null 2>&1
|
||||||
|
@ -23,6 +23,8 @@ options {
|
|||||||
session-keyfile "session.key";
|
session-keyfile "session.key";
|
||||||
servfail-ttl 0;
|
servfail-ttl 0;
|
||||||
dnssec-validation no;
|
dnssec-validation no;
|
||||||
|
max-records-per-type 2050;
|
||||||
|
max-types-per-name 500;
|
||||||
};
|
};
|
||||||
|
|
||||||
key rndc_key {
|
key rndc_key {
|
||||||
@ -78,9 +80,48 @@ zone "transfer4" {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
zone "large" {
|
zone "under-limit" {
|
||||||
type primary;
|
type primary;
|
||||||
file "large.db.raw";
|
file "under-limit.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "under-limit-kasp" {
|
||||||
|
type primary;
|
||||||
|
file "under-limit-kasp.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy masterformat;
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "on-limit" {
|
||||||
|
type primary;
|
||||||
|
file "on-limit.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "on-limit-kasp" {
|
||||||
|
type primary;
|
||||||
|
file "on-limit-kasp.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy masterformat;
|
||||||
|
inline-signing no;
|
||||||
|
allow-update { any; };
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "over-limit" {
|
||||||
|
type primary;
|
||||||
|
file "over-limit.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "255types" {
|
||||||
|
type primary;
|
||||||
|
file "255types.db.raw";
|
||||||
masterfile-format raw;
|
masterfile-format raw;
|
||||||
allow-transfer { any; };
|
allow-transfer { any; };
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,8 @@ options {
|
|||||||
notify no;
|
notify no;
|
||||||
servfail-ttl 0;
|
servfail-ttl 0;
|
||||||
dnssec-validation no;
|
dnssec-validation no;
|
||||||
|
max-records-per-type 2000;
|
||||||
|
max-types-per-name 200;
|
||||||
};
|
};
|
||||||
|
|
||||||
zone "example" {
|
zone "example" {
|
||||||
@ -56,9 +58,37 @@ zone "transfer4" {
|
|||||||
file "transfer.db.full";
|
file "transfer.db.full";
|
||||||
};
|
};
|
||||||
|
|
||||||
zone "large" {
|
zone "under-limit" {
|
||||||
type secondary;
|
type secondary;
|
||||||
primaries { 10.53.0.1; };
|
primaries { 10.53.0.1; };
|
||||||
masterfile-format raw;
|
masterfile-format raw;
|
||||||
file "large.bk";
|
file "under-limit.bk";
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "under-limit-kasp" {
|
||||||
|
type secondary;
|
||||||
|
primaries { 10.53.0.1; };
|
||||||
|
masterfile-format raw;
|
||||||
|
file "under-limit-kasp.bk";
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "on-limit" {
|
||||||
|
type secondary;
|
||||||
|
primaries { 10.53.0.1; };
|
||||||
|
masterfile-format raw;
|
||||||
|
file "on-limit.bk";
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "on-limit-kasp" {
|
||||||
|
type secondary;
|
||||||
|
primaries { 10.53.0.1; };
|
||||||
|
masterfile-format raw;
|
||||||
|
file "on-limit-kasp.bk";
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "255types" {
|
||||||
|
type secondary;
|
||||||
|
primaries { 10.53.0.1; };
|
||||||
|
masterfile-format raw;
|
||||||
|
file "255types.bk";
|
||||||
};
|
};
|
||||||
|
21
bin/tests/system/masterformat/ns4/compile.sh
Executable file
21
bin/tests/system/masterformat/ns4/compile.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
#
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
#
|
||||||
|
# See the COPYRIGHT file distributed with this work for additional
|
||||||
|
# information regarding copyright ownership.
|
||||||
|
|
||||||
|
# shellcheck source=conf.sh
|
||||||
|
. ../../conf.sh
|
||||||
|
|
||||||
|
for zone in kasp-max-records-per-type \
|
||||||
|
kasp-max-records-per-type-dnskey \
|
||||||
|
kasp-max-types-per-name; do
|
||||||
|
$CHECKZONE -D -F raw -o $zone.db.raw $zone template.db >/dev/null 2>&1
|
||||||
|
done
|
28
bin/tests/system/masterformat/ns4/kasp.db
Normal file
28
bin/tests/system/masterformat/ns4/kasp.db
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
;
|
||||||
|
; SPDX-License-Identifier: MPL-2.0
|
||||||
|
;
|
||||||
|
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
;
|
||||||
|
; See the COPYRIGHT file distributed with this work for additional
|
||||||
|
; information regarding copyright ownership.
|
||||||
|
|
||||||
|
$TTL 1D
|
||||||
|
|
||||||
|
@ IN SOA ns hostmaster (
|
||||||
|
1
|
||||||
|
3600
|
||||||
|
1800
|
||||||
|
1814400
|
||||||
|
3
|
||||||
|
)
|
||||||
|
NS ns
|
||||||
|
ns A 10.53.0.1
|
||||||
|
mx MX 10 mail
|
||||||
|
a A 10.53.0.1
|
||||||
|
aaaa AAAA 2001:db8::53
|
||||||
|
cname CNAME cname-target
|
||||||
|
dname DNAME dname-target
|
||||||
|
txt TXT "this is text"
|
89
bin/tests/system/masterformat/ns4/named1.conf.in
Normal file
89
bin/tests/system/masterformat/ns4/named1.conf.in
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* See the COPYRIGHT file distributed with this work for additional
|
||||||
|
* information regarding copyright ownership.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NS4
|
||||||
|
|
||||||
|
options {
|
||||||
|
pid-file "named.pid";
|
||||||
|
listen-on port @PORT@ { 10.53.0.4; };
|
||||||
|
port @PORT@;
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
recursion no;
|
||||||
|
notify no;
|
||||||
|
session-keyfile "session.key";
|
||||||
|
servfail-ttl 0;
|
||||||
|
dnssec-validation no;
|
||||||
|
|
||||||
|
/* Ridicously low on purpose */
|
||||||
|
max-records-per-type 1;
|
||||||
|
max-types-per-name 11;
|
||||||
|
};
|
||||||
|
|
||||||
|
key rndc_key {
|
||||||
|
secret "1234abcd8765";
|
||||||
|
algorithm @DEFAULT_HMAC@;
|
||||||
|
};
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||||
|
};
|
||||||
|
|
||||||
|
dnssec-policy "masterformat" {
|
||||||
|
keys {
|
||||||
|
ksk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
|
||||||
|
zsk key-directory lifetime unlimited algorithm @DEFAULT_ALGORITHM@;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This one should be okay, since the default policy only introduces one DNSKEY
|
||||||
|
* and each signature covering a different type is considered a separate RRset.
|
||||||
|
*/
|
||||||
|
zone "kasp-max-records-per-type" {
|
||||||
|
type primary;
|
||||||
|
file "kasp-max-records-per-type.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy "default";
|
||||||
|
inline-signing no;
|
||||||
|
allow-update { any; };
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This one uses a ZSK / KSK, so that is two records in one RRset,
|
||||||
|
* thus it should fail to sign.
|
||||||
|
*/
|
||||||
|
zone "kasp-max-records-per-type-dnskey" {
|
||||||
|
type primary;
|
||||||
|
file "kasp-max-records-per-type-dnskey.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy "masterformat";
|
||||||
|
inline-signing no;
|
||||||
|
allow-update { any; };
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The template zone is fine and should be possible to sign, but when
|
||||||
|
* adding an extra type to the apex the max-types-per-name will be exceeded,
|
||||||
|
* meaning the update should fail.
|
||||||
|
*/
|
||||||
|
zone "kasp-max-types-per-name" {
|
||||||
|
type primary;
|
||||||
|
file "kasp-max-types-per-name.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy "default";
|
||||||
|
inline-signing no;
|
||||||
|
allow-update { any; };
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
53
bin/tests/system/masterformat/ns4/named2.conf.in
Normal file
53
bin/tests/system/masterformat/ns4/named2.conf.in
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* See the COPYRIGHT file distributed with this work for additional
|
||||||
|
* information regarding copyright ownership.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// NS4
|
||||||
|
|
||||||
|
options {
|
||||||
|
pid-file "named.pid";
|
||||||
|
listen-on port @PORT@ { 10.53.0.4; };
|
||||||
|
port @PORT@;
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
recursion no;
|
||||||
|
notify no;
|
||||||
|
session-keyfile "session.key";
|
||||||
|
servfail-ttl 0;
|
||||||
|
dnssec-validation no;
|
||||||
|
|
||||||
|
/* Ridicously low on purpose */
|
||||||
|
max-records-per-type 1;
|
||||||
|
max-types-per-name 9;
|
||||||
|
};
|
||||||
|
|
||||||
|
key rndc_key {
|
||||||
|
secret "1234abcd8765";
|
||||||
|
algorithm @DEFAULT_HMAC@;
|
||||||
|
};
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The template zone is fine, but when adding the DNSSEC records to the apex,
|
||||||
|
* the max-types-per-name will be exceeded, meaning signing should fail.
|
||||||
|
*/
|
||||||
|
zone "kasp-max-types-per-name" {
|
||||||
|
type primary;
|
||||||
|
file "kasp-max-types-per-name.db.raw";
|
||||||
|
masterfile-format raw;
|
||||||
|
dnssec-policy "default";
|
||||||
|
inline-signing no;
|
||||||
|
allow-update { any; };
|
||||||
|
allow-transfer { any; };
|
||||||
|
};
|
28
bin/tests/system/masterformat/ns4/template.db
Normal file
28
bin/tests/system/masterformat/ns4/template.db
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
;
|
||||||
|
; SPDX-License-Identifier: MPL-2.0
|
||||||
|
;
|
||||||
|
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
; file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
;
|
||||||
|
; See the COPYRIGHT file distributed with this work for additional
|
||||||
|
; information regarding copyright ownership.
|
||||||
|
|
||||||
|
$TTL 1D
|
||||||
|
|
||||||
|
@ IN SOA ns hostmaster (
|
||||||
|
1
|
||||||
|
3600
|
||||||
|
1800
|
||||||
|
1814400
|
||||||
|
3
|
||||||
|
)
|
||||||
|
NS ns
|
||||||
|
ns A 10.53.0.1
|
||||||
|
mx MX 10 mail
|
||||||
|
a A 10.53.0.1
|
||||||
|
aaaa AAAA 2001:db8::53
|
||||||
|
cname CNAME cname-target
|
||||||
|
dname DNAME dname-target
|
||||||
|
txt TXT "this is text"
|
@ -19,13 +19,44 @@ $SHELL clean.sh
|
|||||||
copy_setports ns1/named.conf.in ns1/named.conf
|
copy_setports ns1/named.conf.in ns1/named.conf
|
||||||
copy_setports ns2/named.conf.in ns2/named.conf
|
copy_setports ns2/named.conf.in ns2/named.conf
|
||||||
copy_setports ns3/named.conf.in ns3/named.conf
|
copy_setports ns3/named.conf.in ns3/named.conf
|
||||||
|
copy_setports ns4/named1.conf.in ns4/named.conf
|
||||||
|
|
||||||
cp ns1/example.db ns2/
|
cp ns1/example.db ns2/
|
||||||
cp ns2/formerly-text.db.in ns2/formerly-text.db
|
cp ns2/formerly-text.db.in ns2/formerly-text.db
|
||||||
cp ns1/large.db.in ns1/large.db
|
cp ns1/empty.db.in ns1/under-limit.db
|
||||||
|
|
||||||
|
# counts are set with respect to these limits in named.conf:
|
||||||
|
# max-records-per-type 2050;
|
||||||
|
# max-types-per-name 500;
|
||||||
awk 'END {
|
awk 'END {
|
||||||
for (i = 0; i < 512; i++ ) { print "a TXT", i; }
|
for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; }
|
||||||
for (i = 0; i < 1024; i++ ) { print "b TXT", i; }
|
for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; }
|
||||||
for (i = 0; i < 2000; i++ ) { print "c TXT", i; }
|
for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; }
|
||||||
}' </dev/null >>ns1/large.db
|
}' </dev/null >>ns1/under-limit.db
|
||||||
cd ns1 && $SHELL compile.sh
|
cp ns1/under-limit.db ns1/under-limit-kasp.db
|
||||||
|
|
||||||
|
cp ns1/empty.db.in ns1/on-limit.db
|
||||||
|
awk 'END {
|
||||||
|
for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; }
|
||||||
|
for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; }
|
||||||
|
for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; }
|
||||||
|
for (i = 0; i < 2050; i++ ) { print "2050-txt TXT", i; }
|
||||||
|
}' </dev/null >>ns1/on-limit.db
|
||||||
|
cp ns1/on-limit.db ns1/on-limit-kasp.db
|
||||||
|
|
||||||
|
cp ns1/empty.db.in ns1/over-limit.db
|
||||||
|
awk 'END {
|
||||||
|
for (i = 0; i < 500; i++ ) { print "500-txt TXT", i; }
|
||||||
|
for (i = 0; i < 1000; i++ ) { print "1000-txt TXT", i; }
|
||||||
|
for (i = 0; i < 2000; i++ ) { print "2000-txt TXT", i; }
|
||||||
|
for (i = 0; i < 2050; i++ ) { print "2050-txt TXT", i; }
|
||||||
|
for (i = 0; i < 2100; i++ ) { print "2100-txt TXT", i; }
|
||||||
|
}' </dev/null >>ns1/over-limit.db
|
||||||
|
|
||||||
|
cp ns1/empty.db.in ns1/255types.db
|
||||||
|
for ntype in $(seq 65280 65534); do
|
||||||
|
echo "m TYPE${ntype} \# 0"
|
||||||
|
done >>ns1/255types.db
|
||||||
|
echo "m TXT bunny" >>ns1/255types.db
|
||||||
|
(cd ns1 && $SHELL compile.sh)
|
||||||
|
(cd ns4 && $SHELL compile.sh)
|
||||||
|
@ -134,7 +134,7 @@ n=$((n + 1))
|
|||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "waiting for transfers to complete"
|
echo_i "waiting for transfers to complete"
|
||||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
test -f ns2/transfer.db.raw -a -f ns2/transfer.db.txt && break
|
test -f ns2/transfer.db.raw -a -f ns2/transfer.db.txt && break
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
@ -162,7 +162,7 @@ n=$((n + 1))
|
|||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "checking that secondary formerly in text format is now raw ($n)"
|
echo_i "checking that secondary formerly in text format is now raw ($n)"
|
||||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
ret=0
|
ret=0
|
||||||
israw ns2/formerly-text.db >/dev/null 2>&1 || ret=1
|
israw ns2/formerly-text.db >/dev/null 2>&1 || ret=1
|
||||||
[ "$(rawversion ns2/formerly-text.db)" -eq 1 ] || ret=1
|
[ "$(rawversion ns2/formerly-text.db)" -eq 1 ] || ret=1
|
||||||
@ -173,12 +173,12 @@ n=$((n + 1))
|
|||||||
[ $ret -eq 0 ] || echo_i "failed"
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "checking that large rdatasets loaded ($n)"
|
echo_i "checking that under-limit rdatasets loaded ($n)"
|
||||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
ret=0
|
ret=0
|
||||||
for a in a b c; do
|
for rrcount in 500-txt 1000-txt 2000-txt; do
|
||||||
$DIG +tcp txt "${a}.large" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.test$n"
|
$DIG +tcp txt "${rrcount}.under-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
grep "status: NOERROR" "dig.out.ns2.test$n" >/dev/null || ret=1
|
grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
done
|
done
|
||||||
[ $ret -eq 0 ] && break
|
[ $ret -eq 0 ] && break
|
||||||
sleep 1
|
sleep 1
|
||||||
@ -187,6 +187,253 @@ n=$((n + 1))
|
|||||||
[ $ret -eq 0 ] || echo_i "failed"
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that under-limit rdatasets transfered ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt; do
|
||||||
|
$DIG +tcp txt "${rrcount}.under-limit" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that under-limit-kasp dnskeys loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
$DIG +tcp +dnssec dnskey "under-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.dnskey.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.dnskey.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns1.dnskey.test$n" >/dev/null || ret=1
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that under-limit-kasp rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt; do
|
||||||
|
$DIG +tcp +dnssec txt "${rrcount}.under-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that under-limit-kasp rdatasets transfered ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt; do
|
||||||
|
$DIG +tcp +dnssec txt "${rrcount}.under-limit-kasp" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that on-limit rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do
|
||||||
|
$DIG +tcp txt "${rrcount}.on-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that on-limit rdatasets not transfered ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do
|
||||||
|
$DIG +tcp txt "${rrcount}.on-limit" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n"
|
||||||
|
grep "status: SERVFAIL" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that on-limit-kasp rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do
|
||||||
|
$DIG +tcp +dnssec txt "${rrcount}.on-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that on-limit-kasp rdatasets not transfered ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do
|
||||||
|
$DIG +tcp +dnssec txt "${rrcount}.on-limit-kasp" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.$rrcount.test$n"
|
||||||
|
grep "status: SERVFAIL" "dig.out.ns2.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that over-limit rdatasets not loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt 2100-txt; do
|
||||||
|
$DIG +tcp txt "${rrcount}.over-limit" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
|
grep "status: SERVFAIL" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that kasp-max-records-per-type rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrtype in soa dnskey ns; do
|
||||||
|
$DIG +tcp +dnssec $rrtype "kasp-max-records-per-type" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that kasp-max-records-per-type-dnskey rdatasets not signed ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrtype in soa dnskey ns; do
|
||||||
|
$DIG +tcp +dnssec $rrtype "kasp-max-records-per-type-dnskey" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null && ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that kasp-max-types-per-name rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrtype in soa dnskey ns; do
|
||||||
|
$DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
# Update zone with nsupdate.
|
||||||
|
n=$((n + 1))
|
||||||
|
echo_i "add new type to zone and check that it fails ($n)"
|
||||||
|
ret=0
|
||||||
|
(
|
||||||
|
echo zone kasp-max-types-per-name.
|
||||||
|
echo server 10.53.0.4 "$PORT"
|
||||||
|
echo update add kasp-max-types-per-name. 300 TXT KAPUTT
|
||||||
|
echo send
|
||||||
|
) | $NSUPDATE && ret=1
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that kasp-max-types-per-name rdatasets loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrtype in soa dnskey ns txt; do
|
||||||
|
$DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
grep "KAPUTT" "dig.out.ns4.$rrtype.test$n" >/dev/null && ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
# Reconfigure ns4
|
||||||
|
echo_i "reconfigure ns4"
|
||||||
|
stop_server ns4
|
||||||
|
copy_setports ns4/named2.conf.in ns4/named.conf
|
||||||
|
# Recompile zone
|
||||||
|
$CHECKZONE -D -F raw -o ns4/kasp.db.raw kasp-max-types-per-name ns4/template.db >/dev/null 2>&1
|
||||||
|
start_server --noclean --restart --port "${PORT}" ns4
|
||||||
|
|
||||||
|
echo_i "checking that kasp-max-types-per-name rdatasets not loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrtype in soa dnskey ns; do
|
||||||
|
$DIG +tcp +dnssec $rrtype "kasp-max-types-per-name" @10.53.0.4 -p "${PORT}" >"dig.out.ns4.$rrtype.test$n"
|
||||||
|
grep "status: SERVFAIL" "dig.out.ns4.$rrtype.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that 255 types are loaded ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
$DIG +tcp TXT "m.255types" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.test$n" >/dev/null || ret=1
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that 255 types types are not transfered ($n)"
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
$DIG +tcp TXT "m.255types" @10.53.0.2 -p "${PORT}" >"dig.out.ns2.test$n"
|
||||||
|
grep "status: SERVFAIL" "dig.out.ns2.test$n" >/dev/null || ret=1
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "checking format transitions: text->raw->text ($n)"
|
echo_i "checking format transitions: text->raw->text ($n)"
|
||||||
ret=0
|
ret=0
|
||||||
$CHECKZONE -D -f text -F text -o baseline.txt example.nil ns1/example.db >/dev/null
|
$CHECKZONE -D -f text -F text -o baseline.txt example.nil ns1/example.db >/dev/null
|
||||||
@ -240,7 +487,7 @@ stop_server --use-rndc --port ${CONTROLPORT} ns3
|
|||||||
rm ns3/*.jnl
|
rm ns3/*.jnl
|
||||||
restart
|
restart
|
||||||
#shellcheck disable=SC2034
|
#shellcheck disable=SC2034
|
||||||
for i in 0 1 2 3 4 5 6 7 8 9; do
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
lret=0
|
lret=0
|
||||||
dig_with_opts +comm @10.53.0.3 moretext.dynamic txt >"dig.out.dynamic2.ns3.test$n"
|
dig_with_opts +comm @10.53.0.3 moretext.dynamic txt >"dig.out.dynamic2.ns3.test$n"
|
||||||
grep "more text" "dig.out.dynamic2.ns3.test$n" >/dev/null 2>&1 || lret=1
|
grep "more text" "dig.out.dynamic2.ns3.test$n" >/dev/null 2>&1 || lret=1
|
||||||
@ -273,5 +520,24 @@ n=$((n + 1))
|
|||||||
[ $ret -eq 0 ] || echo_i "failed"
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
|
echo_i "checking that on-limit-kasp rdatasets loaded after re-sign and re-start ($n)"
|
||||||
|
ret=0
|
||||||
|
stop_server ns1
|
||||||
|
start_server --noclean --restart --port "${PORT}" ns1
|
||||||
|
|
||||||
|
for _attempt in 0 1 2 3 4 5 6 7 8 9; do
|
||||||
|
ret=0
|
||||||
|
for rrcount in 500-txt 1000-txt 2000-txt 2050-txt; do
|
||||||
|
$DIG +tcp +dnssec txt "${rrcount}.on-limit-kasp" @10.53.0.1 -p "${PORT}" >"dig.out.ns1.$rrcount.test$n"
|
||||||
|
grep "status: NOERROR" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
grep "RRSIG" "dig.out.ns1.$rrcount.test$n" >/dev/null || ret=1
|
||||||
|
done
|
||||||
|
[ $ret -eq 0 ] && break
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
n=$((n + 1))
|
||||||
|
[ $ret -eq 0 ] || echo_i "failed"
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "exit status: $status"
|
echo_i "exit status: $status"
|
||||||
[ $status -eq 0 ] || exit 1
|
[ $status -eq 0 ] || exit 1
|
||||||
|
2771
bin/tests/system/reclimit/ns1/big.db
Normal file
2771
bin/tests/system/reclimit/ns1/big.db
Normal file
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,13 @@ options {
|
|||||||
listen-on-v6 { none; };
|
listen-on-v6 { none; };
|
||||||
recursion no;
|
recursion no;
|
||||||
dnssec-validation no;
|
dnssec-validation no;
|
||||||
|
max-records-per-type 0;
|
||||||
|
max-types-per-name 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
zone "." { type primary; file "root.db"; };
|
zone "." { type primary; file "root.db"; };
|
||||||
|
|
||||||
|
zone "big." {
|
||||||
|
type primary;
|
||||||
|
file "big.db";
|
||||||
|
};
|
||||||
|
@ -19,3 +19,6 @@ example.net. 60 IN NS direct.example.net.
|
|||||||
direct.example.net. 60 IN A 10.53.0.2
|
direct.example.net. 60 IN A 10.53.0.2
|
||||||
example.com. 60 IN NS direct.example.com.
|
example.com. 60 IN NS direct.example.com.
|
||||||
direct.example.com. 60 IN A 10.53.0.4
|
direct.example.com. 60 IN A 10.53.0.4
|
||||||
|
|
||||||
|
big. in NS ns.big.
|
||||||
|
ns.big. 60 IN A 10.53.0.1
|
||||||
|
43
bin/tests/system/reclimit/ns3/named5.conf.in
Normal file
43
bin/tests/system/reclimit/ns3/named5.conf.in
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* See the COPYRIGHT file distributed with this work for additional
|
||||||
|
* information regarding copyright ownership.
|
||||||
|
*/
|
||||||
|
|
||||||
|
options {
|
||||||
|
directory ".";
|
||||||
|
query-source address 10.53.0.3;
|
||||||
|
notify-source 10.53.0.3;
|
||||||
|
transfer-source 10.53.0.3;
|
||||||
|
port @PORT@;
|
||||||
|
pid-file "named.pid";
|
||||||
|
listen-on { 10.53.0.3; };
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
servfail-ttl 0;
|
||||||
|
qname-minimization disabled;
|
||||||
|
max-recursion-depth 12;
|
||||||
|
recursion yes;
|
||||||
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
|
max-types-per-name 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
trust-anchors { };
|
||||||
|
|
||||||
|
key rndc_key {
|
||||||
|
secret "1234abcd8765";
|
||||||
|
algorithm @DEFAULT_HMAC@;
|
||||||
|
};
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "." { type hint; file "hints.db"; };
|
43
bin/tests/system/reclimit/ns3/named6.conf.in
Normal file
43
bin/tests/system/reclimit/ns3/named6.conf.in
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* See the COPYRIGHT file distributed with this work for additional
|
||||||
|
* information regarding copyright ownership.
|
||||||
|
*/
|
||||||
|
|
||||||
|
options {
|
||||||
|
directory ".";
|
||||||
|
query-source address 10.53.0.3;
|
||||||
|
notify-source 10.53.0.3;
|
||||||
|
transfer-source 10.53.0.3;
|
||||||
|
port @PORT@;
|
||||||
|
pid-file "named.pid";
|
||||||
|
listen-on { 10.53.0.3; };
|
||||||
|
listen-on-v6 { none; };
|
||||||
|
servfail-ttl 0;
|
||||||
|
qname-minimization disabled;
|
||||||
|
max-recursion-depth 12;
|
||||||
|
recursion yes;
|
||||||
|
dnssec-validation yes;
|
||||||
|
max-records-per-type 0;
|
||||||
|
max-types-per-name 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
trust-anchors { };
|
||||||
|
|
||||||
|
key rndc_key {
|
||||||
|
secret "1234abcd8765";
|
||||||
|
algorithm @DEFAULT_HMAC@;
|
||||||
|
};
|
||||||
|
|
||||||
|
controls {
|
||||||
|
inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||||
|
};
|
||||||
|
|
||||||
|
zone "." { type hint; file "hints.db"; };
|
@ -222,6 +222,50 @@ eval count=$(cat dig.out.3.test$n)
|
|||||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||||
status=$((status + ret))
|
status=$((status + ret))
|
||||||
|
|
||||||
#grep "duplicate query" ns3/named.run
|
n=$((n + 1))
|
||||||
|
echo_i "checking RRset that exceeds max-records-per-type ($n)"
|
||||||
|
ret=0
|
||||||
|
$DIG $DIGOPTS @10.53.0.3 biganswer.big >dig.out.1.test$n || ret=1
|
||||||
|
grep 'status: SERVFAIL' dig.out.1.test$n >/dev/null || ret=1
|
||||||
|
ns3_reset ns3/named5.conf.in
|
||||||
|
$DIG $DIGOPTS @10.53.0.3 biganswer.big >dig.out.2.test$n || ret=1
|
||||||
|
grep 'status: NOERROR' dig.out.2.test$n >/dev/null || ret=1
|
||||||
|
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
|
check_manytypes() (
|
||||||
|
i=$1
|
||||||
|
type=$2
|
||||||
|
expected=$3
|
||||||
|
|
||||||
|
$DIG $DIGOPTS @10.53.0.3 IN $type manytypes.big >dig.out.$i.$type.test$n || exit 1
|
||||||
|
grep 'status: '"${expected}"'' dig.out.$i.$type.test$n >/dev/null || exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
)
|
||||||
|
|
||||||
|
n=$((n + 1))
|
||||||
|
echo_i "checking name that exceeds max-types-per-name ($n)"
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
# Limited to 10 types - these should be fine
|
||||||
|
for ntype in $(seq 65280 65289); do
|
||||||
|
check_manytypes 1 "TYPE${ntype}" NOERROR || ret=1
|
||||||
|
done
|
||||||
|
# Everything on top of that should SERVFAIL
|
||||||
|
for ntype in $(seq 65290 65534); do
|
||||||
|
check_manytypes 1 "TYPE${ntype}" SERVFAIL || ret=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Lift the limit
|
||||||
|
ns3_reset ns3/named6.conf.in
|
||||||
|
|
||||||
|
for ntype in $(seq 65280 65534); do
|
||||||
|
check_manytypes 2 "TYPE${ntype}" NOERROR || ret=1
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||||
|
status=$((status + ret))
|
||||||
|
|
||||||
echo_i "exit status: $status"
|
echo_i "exit status: $status"
|
||||||
[ $status -eq 0 ] || exit 1
|
[ $status -eq 0 ] || exit 1
|
||||||
|
@ -3681,6 +3681,36 @@ system.
|
|||||||
This sets the maximum number of records permitted in a zone. The default is
|
This sets the maximum number of records permitted in a zone. The default is
|
||||||
zero, which means the maximum is unlimited.
|
zero, which means the maximum is unlimited.
|
||||||
|
|
||||||
|
.. namedconf:statement:: max-records-per-type
|
||||||
|
:tags: server
|
||||||
|
:short: Sets the maximum number of records that can be stored in an RRset
|
||||||
|
|
||||||
|
This sets the maximum number of resource records that can be stored
|
||||||
|
in an RRset in a database. When configured in :namedconf:ref:`options`
|
||||||
|
or :namedconf:ref:`view`, it controls the cache database; it also sets
|
||||||
|
the default value for zone databases, which can be overridden by setting
|
||||||
|
it at the :namedconf:ref:`zone` level.
|
||||||
|
|
||||||
|
If set to a positive value, any attempt to cache or to add to a zone
|
||||||
|
an RRset with more than the specified number of records will result in
|
||||||
|
a failure. If set to 0, there is no cap on RRset size. The default is
|
||||||
|
100.
|
||||||
|
|
||||||
|
.. namedconf:statement:: max-types-per-name
|
||||||
|
:tags: server
|
||||||
|
:short: Sets the maximum number of RR types that can be stored for an owner name
|
||||||
|
|
||||||
|
This sets the maximum number of resource record types that can be stored
|
||||||
|
for a single owner name in a database. When configured in :namedconf:ref:`options`
|
||||||
|
or :namedconf:ref:`view`, it controls the cache database, and also sets
|
||||||
|
the default value for zone databases, which can be overridden by setting
|
||||||
|
it at the :namedconf:ref:`zone` level
|
||||||
|
|
||||||
|
If set to a positive value, any attempt to cache or to add to a zone an owner
|
||||||
|
name with more than the specified number of resource record types will result
|
||||||
|
in a failure. If set to 0, there is no cap on RR types number. The default is
|
||||||
|
100.
|
||||||
|
|
||||||
.. namedconf:statement:: recursive-clients
|
.. namedconf:statement:: recursive-clients
|
||||||
:tags: query
|
:tags: query
|
||||||
:short: Specifies the maximum number of concurrent recursive queries the server can perform.
|
:short: Specifies the maximum number of concurrent recursive queries the server can perform.
|
||||||
|
@ -16,12 +16,14 @@ zone <string> [ <class> ] {
|
|||||||
max-ixfr-ratio ( unlimited | <percentage> );
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||||||
max-journal-size ( default | unlimited | <sizeval> );
|
max-journal-size ( default | unlimited | <sizeval> );
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-refresh-time <integer>;
|
max-refresh-time <integer>;
|
||||||
max-retry-time <integer>;
|
max-retry-time <integer>;
|
||||||
max-transfer-idle-in <integer>;
|
max-transfer-idle-in <integer>;
|
||||||
max-transfer-idle-out <integer>;
|
max-transfer-idle-out <integer>;
|
||||||
max-transfer-time-in <integer>;
|
max-transfer-time-in <integer>;
|
||||||
max-transfer-time-out <integer>;
|
max-transfer-time-out <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
min-refresh-time <integer>;
|
min-refresh-time <integer>;
|
||||||
min-retry-time <integer>;
|
min-retry-time <integer>;
|
||||||
multi-master <boolean>;
|
multi-master <boolean>;
|
||||||
|
@ -183,6 +183,7 @@ options {
|
|||||||
max-journal-size ( default | unlimited | <sizeval> );
|
max-journal-size ( default | unlimited | <sizeval> );
|
||||||
max-ncache-ttl <duration>;
|
max-ncache-ttl <duration>;
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-recursion-depth <integer>;
|
max-recursion-depth <integer>;
|
||||||
max-recursion-queries <integer>;
|
max-recursion-queries <integer>;
|
||||||
max-refresh-time <integer>;
|
max-refresh-time <integer>;
|
||||||
@ -193,6 +194,7 @@ options {
|
|||||||
max-transfer-idle-out <integer>;
|
max-transfer-idle-out <integer>;
|
||||||
max-transfer-time-in <integer>;
|
max-transfer-time-in <integer>;
|
||||||
max-transfer-time-out <integer>;
|
max-transfer-time-out <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
max-udp-size <integer>;
|
max-udp-size <integer>;
|
||||||
max-validation-failures-per-fetch <integer>; // experimental
|
max-validation-failures-per-fetch <integer>; // experimental
|
||||||
max-validations-per-fetch <integer>; // experimental
|
max-validations-per-fetch <integer>; // experimental
|
||||||
@ -468,6 +470,7 @@ view <string> [ <class> ] {
|
|||||||
max-journal-size ( default | unlimited | <sizeval> );
|
max-journal-size ( default | unlimited | <sizeval> );
|
||||||
max-ncache-ttl <duration>;
|
max-ncache-ttl <duration>;
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-recursion-depth <integer>;
|
max-recursion-depth <integer>;
|
||||||
max-recursion-queries <integer>;
|
max-recursion-queries <integer>;
|
||||||
max-refresh-time <integer>;
|
max-refresh-time <integer>;
|
||||||
@ -477,6 +480,7 @@ view <string> [ <class> ] {
|
|||||||
max-transfer-idle-out <integer>;
|
max-transfer-idle-out <integer>;
|
||||||
max-transfer-time-in <integer>;
|
max-transfer-time-in <integer>;
|
||||||
max-transfer-time-out <integer>;
|
max-transfer-time-out <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
max-udp-size <integer>;
|
max-udp-size <integer>;
|
||||||
max-validation-failures-per-fetch <integer>; // experimental
|
max-validation-failures-per-fetch <integer>; // experimental
|
||||||
max-validations-per-fetch <integer>; // experimental
|
max-validations-per-fetch <integer>; // experimental
|
||||||
|
@ -37,8 +37,10 @@ zone <string> [ <class> ] {
|
|||||||
max-ixfr-ratio ( unlimited | <percentage> );
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||||||
max-journal-size ( default | unlimited | <sizeval> );
|
max-journal-size ( default | unlimited | <sizeval> );
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-transfer-idle-out <integer>;
|
max-transfer-idle-out <integer>;
|
||||||
max-transfer-time-out <integer>;
|
max-transfer-time-out <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
||||||
notify ( explicit | master-only | primary-only | <boolean> );
|
notify ( explicit | master-only | primary-only | <boolean> );
|
||||||
notify-delay <integer>;
|
notify-delay <integer>;
|
||||||
|
@ -7,6 +7,8 @@ zone <string> [ <class> ] {
|
|||||||
masterfile-format ( raw | text );
|
masterfile-format ( raw | text );
|
||||||
masterfile-style ( full | relative );
|
masterfile-style ( full | relative );
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
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> ]; ... };
|
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> );
|
zone-statistics ( full | terse | none | <boolean> );
|
||||||
|
@ -28,12 +28,14 @@ zone <string> [ <class> ] {
|
|||||||
max-ixfr-ratio ( unlimited | <percentage> );
|
max-ixfr-ratio ( unlimited | <percentage> );
|
||||||
max-journal-size ( default | unlimited | <sizeval> );
|
max-journal-size ( default | unlimited | <sizeval> );
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-refresh-time <integer>;
|
max-refresh-time <integer>;
|
||||||
max-retry-time <integer>;
|
max-retry-time <integer>;
|
||||||
max-transfer-idle-in <integer>;
|
max-transfer-idle-in <integer>;
|
||||||
max-transfer-idle-out <integer>;
|
max-transfer-idle-out <integer>;
|
||||||
max-transfer-time-in <integer>;
|
max-transfer-time-in <integer>;
|
||||||
max-transfer-time-out <integer>;
|
max-transfer-time-out <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
min-refresh-time <integer>;
|
min-refresh-time <integer>;
|
||||||
min-retry-time <integer>;
|
min-retry-time <integer>;
|
||||||
multi-master <boolean>;
|
multi-master <boolean>;
|
||||||
|
@ -5,6 +5,8 @@ zone <string> [ <class> ] {
|
|||||||
forward ( first | only );
|
forward ( first | only );
|
||||||
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
|
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
|
||||||
server-names { <string>; ... };
|
server-names { <string>; ... };
|
||||||
zone-statistics ( full | terse | none | <boolean> );
|
zone-statistics ( full | terse | none | <boolean> );
|
||||||
|
@ -11,10 +11,12 @@ zone <string> [ <class> ] {
|
|||||||
masterfile-format ( raw | text );
|
masterfile-format ( raw | text );
|
||||||
masterfile-style ( full | relative );
|
masterfile-style ( full | relative );
|
||||||
max-records <integer>;
|
max-records <integer>;
|
||||||
|
max-records-per-type <integer>;
|
||||||
max-refresh-time <integer>;
|
max-refresh-time <integer>;
|
||||||
max-retry-time <integer>;
|
max-retry-time <integer>;
|
||||||
max-transfer-idle-in <integer>;
|
max-transfer-idle-in <integer>;
|
||||||
max-transfer-time-in <integer>;
|
max-transfer-time-in <integer>;
|
||||||
|
max-types-per-name <integer>;
|
||||||
min-refresh-time <integer>;
|
min-refresh-time <integer>;
|
||||||
min-retry-time <integer>;
|
min-retry-time <integer>;
|
||||||
multi-master <boolean>;
|
multi-master <boolean>;
|
||||||
|
@ -19,6 +19,21 @@ Security Fixes
|
|||||||
responses can cause server to respond slowly or not respond at all for other
|
responses can cause server to respond slowly or not respond at all for other
|
||||||
clients. :cve:`2024-0760` :gl:`#4481`
|
clients. :cve:`2024-0760` :gl:`#4481`
|
||||||
|
|
||||||
|
- Excessively large resource record sets can be crafted to slow down
|
||||||
|
database processing. This has been addressed by adding a configurable
|
||||||
|
limit to the number of records that can be stored per name and type in
|
||||||
|
a cache or zone database. The default is 100, but it can be tuned with
|
||||||
|
the new ``max-records-per-type`` option. :gl:`#497` :gl:`#3405`
|
||||||
|
|
||||||
|
An excessively large number of resource record types for a single owner name can
|
||||||
|
be crafted to slow down database processing. This has been addressed by adding
|
||||||
|
a configurable limit to the number of records that can be stored per name and
|
||||||
|
type in a cache or zone database. The default is 100, and can be tuned with
|
||||||
|
the new ``max-rrtypes-per-name`` option. :cve:`2024-1737` :gl:`#3403`
|
||||||
|
|
||||||
|
ISC would like to thank Toshifumi Sakaguchi who independently discovered
|
||||||
|
and responsibly reported the issue to ISC. :gl:`#4548`
|
||||||
|
|
||||||
New Features
|
New Features
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -80,6 +80,8 @@ struct dns_cache {
|
|||||||
dns_ttl_t serve_stale_ttl;
|
dns_ttl_t serve_stale_ttl;
|
||||||
dns_ttl_t serve_stale_refresh;
|
dns_ttl_t serve_stale_refresh;
|
||||||
isc_stats_t *stats;
|
isc_stats_t *stats;
|
||||||
|
uint32_t maxrrperset;
|
||||||
|
uint32_t maxtypepername;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -128,6 +130,8 @@ 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_setservestalettl(db, cache->serve_stale_ttl);
|
||||||
dns_db_setservestalerefresh(db, cache->serve_stale_refresh);
|
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
|
* XXX this is only used by the RBT cache, and can
|
||||||
@ -546,6 +550,26 @@ dns_cache_updatestats(dns_cache_t *cache, isc_result_t result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_cache_setmaxrrperset(dns_cache_t *cache, uint32_t value) {
|
||||||
|
REQUIRE(VALID_CACHE(cache));
|
||||||
|
|
||||||
|
cache->maxrrperset = value;
|
||||||
|
if (cache->db != NULL) {
|
||||||
|
dns_db_setmaxrrperset(cache->db, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_cache_setmaxtypepername(dns_cache_t *cache, uint32_t value) {
|
||||||
|
REQUIRE(VALID_CACHE(cache));
|
||||||
|
|
||||||
|
cache->maxtypepername = value;
|
||||||
|
if (cache->db != NULL) {
|
||||||
|
dns_db_setmaxtypepername(cache->db, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: Much of the following code has been copied in from statschannel.c.
|
* 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
|
* We should refactor this into a generic function in stats.c that can be
|
||||||
|
18
lib/dns/db.c
18
lib/dns/db.c
@ -1170,3 +1170,21 @@ dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
|
|||||||
}
|
}
|
||||||
return (ISC_R_NOTIMPLEMENTED);
|
return (ISC_R_NOTIMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_db_setmaxrrperset(dns_db_t *db, uint32_t value) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
|
||||||
|
if (db->methods->setmaxrrperset != NULL) {
|
||||||
|
(db->methods->setmaxrrperset)(db, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_db_setmaxtypepername(dns_db_t *db, uint32_t value) {
|
||||||
|
REQUIRE(DNS_DB_VALID(db));
|
||||||
|
|
||||||
|
if (db->methods->setmaxtypepername != NULL) {
|
||||||
|
(db->methods->setmaxtypepername)(db, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -246,6 +246,18 @@ dns_cache_updatestats(dns_cache_t *cache, isc_result_t result);
|
|||||||
* Update cache statistics based on result code in 'result'
|
* Update cache statistics based on result code in 'result'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_cache_setmaxrrperset(dns_cache_t *cache, uint32_t value);
|
||||||
|
/*%<
|
||||||
|
* Set the maximum resource records per RRSet that can be cached.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_cache_setmaxtypepername(dns_cache_t *cache, uint32_t value);
|
||||||
|
/*%<
|
||||||
|
* Set the maximum resource record types per owner name that can be cached.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_LIBXML2
|
#ifdef HAVE_LIBXML2
|
||||||
int
|
int
|
||||||
dns_cache_renderxml(dns_cache_t *cache, void *writer0);
|
dns_cache_renderxml(dns_cache_t *cache, void *writer0);
|
||||||
|
@ -183,6 +183,8 @@ typedef struct dns_dbmethods {
|
|||||||
void (*deletedata)(dns_db_t *db, dns_dbnode_t *node, void *data);
|
void (*deletedata)(dns_db_t *db, dns_dbnode_t *node, void *data);
|
||||||
isc_result_t (*nodefullname)(dns_db_t *db, dns_dbnode_t *node,
|
isc_result_t (*nodefullname)(dns_db_t *db, dns_dbnode_t *node,
|
||||||
dns_name_t *name);
|
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;
|
} dns_dbmethods_t;
|
||||||
|
|
||||||
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
|
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t *mctx,
|
||||||
@ -1800,4 +1802,23 @@ dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name);
|
|||||||
* \li 'db' is a valid database
|
* \li 'db' is a valid database
|
||||||
* \li 'node' and 'name' are not NULL
|
* \li 'node' and 'name' are not 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_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
|
ISC_LANG_ENDDECLS
|
||||||
|
@ -169,7 +169,8 @@ extern dns_rdatasetmethods_t dns_rdataslab_rdatasetmethods;
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
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
|
* Slabify a rdataset. The slab area will be allocated and returned
|
||||||
* in 'region'.
|
* in 'region'.
|
||||||
@ -225,7 +226,8 @@ isc_result_t
|
|||||||
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||||||
unsigned int reservelen, isc_mem_t *mctx,
|
unsigned int reservelen, isc_mem_t *mctx,
|
||||||
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
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'.
|
* Merge 'oslab' and 'nslab'.
|
||||||
*/
|
*/
|
||||||
|
@ -183,6 +183,8 @@ struct dns_view {
|
|||||||
uint32_t fail_ttl;
|
uint32_t fail_ttl;
|
||||||
dns_badcache_t *failcache;
|
dns_badcache_t *failcache;
|
||||||
unsigned int udpsize;
|
unsigned int udpsize;
|
||||||
|
uint32_t maxrrperset;
|
||||||
|
uint32_t maxtypepername;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Configurable data for server use only,
|
* Configurable data for server use only,
|
||||||
@ -1242,6 +1244,18 @@ dns_view_getresolver(dns_view_t *view, dns_resolver_t **resolverp);
|
|||||||
* Return the resolver associated with the view.
|
* Return the resolver associated with the view.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_view_setmaxrrperset(dns_view_t *view, uint32_t value);
|
||||||
|
/*%<
|
||||||
|
* Set the maximum resource records per RRSet that can be cached.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_view_setmaxtypepername(dns_view_t *view, uint32_t value);
|
||||||
|
/*%<
|
||||||
|
* Set the maximum resource record types per owner name that can be cached.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize);
|
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize);
|
||||||
/*%<
|
/*%<
|
||||||
|
@ -366,6 +366,32 @@ dns_zone_getmaxrecords(dns_zone_t *zone);
|
|||||||
*\li uint32_t maxrecords.
|
*\li uint32_t maxrecords.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t maxrrperset);
|
||||||
|
/*%<
|
||||||
|
* Sets the maximum number of records per rrset permitted in a zone.
|
||||||
|
* 0 implies unlimited.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*\li 'zone' to be valid initialised zone.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*\li void
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t maxtypepername);
|
||||||
|
/*%<
|
||||||
|
* Sets the maximum number of resource record types per owner name
|
||||||
|
* permitted in a zone. 0 implies unlimited.
|
||||||
|
*
|
||||||
|
* Requires:
|
||||||
|
*\li 'zone' to be valid initialised zone.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
*\li void
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
dns_zone_setmaxttl(dns_zone_t *zone, uint32_t maxttl);
|
dns_zone_setmaxttl(dns_zone_t *zone, uint32_t maxttl);
|
||||||
/*%<
|
/*%<
|
||||||
|
@ -217,6 +217,9 @@ struct qpcache {
|
|||||||
/* Locked by lock. */
|
/* Locked by lock. */
|
||||||
unsigned int active;
|
unsigned int active;
|
||||||
|
|
||||||
|
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
|
* The time after a failed lookup, where stale answers from cache
|
||||||
* may be used directly in a DNS response without attempting a
|
* may be used directly in a DNS response without attempting a
|
||||||
@ -2883,6 +2886,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||||||
dns_typepair_t negtype = 0, sigtype;
|
dns_typepair_t negtype = 0, sigtype;
|
||||||
dns_trust_t trust;
|
dns_trust_t trust;
|
||||||
int idx;
|
int idx;
|
||||||
|
uint32_t ntypes;
|
||||||
|
|
||||||
if ((options & DNS_DBADD_FORCE) != 0) {
|
if ((options & DNS_DBADD_FORCE) != 0) {
|
||||||
trust = dns_trust_ultimate;
|
trust = dns_trust_ultimate;
|
||||||
@ -2915,6 +2919,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||||||
{
|
{
|
||||||
mark_ancient(topheader);
|
mark_ancient(topheader);
|
||||||
}
|
}
|
||||||
|
ntypes = 0; /* Always add the negative entry */
|
||||||
goto find_header;
|
goto find_header;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -2938,9 +2943,11 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||||||
* check for an extant non-ancient NODATA ncache
|
* check for an extant non-ancient NODATA ncache
|
||||||
* entry which covers the same type as the RRSIG.
|
* entry which covers the same type as the RRSIG.
|
||||||
*/
|
*/
|
||||||
|
ntypes = 0;
|
||||||
for (topheader = qpnode->data; topheader != NULL;
|
for (topheader = qpnode->data; topheader != NULL;
|
||||||
topheader = topheader->next)
|
topheader = topheader->next)
|
||||||
{
|
{
|
||||||
|
++ntypes;
|
||||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||||
(newheader->type == sigtype &&
|
(newheader->type == sigtype &&
|
||||||
topheader->type ==
|
topheader->type ==
|
||||||
@ -2983,9 +2990,12 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ntypes = 0;
|
||||||
for (topheader = qpnode->data; topheader != NULL;
|
for (topheader = qpnode->data; topheader != NULL;
|
||||||
topheader = topheader->next)
|
topheader = topheader->next)
|
||||||
{
|
{
|
||||||
|
++ntypes;
|
||||||
|
|
||||||
if (prio_type(topheader->type)) {
|
if (prio_type(topheader->type)) {
|
||||||
prioheader = topheader;
|
prioheader = topheader;
|
||||||
}
|
}
|
||||||
@ -3253,6 +3263,14 @@ find_header:
|
|||||||
/*
|
/*
|
||||||
* No rdatasets of the given type exist at the node.
|
* 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);
|
INSIST(newheader->down == NULL);
|
||||||
|
|
||||||
if (prio_type(newheader->type)) {
|
if (prio_type(newheader->type)) {
|
||||||
@ -3280,7 +3298,7 @@ find_header:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset,
|
||||||
dns_rdataset_t *rdataset) {
|
dns_rdataset_t *rdataset) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_slabheader_proof_t *noqname = NULL;
|
dns_slabheader_proof_t *noqname = NULL;
|
||||||
@ -3291,12 +3309,12 @@ addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
|||||||
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
|
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
|
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
|
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -3319,7 +3337,7 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset,
|
||||||
dns_rdataset_t *rdataset) {
|
dns_rdataset_t *rdataset) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_slabheader_proof_t *closest = NULL;
|
dns_slabheader_proof_t *closest = NULL;
|
||||||
@ -3330,12 +3348,12 @@ addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
|||||||
result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
|
result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
|
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
|
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -3386,7 +3404,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
qpdb->maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -3423,14 +3442,16 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||||||
DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_OPTOUT);
|
DNS_SLABHEADER_SETATTR(newheader, DNS_SLABHEADERATTR_OPTOUT);
|
||||||
}
|
}
|
||||||
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
|
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
|
||||||
result = addnoqname(qpdb->common.mctx, newheader, rdataset);
|
result = addnoqname(qpdb->common.mctx, newheader,
|
||||||
|
qpdb->maxrrperset, rdataset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
dns_slabheader_destroy(&newheader);
|
dns_slabheader_destroy(&newheader);
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
|
if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
|
||||||
result = addclosest(qpdb->common.mctx, newheader, rdataset);
|
result = addclosest(qpdb->common.mctx, newheader,
|
||||||
|
qpdb->maxrrperset, rdataset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
dns_slabheader_destroy(&newheader);
|
dns_slabheader_destroy(&newheader);
|
||||||
return (result);
|
return (result);
|
||||||
@ -4330,6 +4351,24 @@ expire_ttl_headers(qpcache_t *qpdb, unsigned int locknum,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setmaxrrperset(dns_db_t *db, uint32_t value) {
|
||||||
|
qpcache_t *qpdb = (qpcache_t *)db;
|
||||||
|
|
||||||
|
REQUIRE(VALID_QPDB(qpdb));
|
||||||
|
|
||||||
|
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 = {
|
static dns_dbmethods_t qpdb_cachemethods = {
|
||||||
.destroy = qpdb_destroy,
|
.destroy = qpdb_destroy,
|
||||||
.findnode = findnode,
|
.findnode = findnode,
|
||||||
@ -4354,6 +4393,8 @@ static dns_dbmethods_t qpdb_cachemethods = {
|
|||||||
.unlocknode = unlocknode,
|
.unlocknode = unlocknode,
|
||||||
.expiredata = expiredata,
|
.expiredata = expiredata,
|
||||||
.deletedata = deletedata,
|
.deletedata = deletedata,
|
||||||
|
.setmaxrrperset = setmaxrrperset,
|
||||||
|
.setmaxtypepername = setmaxtypepername,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -178,6 +178,8 @@ struct qpzonedb {
|
|||||||
uint32_t current_serial;
|
uint32_t current_serial;
|
||||||
uint32_t least_serial;
|
uint32_t least_serial;
|
||||||
uint32_t next_serial;
|
uint32_t next_serial;
|
||||||
|
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 *current_version;
|
||||||
qpz_version_t *future_version;
|
qpz_version_t *future_version;
|
||||||
qpz_versionlist_t open_versions;
|
qpz_versionlist_t open_versions;
|
||||||
@ -1833,6 +1835,7 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||||||
unsigned char *merged = NULL;
|
unsigned char *merged = NULL;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
bool merge = false;
|
bool merge = false;
|
||||||
|
uint32_t ntypes;
|
||||||
|
|
||||||
if ((options & DNS_DBADD_MERGE) != 0) {
|
if ((options & DNS_DBADD_MERGE) != 0) {
|
||||||
REQUIRE(version != NULL);
|
REQUIRE(version != NULL);
|
||||||
@ -1848,9 +1851,11 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||||||
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
|
changed = add_changed(newheader, version DNS__DB_FLARG_PASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ntypes = 0;
|
||||||
for (topheader = node->data; topheader != NULL;
|
for (topheader = node->data; topheader != NULL;
|
||||||
topheader = topheader->next)
|
topheader = topheader->next)
|
||||||
{
|
{
|
||||||
|
++ntypes;
|
||||||
if (prio_type(topheader->type)) {
|
if (prio_type(topheader->type)) {
|
||||||
prioheader = topheader;
|
prioheader = topheader;
|
||||||
}
|
}
|
||||||
@ -1898,7 +1903,7 @@ add(qpzonedb_t *qpdb, qpznode_t *node, const dns_name_t *nodename,
|
|||||||
(unsigned int)(sizeof(*newheader)),
|
(unsigned int)(sizeof(*newheader)),
|
||||||
qpdb->common.mctx, qpdb->common.rdclass,
|
qpdb->common.mctx, qpdb->common.rdclass,
|
||||||
(dns_rdatatype_t)header->type, flags,
|
(dns_rdatatype_t)header->type, flags,
|
||||||
&merged);
|
qpdb->maxrrperset, &merged);
|
||||||
}
|
}
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
/*
|
/*
|
||||||
@ -2017,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.
|
* 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);
|
INSIST(newheader->down == NULL);
|
||||||
|
|
||||||
if (prio_type(newheader->type)) {
|
if (prio_type(newheader->type)) {
|
||||||
@ -2147,7 +2160,8 @@ loading_addrdataset(void *arg, const dns_name_t *name,
|
|||||||
|
|
||||||
loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node);
|
loading_addnode(loadctx, name, rdataset->type, rdataset->covers, &node);
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
qpdb->maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -4648,7 +4662,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
|
|||||||
rdataset->covers != dns_rdatatype_nsec3)));
|
rdataset->covers != dns_rdatatype_nsec3)));
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
qpdb->maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -4767,7 +4782,8 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *dbnode, dns_dbversion_t *dbversion,
|
|||||||
|
|
||||||
dns_name_copy(&node->name, nodename);
|
dns_name_copy(&node->name, nodename);
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, qpdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
0);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -5277,6 +5293,24 @@ addglue(dns_db_t *db, dns_dbversion_t *dbversion, dns_rdataset_t *rdataset,
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setmaxrrperset(dns_db_t *db, uint32_t value) {
|
||||||
|
qpzonedb_t *qpdb = (qpzonedb_t *)db;
|
||||||
|
|
||||||
|
REQUIRE(VALID_QPZONE(qpdb));
|
||||||
|
|
||||||
|
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 = {
|
static dns_dbmethods_t qpdb_zonemethods = {
|
||||||
.destroy = qpdb_destroy,
|
.destroy = qpdb_destroy,
|
||||||
.beginload = beginload,
|
.beginload = beginload,
|
||||||
@ -5310,6 +5344,8 @@ static dns_dbmethods_t qpdb_zonemethods = {
|
|||||||
.addglue = addglue,
|
.addglue = addglue,
|
||||||
.deletedata = deletedata,
|
.deletedata = deletedata,
|
||||||
.nodefullname = nodefullname,
|
.nodefullname = nodefullname,
|
||||||
|
.setmaxrrperset = setmaxrrperset,
|
||||||
|
.setmaxtypepername = setmaxtypepername,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1582,6 +1582,8 @@ dns_dbmethods_t dns__rbtdb_cachemethods = {
|
|||||||
.unlocknode = dns__rbtdb_unlocknode,
|
.unlocknode = dns__rbtdb_unlocknode,
|
||||||
.expiredata = expiredata,
|
.expiredata = expiredata,
|
||||||
.deletedata = dns__rbtdb_deletedata,
|
.deletedata = dns__rbtdb_deletedata,
|
||||||
|
.setmaxrrperset = dns__rbtdb_setmaxrrperset,
|
||||||
|
.setmaxtypepername = dns__rbtdb_setmaxtypepername,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1749,7 +1749,8 @@ loading_addrdataset(void *arg, const dns_name_t *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
rbtdb->maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -2418,6 +2419,8 @@ dns_dbmethods_t dns__rbtdb_zonemethods = {
|
|||||||
.addglue = addglue,
|
.addglue = addglue,
|
||||||
.deletedata = dns__rbtdb_deletedata,
|
.deletedata = dns__rbtdb_deletedata,
|
||||||
.nodefullname = dns__rbtdb_nodefullname,
|
.nodefullname = dns__rbtdb_nodefullname,
|
||||||
|
.setmaxrrperset = dns__rbtdb_setmaxrrperset,
|
||||||
|
.setmaxtypepername = dns__rbtdb_setmaxtypepername,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2566,6 +2566,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||||||
dns_typepair_t negtype = 0, sigtype;
|
dns_typepair_t negtype = 0, sigtype;
|
||||||
dns_trust_t trust;
|
dns_trust_t trust;
|
||||||
int idx;
|
int idx;
|
||||||
|
uint32_t ntypes = 0;
|
||||||
|
|
||||||
if ((options & DNS_DBADD_MERGE) != 0) {
|
if ((options & DNS_DBADD_MERGE) != 0) {
|
||||||
REQUIRE(rbtversion != NULL);
|
REQUIRE(rbtversion != NULL);
|
||||||
@ -2618,6 +2619,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||||||
{
|
{
|
||||||
mark_ancient(topheader);
|
mark_ancient(topheader);
|
||||||
}
|
}
|
||||||
|
ntypes = 0; /* Always add the negative entry */
|
||||||
goto find_header;
|
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
|
* check for an extant non-ancient NODATA ncache
|
||||||
* entry which covers the same type as the RRSIG.
|
* entry which covers the same type as the RRSIG.
|
||||||
*/
|
*/
|
||||||
|
ntypes = 0;
|
||||||
for (topheader = rbtnode->data; topheader != NULL;
|
for (topheader = rbtnode->data; topheader != NULL;
|
||||||
topheader = topheader->next)
|
topheader = topheader->next)
|
||||||
{
|
{
|
||||||
|
++ntypes;
|
||||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||||
(newheader->type == sigtype &&
|
(newheader->type == sigtype &&
|
||||||
topheader->type ==
|
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;
|
for (topheader = rbtnode->data; topheader != NULL;
|
||||||
topheader = topheader->next)
|
topheader = topheader->next)
|
||||||
{
|
{
|
||||||
|
++ntypes;
|
||||||
if (prio_type(topheader->type)) {
|
if (prio_type(topheader->type)) {
|
||||||
prioheader = topheader;
|
prioheader = topheader;
|
||||||
}
|
}
|
||||||
@ -2780,7 +2786,7 @@ find_header:
|
|||||||
rbtdb->common.mctx,
|
rbtdb->common.mctx,
|
||||||
rbtdb->common.rdclass,
|
rbtdb->common.rdclass,
|
||||||
(dns_rdatatype_t)header->type, flags,
|
(dns_rdatatype_t)header->type, flags,
|
||||||
&merged);
|
rbtdb->maxrrperset, &merged);
|
||||||
}
|
}
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
/*
|
/*
|
||||||
@ -3082,6 +3088,14 @@ find_header:
|
|||||||
/*
|
/*
|
||||||
* No rdatasets of the given type exist at the node.
|
* 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);
|
INSIST(newheader->down == NULL);
|
||||||
|
|
||||||
if (prio_type(newheader->type)) {
|
if (prio_type(newheader->type)) {
|
||||||
@ -3141,7 +3155,7 @@ delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, dns_typepair_t type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset,
|
||||||
dns_rdataset_t *rdataset) {
|
dns_rdataset_t *rdataset) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_slabheader_proof_t *noqname = NULL;
|
dns_slabheader_proof_t *noqname = NULL;
|
||||||
@ -3152,12 +3166,12 @@ addnoqname(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
|||||||
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
|
result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
|
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
|
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -3180,7 +3194,7 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader, uint32_t maxrrperset,
|
||||||
dns_rdataset_t *rdataset) {
|
dns_rdataset_t *rdataset) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_slabheader_proof_t *closest = NULL;
|
dns_slabheader_proof_t *closest = NULL;
|
||||||
@ -3191,12 +3205,12 @@ addclosest(isc_mem_t *mctx, dns_slabheader_t *newheader,
|
|||||||
result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
|
result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0);
|
result = dns_rdataslab_fromrdataset(&neg, mctx, &r1, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0);
|
result = dns_rdataslab_fromrdataset(&negsig, mctx, &r2, 0, maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
@ -3272,7 +3286,8 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
rbtdb->maxrrperset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -3329,7 +3344,7 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
|
|||||||
}
|
}
|
||||||
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
|
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
|
||||||
result = addnoqname(rbtdb->common.mctx, newheader,
|
result = addnoqname(rbtdb->common.mctx, newheader,
|
||||||
rdataset);
|
rbtdb->maxrrperset, rdataset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
dns_slabheader_destroy(&newheader);
|
dns_slabheader_destroy(&newheader);
|
||||||
return (result);
|
return (result);
|
||||||
@ -3337,7 +3352,7 @@ dns__rbtdb_addrdataset(dns_db_t *db, dns_dbnode_t *node,
|
|||||||
}
|
}
|
||||||
if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
|
if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
|
||||||
result = addclosest(rbtdb->common.mctx, newheader,
|
result = addclosest(rbtdb->common.mctx, newheader,
|
||||||
rdataset);
|
rbtdb->maxrrperset, rdataset);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
dns_slabheader_destroy(&newheader);
|
dns_slabheader_destroy(&newheader);
|
||||||
return (result);
|
return (result);
|
||||||
@ -3487,7 +3502,8 @@ dns__rbtdb_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
|
|||||||
dns__rbtdb_nodefullname(db, node, nodename);
|
dns__rbtdb_nodefullname(db, node, nodename);
|
||||||
|
|
||||||
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
|
||||||
®ion, sizeof(dns_slabheader_t));
|
®ion, sizeof(dns_slabheader_t),
|
||||||
|
0);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
@ -4957,3 +4973,21 @@ expire_ttl_headers(dns_rbtdb_t *rbtdb, unsigned int locknum,
|
|||||||
dns_expire_ttl DNS__DB_FLARG_PASS);
|
dns_expire_ttl DNS__DB_FLARG_PASS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns__rbtdb_setmaxrrperset(dns_db_t *db, uint32_t value) {
|
||||||
|
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||||
|
|
||||||
|
REQUIRE(VALID_RBTDB(rbtdb));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -114,6 +114,8 @@ struct dns_rbtdb {
|
|||||||
uint32_t current_serial;
|
uint32_t current_serial;
|
||||||
uint32_t least_serial;
|
uint32_t least_serial;
|
||||||
uint32_t next_serial;
|
uint32_t next_serial;
|
||||||
|
uint32_t maxrrperset;
|
||||||
|
uint32_t maxtypepername;
|
||||||
dns_rbtdb_version_t *current_version;
|
dns_rbtdb_version_t *current_version;
|
||||||
dns_rbtdb_version_t *future_version;
|
dns_rbtdb_version_t *future_version;
|
||||||
rbtdb_versionlist_t open_versions;
|
rbtdb_versionlist_t open_versions;
|
||||||
@ -427,6 +429,18 @@ dns__rbtdb_setttl(dns_slabheader_t *header, dns_ttl_t newttl);
|
|||||||
* also update the TTL heap accordingly.
|
* also update the TTL heap accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions specific to zone databases that are also called from rbtdb.c.
|
* Functions specific to zone databases that are also called from rbtdb.c.
|
||||||
*/
|
*/
|
||||||
|
@ -168,7 +168,8 @@ fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
|
|||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
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
|
* Use &removed as a sentinel pointer for duplicate
|
||||||
* rdata as rdata.data == NULL is valid.
|
* rdata as rdata.data == NULL is valid.
|
||||||
@ -208,6 +209,10 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (maxrrperset > 0 && nitems > maxrrperset) {
|
||||||
|
return (DNS_R_TOOMANYRECORDS);
|
||||||
|
}
|
||||||
|
|
||||||
if (nitems > 0xffff) {
|
if (nitems > 0xffff) {
|
||||||
return (ISC_R_NOSPACE);
|
return (ISC_R_NOSPACE);
|
||||||
}
|
}
|
||||||
@ -515,7 +520,8 @@ isc_result_t
|
|||||||
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
||||||
unsigned int reservelen, isc_mem_t *mctx,
|
unsigned int reservelen, isc_mem_t *mctx,
|
||||||
dns_rdataclass_t rdclass, dns_rdatatype_t type,
|
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 = NULL, *ostart = NULL, *ncurrent = NULL;
|
unsigned char *ocurrent = NULL, *ostart = NULL, *ncurrent = NULL;
|
||||||
unsigned char *tstart = NULL, *tcurrent = NULL, *data = NULL;
|
unsigned char *tstart = NULL, *tcurrent = NULL, *data = NULL;
|
||||||
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
|
unsigned int ocount, ncount, count, olength, tlength, tcount, length;
|
||||||
@ -554,6 +560,10 @@ dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
|
|||||||
#endif /* if DNS_RDATASET_FIXED */
|
#endif /* if DNS_RDATASET_FIXED */
|
||||||
INSIST(ocount > 0 && ncount > 0);
|
INSIST(ocount > 0 && ncount > 0);
|
||||||
|
|
||||||
|
if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
|
||||||
|
return (DNS_R_TOOMANYRECORDS);
|
||||||
|
}
|
||||||
|
|
||||||
#if DNS_RDATASET_FIXED
|
#if DNS_RDATASET_FIXED
|
||||||
oncount = ncount;
|
oncount = ncount;
|
||||||
#endif /* if DNS_RDATASET_FIXED */
|
#endif /* if DNS_RDATASET_FIXED */
|
||||||
|
@ -643,6 +643,9 @@ dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
|
|||||||
dns_cache_attach(cache, &view->cache);
|
dns_cache_attach(cache, &view->cache);
|
||||||
dns_cache_attachdb(cache, &view->cachedb);
|
dns_cache_attachdb(cache, &view->cachedb);
|
||||||
INSIST(DNS_DB_VALID(view->cachedb));
|
INSIST(DNS_DB_VALID(view->cachedb));
|
||||||
|
|
||||||
|
dns_cache_setmaxrrperset(view->cache, view->maxrrperset);
|
||||||
|
dns_cache_setmaxtypepername(view->cache, view->maxtypepername);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -2336,6 +2339,24 @@ dns_view_getresolver(dns_view_t *view, dns_resolver_t **resolverp) {
|
|||||||
return (result);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize) {
|
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize) {
|
||||||
REQUIRE(DNS_VIEW_VALID(view));
|
REQUIRE(DNS_VIEW_VALID(view));
|
||||||
|
@ -318,6 +318,8 @@ struct dns_zone {
|
|||||||
uint32_t minretry;
|
uint32_t minretry;
|
||||||
|
|
||||||
uint32_t maxrecords;
|
uint32_t maxrecords;
|
||||||
|
uint32_t maxrrperset;
|
||||||
|
uint32_t maxtypepername;
|
||||||
|
|
||||||
dns_remote_t primaries;
|
dns_remote_t primaries;
|
||||||
|
|
||||||
@ -9741,6 +9743,7 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
dns_diff_clear(&_sig_diff);
|
dns_diff_clear(&_sig_diff);
|
||||||
|
dns_diff_clear(&post_diff);
|
||||||
|
|
||||||
for (i = 0; i < nkeys; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
dst_key_free(&zone_keys[i]);
|
dst_key_free(&zone_keys[i]);
|
||||||
@ -12057,6 +12060,26 @@ dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
|
|||||||
zone->maxrecords = val;
|
zone->maxrecords = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
|
||||||
|
REQUIRE(DNS_ZONE_VALID(zone));
|
||||||
|
|
||||||
|
zone->maxrrperset = val;
|
||||||
|
if (zone->db != NULL) {
|
||||||
|
dns_db_setmaxrrperset(zone->db, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
|
||||||
|
REQUIRE(DNS_ZONE_VALID(zone));
|
||||||
|
|
||||||
|
zone->maxtypepername = val;
|
||||||
|
if (zone->db != NULL) {
|
||||||
|
dns_db_setmaxtypepername(zone->db, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
|
notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
|
||||||
isc_sockaddr_t *addr, dns_tsigkey_t *key,
|
isc_sockaddr_t *addr, dns_tsigkey_t *key,
|
||||||
@ -14458,6 +14481,9 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
dns_db_setloop(stub->db, zone->loop);
|
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);
|
result = dns_db_newversion(stub->db, &stub->version);
|
||||||
@ -17514,6 +17540,8 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
|
|||||||
}
|
}
|
||||||
zone_attachdb(zone, db);
|
zone_attachdb(zone, db);
|
||||||
dns_db_setloop(zone->db, zone->loop);
|
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);
|
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
@ -22470,7 +22498,11 @@ failure:
|
|||||||
* Something went wrong; try again in ten minutes or
|
* Something went wrong; try again in ten minutes or
|
||||||
* after a key refresh interval, whichever is shorter.
|
* after a key refresh interval, whichever is shorter.
|
||||||
*/
|
*/
|
||||||
dnssec_log(zone, ISC_LOG_DEBUG(3),
|
int loglevel = ISC_LOG_DEBUG(3);
|
||||||
|
if (result != DNS_R_NOTLOADED) {
|
||||||
|
loglevel = ISC_LOG_ERROR;
|
||||||
|
}
|
||||||
|
dnssec_log(zone, loglevel,
|
||||||
"zone_rekey failure: %s (retry in %u seconds)",
|
"zone_rekey failure: %s (retry in %u seconds)",
|
||||||
isc_result_totext(result),
|
isc_result_totext(result),
|
||||||
ISC_MIN(zone->refreshkeyinterval, 600));
|
ISC_MIN(zone->refreshkeyinterval, 600));
|
||||||
@ -24153,6 +24185,8 @@ dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dns_db_setloop(db, zone->loop);
|
dns_db_setloop(db, zone->loop);
|
||||||
|
dns_db_setmaxrrperset(db, zone->maxrrperset);
|
||||||
|
dns_db_setmaxtypepername(db, zone->maxtypepername);
|
||||||
|
|
||||||
*dbp = db;
|
*dbp = db;
|
||||||
|
|
||||||
|
@ -2372,6 +2372,12 @@ static cfg_clausedef_t zone_clauses[] = {
|
|||||||
{ "max-records", &cfg_type_uint32,
|
{ "max-records", &cfg_type_uint32,
|
||||||
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||||||
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
||||||
|
{ "max-records-per-type", &cfg_type_uint32,
|
||||||
|
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||||||
|
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
||||||
|
{ "max-types-per-name", &cfg_type_uint32,
|
||||||
|
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||||||
|
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_REDIRECT },
|
||||||
{ "max-refresh-time", &cfg_type_uint32,
|
{ "max-refresh-time", &cfg_type_uint32,
|
||||||
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||||||
{ "max-retry-time", &cfg_type_uint32,
|
{ "max-retry-time", &cfg_type_uint32,
|
||||||
|
@ -3160,9 +3160,18 @@ update_action(void *arg) {
|
|||||||
dns_diff_clear(&ctx.add_diff);
|
dns_diff_clear(&ctx.add_diff);
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
CHECK(update_one_rr(db, ver, &diff,
|
result = update_one_rr(
|
||||||
DNS_DIFFOP_ADD,
|
db, ver, &diff, DNS_DIFFOP_ADD,
|
||||||
name, ttl, &rdata));
|
name, ttl, &rdata);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
update_log(client, zone,
|
||||||
|
LOGLEVEL_PROTOCOL,
|
||||||
|
"adding an RR "
|
||||||
|
"failed: %s",
|
||||||
|
isc_result_totext(
|
||||||
|
result));
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (update_class == dns_rdataclass_any) {
|
} else if (update_class == dns_rdataclass_any) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user