mirror of
https://github.com/isc-projects/bind9.git
synced 2026-02-24 02:10:30 -05:00
Merge branch '3405-security-limit-the-number-of-resource-records-in-rrset-nxdomain' into 'v9.20.0-release'
[CVE-2024-1737 (part 2)] Be smarter about refusing to add many RR types to the database See merge request isc-private/bind9!712
This commit is contained in:
commit
92a73bca2d
13 changed files with 2947 additions and 2671 deletions
|
|
@ -361,7 +361,6 @@ n=$((n + 1))
|
|||
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
|
||||
(
|
||||
|
|
|
|||
|
|
@ -19,3 +19,5 @@ rm -f ns?/named.memstats
|
|||
rm -f ns?/named.run
|
||||
rm -f ns*/named.conf
|
||||
rm -f ns*/managed-keys.bind*
|
||||
rm -f ns*/signed.db*
|
||||
rm -f ns*/*.db.signed
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -32,3 +32,8 @@ zone "big." {
|
|||
type primary;
|
||||
file "big.db";
|
||||
};
|
||||
|
||||
zone "signed." {
|
||||
type primary;
|
||||
file "signed.db.signed";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,5 +20,8 @@ direct.example.net. 60 IN A 10.53.0.2
|
|||
example.com. 60 IN NS direct.example.com.
|
||||
direct.example.com. 60 IN A 10.53.0.4
|
||||
|
||||
big. in NS ns.big.
|
||||
big. IN NS ns.big.
|
||||
ns.big. 60 IN A 10.53.0.1
|
||||
|
||||
signed. IN NS ns.signed.
|
||||
ns.signed. 60 IN A 10.53.0.1
|
||||
|
|
|
|||
|
|
@ -15,3 +15,8 @@
|
|||
|
||||
copy_setports ns1/named.conf.in ns1/named.conf
|
||||
copy_setports ns3/named1.conf.in ns3/named.conf
|
||||
|
||||
sed -e s/big[.]/signed./g <ns1/big.db >ns1/signed.db
|
||||
$KEYGEN -K ns1 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK signed >/dev/null 2>&1
|
||||
$KEYGEN -K ns1 -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" signed >/dev/null 2>&1
|
||||
$SIGNER -K ns1 -S -f ns1/signed.db.signed -o signed ns1/signed.db >/dev/null
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ set -e
|
|||
|
||||
. ../conf.sh
|
||||
|
||||
DIGOPTS="-p ${PORT}"
|
||||
dig_with_opts() {
|
||||
$DIG -p "${PORT}" +retries=0 "$@"
|
||||
}
|
||||
|
||||
status=0
|
||||
n=0
|
||||
|
|
@ -26,6 +28,10 @@ ns3_reset() {
|
|||
$RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush | sed 's/^/I:ns3 /'
|
||||
}
|
||||
|
||||
ns3_flush() {
|
||||
$RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush | sed 's/^/I:ns3 /'
|
||||
}
|
||||
|
||||
ns3_sends_aaaa_queries() {
|
||||
if grep "started AAAA fetch" ns3/named.run >/dev/null; then
|
||||
return 0
|
||||
|
|
@ -66,12 +72,12 @@ echo_i "attempt excessive-depth lookup ($n)"
|
|||
ret=0
|
||||
echo "1000" >ans2/ans.limit
|
||||
echo "1000" >ans4/ans.limit
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.4 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect1.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.4 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect1.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
check_query_count dig.out.2.test$n dig.out.4.test$n 27 14
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
|
@ -82,12 +88,12 @@ ret=0
|
|||
echo "12" >ans2/ans.limit
|
||||
echo "12" >ans4/ans.limit
|
||||
ns3_reset ns3/named1.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.4 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect2.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.4 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect2.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
check_query_count dig.out.2.test$n dig.out.4.test$n 50 26
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
|
@ -99,12 +105,12 @@ echo_i "attempt excessive-depth lookup ($n)"
|
|||
ret=0
|
||||
echo "12" >ans2/ans.limit
|
||||
ns3_reset ns3/named2.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.4 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect3.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.4 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect3.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
check_query_count dig.out.2.test$n dig.out.4.test$n 13 7
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
|
@ -115,12 +121,12 @@ ret=0
|
|||
echo "5" >ans2/ans.limit
|
||||
echo "5" >ans4/ans.limit
|
||||
ns3_reset ns3/named2.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.4 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect4.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.4 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect4.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
check_query_count dig.out.2.test$n dig.out.4.test$n 22 12
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
|
@ -133,14 +139,14 @@ ret=0
|
|||
echo "13" >ans2/ans.limit
|
||||
echo "13" >ans4/ans.limit
|
||||
ns3_reset ns3/named3.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.4 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect5.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.4 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect5.example.org >dig.out.1.test$n || ret=1
|
||||
if ns3_sends_aaaa_queries; then
|
||||
grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1
|
||||
fi
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.4 count txt >dig.out.4.test$n || ret=1
|
||||
eval count=$(cat dig.out.2.test$n)
|
||||
[ $count -le 50 ] || {
|
||||
ret=1
|
||||
|
|
@ -154,10 +160,10 @@ echo_i "attempt permissible lookup ($n)"
|
|||
ret=0
|
||||
echo "12" >ans2/ans.limit
|
||||
ns3_reset ns3/named3.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect6.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect6.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
eval count=$(cat dig.out.2.test$n)
|
||||
[ $count -le 50 ] || {
|
||||
ret=1
|
||||
|
|
@ -173,12 +179,12 @@ echo_i "attempt excessive-queries lookup ($n)"
|
|||
ret=0
|
||||
echo "11" >ans2/ans.limit
|
||||
ns3_reset ns3/named4.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect7.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect7.example.org >dig.out.1.test$n || ret=1
|
||||
if ns3_sends_aaaa_queries; then
|
||||
grep "status: SERVFAIL" dig.out.1.test$n >/dev/null || ret=1
|
||||
fi
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
eval count=$(cat dig.out.2.test$n)
|
||||
[ $count -le 40 ] || {
|
||||
ret=1
|
||||
|
|
@ -192,10 +198,10 @@ echo_i "attempt permissible lookup ($n)"
|
|||
ret=0
|
||||
echo "9" >ans2/ans.limit
|
||||
ns3_reset ns3/named4.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS @10.53.0.3 indirect8.example.org >dig.out.1.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts @10.53.0.3 indirect8.example.org >dig.out.1.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
eval count=$(cat dig.out.2.test$n)
|
||||
[ $count -le 40 ] || {
|
||||
ret=1
|
||||
|
|
@ -208,12 +214,12 @@ n=$((n + 1))
|
|||
echo_i "attempting NS explosion ($n)"
|
||||
ret=0
|
||||
ns3_reset ns3/named4.conf.in
|
||||
$DIG $DIGOPTS @10.53.0.2 reset >/dev/null || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.3 ns1.1.example.net >dig.out.1.test$n || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
dig_with_opts @10.53.0.2 reset >/dev/null || ret=1
|
||||
dig_with_opts +short @10.53.0.3 ns1.1.example.net >dig.out.1.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.2 count txt >dig.out.2.test$n || ret=1
|
||||
eval count=$(cat dig.out.2.test$n)
|
||||
[ $count -lt 50 ] || ret=1
|
||||
$DIG $DIGOPTS +short @10.53.0.7 count txt >dig.out.3.test$n || ret=1
|
||||
dig_with_opts +short @10.53.0.7 count txt >dig.out.3.test$n || ret=1
|
||||
eval count=$(cat dig.out.3.test$n)
|
||||
[ $count -lt 50 ] || {
|
||||
ret=1
|
||||
|
|
@ -225,46 +231,253 @@ status=$((status + ret))
|
|||
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
|
||||
dig_with_opts @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
|
||||
dig_with_opts @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
|
||||
name=$2
|
||||
type=$3
|
||||
expected=$4
|
||||
exname=$5
|
||||
extype=$6
|
||||
ttl=$7
|
||||
neq_ttl=$8
|
||||
|
||||
$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
|
||||
if ! dig_with_opts @10.53.0.3 IN "$type" "$name" >"dig.out.$i.$type.test$n"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! grep 'status: '"${expected}"'' "dig.out.$i.$type.test$n" >/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$ttl" ] && ! grep -q "^$exname.[[:space:]]*${ttl}[[:space:]]*IN[[:space:]]*$extype" "dig.out.$i.$type.test$n"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "${neq_ttl}" ] && grep -q "^$exname.[[:space:]]*${neq_ttl}[[:space:]]*IN[[:space:]]*$type" "dig.out.$i.$type.test$n"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
)
|
||||
|
||||
n=$((n + 1))
|
||||
echo_i "checking name that exceeds max-types-per-name ($n)"
|
||||
ret=0
|
||||
echo_i "checking that priority names under the max-types-per-name limit get cached ($n)"
|
||||
|
||||
# Limited to 10 types - these should be fine
|
||||
# Query for NXDOMAIN for items on our priority list - these should get cached
|
||||
for rrtype in AAAA MX NS; do
|
||||
check_manytypes 1 manytypes.big "${rrtype}" NOERROR big SOA 60 || ret=1
|
||||
done
|
||||
# Wait at least 1 second
|
||||
for rrtype in AAAA MX NS; do
|
||||
check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
ns3_flush
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that NXDOMAIN names under the max-types-per-name limit get cached ($n)"
|
||||
|
||||
# Query for 10 NXDOMAIN types
|
||||
for ntype in $(seq 65270 65279); do
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR big SOA 60 || ret=1
|
||||
done
|
||||
# Wait at least 1 second
|
||||
sleep 1
|
||||
# Query for 10 NXDOMAIN types again - these should be cached
|
||||
for ntype in $(seq 65270 65279); do
|
||||
check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR big SOA "" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that existing names under the max-types-per-name limit get cached ($n)"
|
||||
|
||||
# Limited to 10 types - these should be cached and the previous record should be evicted
|
||||
for ntype in $(seq 65280 65289); do
|
||||
check_manytypes 1 "TYPE${ntype}" NOERROR || ret=1
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 60 || 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
|
||||
# Wait at least one second
|
||||
sleep 1
|
||||
# Limited to 10 types - these should be cached
|
||||
for ntype in $(seq 65280 65289); do
|
||||
check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that NXDOMAIN names over the max-types-per-name limit don't get cached ($n)"
|
||||
|
||||
# Query for 10 NXDOMAIN types
|
||||
for ntype in $(seq 65270 65279); do
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR big SOA 0 || ret=1
|
||||
done
|
||||
# Wait at least 1 second
|
||||
sleep 1
|
||||
# Query for 10 NXDOMAIN types again - these should not be cached
|
||||
for ntype in $(seq 65270 65279); do
|
||||
check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR big SOA 0 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that priority NXDOMAIN names over the max-types-per-name limit get cached ($n)"
|
||||
|
||||
# Query for NXDOMAIN for items on our priority list - these should get cached
|
||||
for rrtype in AAAA MX NS; do
|
||||
check_manytypes 1 manytypes.big "${rrtype}" NOERROR big SOA 60 || ret=1
|
||||
done
|
||||
# Wait at least 1 second
|
||||
for rrtype in AAAA MX NS; do
|
||||
check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that priority name over the max-types-per-name get cached ($n)"
|
||||
|
||||
# Query for an item on our priority list - it should get cached
|
||||
check_manytypes 1 manytypes.big "A" NOERROR manytypes.big A 60 || ret=1
|
||||
# Wait at least 1 second
|
||||
sleep 1
|
||||
# Query the same name again - it should be in the cache
|
||||
check_manytypes 2 manytypes.big "A" NOERROR big manytypes.A "" 60 || ret=1
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
ns3_flush
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that priority name over the max-types-per-name don't get evicted ($n)"
|
||||
|
||||
# Query for an item on our priority list - it should get cached
|
||||
check_manytypes 1 manytypes.big "A" NOERROR manytypes.big A 60 || ret=1
|
||||
# Query for 10 more types - this should not evict A record
|
||||
for ntype in $(seq 65280 65289); do
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big || ret=1
|
||||
done
|
||||
# Wait at least 1 second
|
||||
sleep 1
|
||||
# Query the same name again - it should be in the cache
|
||||
check_manytypes 2 manytypes.big "A" NOERROR manytypes.big A "" 60 || ret=1
|
||||
# This one was first in the list and should have been evicted
|
||||
check_manytypes 2 manytypes.big "TYPE65280" NOERROR manytypes.big TYPE65280 60 || ret=1
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
ns3_flush
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that non-priority types cause eviction ($n)"
|
||||
|
||||
# Everything on top of that will cause the cache eviction
|
||||
for ntype in $(seq 65280 65299); do
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
# Wait at least one second
|
||||
sleep 1
|
||||
# These should have TTL != 60 now
|
||||
for ntype in $(seq 65290 65299); do
|
||||
check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 60 || ret=1
|
||||
done
|
||||
# These should have been evicted
|
||||
for ntype in $(seq 65280 65289); do
|
||||
check_manytypes 3 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
# These should have been evicted by the previous block
|
||||
for ntype in $(seq 65290 65299); do
|
||||
check_manytypes 4 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
ns3_flush
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that signed names under the max-types-per-name limit get cached ($n)"
|
||||
|
||||
# Go through the 10 items, this should result in 20 items (type + rrsig(type))
|
||||
for ntype in $(seq 65280 65289); do
|
||||
check_manytypes 1 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
|
||||
# Wait at least one second
|
||||
sleep 1
|
||||
|
||||
# These should have TTL != 60 now
|
||||
for ntype in $(seq 65285 65289); do
|
||||
check_manytypes 2 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" "" 60 || ret=1
|
||||
done
|
||||
|
||||
# These should have been evicted
|
||||
for ntype in $(seq 65280 65284); do
|
||||
check_manytypes 3 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
|
||||
# These should have been evicted by the previous block
|
||||
for ntype in $(seq 65285 65289); do
|
||||
check_manytypes 4 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
if [ $status -ne 0 ]; then exit 1; fi
|
||||
|
||||
n=$((n + 1))
|
||||
ret=0
|
||||
echo_i "checking that lifting the limit will allow everything to get cached ($n)"
|
||||
|
||||
# Lift the limit
|
||||
ns3_reset ns3/named6.conf.in
|
||||
|
||||
for ntype in $(seq 65280 65534); do
|
||||
check_manytypes 2 "TYPE${ntype}" NOERROR || ret=1
|
||||
check_manytypes 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 60 || ret=1
|
||||
done
|
||||
# Wait at least one second
|
||||
sleep 1
|
||||
for ntype in $(seq 65280 65534); do
|
||||
check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 60 || ret=1
|
||||
done
|
||||
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
if [ $ret -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
|
|
|
|||
|
|
@ -474,18 +474,18 @@ n=$((n + 1))
|
|||
echo_i "check prefetch qtype * (${n})"
|
||||
ret=0
|
||||
dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.1.${n} || ret=1
|
||||
ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 3 }' dig.out.1.${n})
|
||||
ttl1=$(awk '/^fetchall.tld/ { print $2 - 3; exit }' dig.out.1.${n})
|
||||
# sleep so we are in prefetch range
|
||||
sleep "${ttl1:-0}"
|
||||
# trigger prefetch
|
||||
dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.2.${n} || ret=1
|
||||
ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n})
|
||||
ttl2=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.2.${n})
|
||||
sleep 1
|
||||
# check that prefetch occurred;
|
||||
# note that only one record is prefetched, which is the AAAA record in this case,
|
||||
# note that only the first record is prefetched,
|
||||
# because of the order of the records in the cache
|
||||
dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.3.${n} || ret=1
|
||||
ttl3=$(awk '/::1/ { print $2 }' dig.out.3.${n})
|
||||
ttl3=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.3.${n})
|
||||
test "${ttl3:-0}" -gt "${ttl2:-1}" || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
|
|
|||
|
|
@ -145,4 +145,46 @@ typedef struct {
|
|||
bool exiting;
|
||||
} db_nodelock_t;
|
||||
|
||||
static inline bool
|
||||
prio_type(dns_typepair_t type) {
|
||||
switch (type) {
|
||||
case dns_rdatatype_soa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_soa):
|
||||
case dns_rdatatype_a:
|
||||
case DNS_SIGTYPE(dns_rdatatype_a):
|
||||
case dns_rdatatype_mx:
|
||||
case DNS_SIGTYPE(dns_rdatatype_mx):
|
||||
case dns_rdatatype_aaaa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_aaaa):
|
||||
case dns_rdatatype_nsec:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec):
|
||||
case dns_rdatatype_nsec3:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec3):
|
||||
case dns_rdatatype_ns:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ns):
|
||||
case dns_rdatatype_ds:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ds):
|
||||
case dns_rdatatype_cname:
|
||||
case DNS_SIGTYPE(dns_rdatatype_cname):
|
||||
case dns_rdatatype_dname:
|
||||
case DNS_SIGTYPE(dns_rdatatype_dname):
|
||||
case dns_rdatatype_svcb:
|
||||
case DNS_SIGTYPE(dns_rdatatype_svcb):
|
||||
case dns_rdatatype_https:
|
||||
case DNS_SIGTYPE(dns_rdatatype_https):
|
||||
case dns_rdatatype_dnskey:
|
||||
case DNS_SIGTYPE(dns_rdatatype_dnskey):
|
||||
case dns_rdatatype_srv:
|
||||
case DNS_SIGTYPE(dns_rdatatype_srv):
|
||||
case dns_rdatatype_txt:
|
||||
case DNS_SIGTYPE(dns_rdatatype_txt):
|
||||
case dns_rdatatype_ptr:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ptr):
|
||||
case dns_rdatatype_naptr:
|
||||
case DNS_SIGTYPE(dns_rdatatype_naptr):
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
|
|
|||
|
|
@ -2438,30 +2438,6 @@ again:
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
prio_type(dns_typepair_t type) {
|
||||
switch (type) {
|
||||
case dns_rdatatype_soa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_soa):
|
||||
case dns_rdatatype_a:
|
||||
case DNS_SIGTYPE(dns_rdatatype_a):
|
||||
case dns_rdatatype_aaaa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_aaaa):
|
||||
case dns_rdatatype_nsec:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec):
|
||||
case dns_rdatatype_nsec3:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec3):
|
||||
case dns_rdatatype_ns:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ns):
|
||||
case dns_rdatatype_ds:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ds):
|
||||
case dns_rdatatype_cname:
|
||||
case DNS_SIGTYPE(dns_rdatatype_cname):
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*%
|
||||
* These functions allow the heap code to rank the priority of each
|
||||
* element. It returns true if v1 happens "sooner" than v2.
|
||||
|
|
@ -2871,6 +2847,24 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static bool
|
||||
overmaxtype(qpcache_t *qpdb, uint32_t ntypes) {
|
||||
if (qpdb->maxtypepername == 0) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (ntypes >= qpdb->maxtypepername);
|
||||
}
|
||||
|
||||
static bool
|
||||
prio_header(dns_slabheader_t *header) {
|
||||
if (NEGATIVE(header) && prio_type(DNS_TYPEPAIR_COVERS(header->type))) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (prio_type(header->type));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
||||
const dns_name_t *nodename ISC_ATTR_UNUSED, dns_slabheader_t *newheader,
|
||||
|
|
@ -2879,14 +2873,13 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
isc_rwlocktype_t tlocktype DNS__DB_FLARG) {
|
||||
dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
|
||||
dns_slabheader_t *header = NULL, *sigheader = NULL;
|
||||
dns_slabheader_t *prioheader = NULL;
|
||||
dns_slabheader_t *prioheader = NULL, *expireheader = NULL;
|
||||
bool header_nx;
|
||||
bool newheader_nx;
|
||||
dns_rdatatype_t rdtype, covers;
|
||||
dns_typepair_t negtype = 0, sigtype;
|
||||
dns_typepair_t negtype = 0;
|
||||
dns_trust_t trust;
|
||||
int idx;
|
||||
uint32_t ntypes;
|
||||
uint32_t ntypes = 0;
|
||||
|
||||
if ((options & DNS_DBADD_FORCE) != 0) {
|
||||
trust = dns_trust_ultimate;
|
||||
|
|
@ -2895,10 +2888,11 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
}
|
||||
|
||||
newheader_nx = NONEXISTENT(newheader) ? true : false;
|
||||
|
||||
if (!newheader_nx) {
|
||||
rdtype = DNS_TYPEPAIR_TYPE(newheader->type);
|
||||
covers = DNS_TYPEPAIR_COVERS(newheader->type);
|
||||
sigtype = DNS_SIGTYPE(covers);
|
||||
dns_rdatatype_t rdtype = DNS_TYPEPAIR_TYPE(newheader->type);
|
||||
dns_rdatatype_t covers = DNS_TYPEPAIR_COVERS(newheader->type);
|
||||
dns_typepair_t sigtype = DNS_SIGTYPE(covers);
|
||||
if (NEGATIVE(newheader)) {
|
||||
/*
|
||||
* We're adding a negative cache entry.
|
||||
|
|
@ -2919,7 +2913,6 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
{
|
||||
mark_ancient(topheader);
|
||||
}
|
||||
ntypes = 0; /* Always add the negative entry */
|
||||
goto find_header;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2931,6 +2924,7 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
{
|
||||
if (topheader->type == sigtype) {
|
||||
sigheader = topheader;
|
||||
break;
|
||||
}
|
||||
}
|
||||
negtype = DNS_TYPEPAIR_VALUE(covers, 0);
|
||||
|
|
@ -2943,11 +2937,9 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
* check for an extant non-ancient NODATA ncache
|
||||
* entry which covers the same type as the RRSIG.
|
||||
*/
|
||||
ntypes = 0;
|
||||
for (topheader = qpnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||
(newheader->type == sigtype &&
|
||||
topheader->type ==
|
||||
|
|
@ -2990,15 +2982,17 @@ add(qpcache_t *qpdb, qpcnode_t *qpnode,
|
|||
}
|
||||
}
|
||||
|
||||
ntypes = 0;
|
||||
for (topheader = qpnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
|
||||
if (prio_type(topheader->type)) {
|
||||
if (ACTIVE(topheader, now)) {
|
||||
++ntypes;
|
||||
expireheader = topheader;
|
||||
}
|
||||
if (prio_header(topheader)) {
|
||||
prioheader = topheader;
|
||||
}
|
||||
|
||||
if (topheader->type == newheader->type ||
|
||||
topheader->type == negtype)
|
||||
{
|
||||
|
|
@ -3263,17 +3257,9 @@ find_header:
|
|||
/*
|
||||
* No rdatasets of the given type exist at the node.
|
||||
*/
|
||||
if (trust != dns_trust_ultimate &&
|
||||
qpdb->maxtypepername > 0 &&
|
||||
ntypes >= qpdb->maxtypepername)
|
||||
{
|
||||
dns_slabheader_destroy(&newheader);
|
||||
return (DNS_R_TOOMANYRECORDS);
|
||||
}
|
||||
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (prio_type(newheader->type)) {
|
||||
if (prio_header(newheader)) {
|
||||
/* This is a priority type, prepend it */
|
||||
newheader->next = qpnode->data;
|
||||
qpnode->data = newheader;
|
||||
|
|
@ -3286,6 +3272,30 @@ find_header:
|
|||
newheader->next = qpnode->data;
|
||||
qpnode->data = newheader;
|
||||
}
|
||||
|
||||
if (overmaxtype(qpdb, ntypes)) {
|
||||
if (expireheader == NULL) {
|
||||
expireheader = newheader;
|
||||
}
|
||||
if (NEGATIVE(newheader) &&
|
||||
!prio_header(newheader))
|
||||
{
|
||||
/*
|
||||
* Add the new non-priority negative
|
||||
* header to the database only
|
||||
* temporarily.
|
||||
*/
|
||||
expireheader = newheader;
|
||||
}
|
||||
|
||||
mark_ancient(expireheader);
|
||||
/*
|
||||
* FIXME: In theory, we should mark the RRSIG
|
||||
* and the header at the same time, but there is
|
||||
* no direct link between those two header, so
|
||||
* we would have to check the whole list again.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -330,31 +330,6 @@ typedef struct qpdb_dbiterator {
|
|||
*/
|
||||
static atomic_uint_fast16_t init_count = 0;
|
||||
|
||||
static bool
|
||||
prio_type(dns_typepair_t type) {
|
||||
switch (type) {
|
||||
case dns_rdatatype_soa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_soa):
|
||||
case dns_rdatatype_a:
|
||||
case DNS_SIGTYPE(dns_rdatatype_a):
|
||||
case dns_rdatatype_aaaa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_aaaa):
|
||||
case dns_rdatatype_nsec:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec):
|
||||
case dns_rdatatype_ns:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ns):
|
||||
case dns_rdatatype_ds:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ds):
|
||||
case dns_rdatatype_nsec3:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec3):
|
||||
case dns_rdatatype_cname:
|
||||
case DNS_SIGTYPE(dns_rdatatype_cname):
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locking
|
||||
*
|
||||
|
|
|
|||
|
|
@ -351,30 +351,6 @@ dns__rbtdb_setttl(dns_slabheader_t *header, dns_ttl_t newttl) {
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
prio_type(dns_typepair_t type) {
|
||||
switch (type) {
|
||||
case dns_rdatatype_soa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_soa):
|
||||
case dns_rdatatype_a:
|
||||
case DNS_SIGTYPE(dns_rdatatype_a):
|
||||
case dns_rdatatype_aaaa:
|
||||
case DNS_SIGTYPE(dns_rdatatype_aaaa):
|
||||
case dns_rdatatype_nsec:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec):
|
||||
case dns_rdatatype_nsec3:
|
||||
case DNS_SIGTYPE(dns_rdatatype_nsec3):
|
||||
case dns_rdatatype_ns:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ns):
|
||||
case dns_rdatatype_ds:
|
||||
case DNS_SIGTYPE(dns_rdatatype_ds):
|
||||
case dns_rdatatype_cname:
|
||||
case DNS_SIGTYPE(dns_rdatatype_cname):
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*%
|
||||
* These functions allow the heap code to rank the priority of each
|
||||
* element. It returns true if v1 happens "sooner" than v2.
|
||||
|
|
@ -2548,6 +2524,24 @@ update_recordsandxfrsize(bool add, dns_rbtdb_version_t *rbtversion,
|
|||
RWUNLOCK(&rbtversion->rwlock, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
static bool
|
||||
overmaxtype(dns_rbtdb_t *rbtdb, uint32_t ntypes) {
|
||||
if (rbtdb->maxtypepername == 0) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (ntypes >= rbtdb->maxtypepername);
|
||||
}
|
||||
|
||||
static bool
|
||||
prio_header(dns_slabheader_t *header) {
|
||||
if (NEGATIVE(header) && prio_type(DNS_TYPEPAIR_COVERS(header->type))) {
|
||||
return (true);
|
||||
}
|
||||
|
||||
return (prio_type(header->type));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
||||
const dns_name_t *nodename, dns_rbtdb_version_t *rbtversion,
|
||||
|
|
@ -2556,7 +2550,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
rbtdb_changed_t *changed = NULL;
|
||||
dns_slabheader_t *topheader = NULL, *topheader_prev = NULL;
|
||||
dns_slabheader_t *header = NULL, *sigheader = NULL;
|
||||
dns_slabheader_t *prioheader = NULL;
|
||||
dns_slabheader_t *prioheader = NULL, *expireheader = NULL;
|
||||
unsigned char *merged = NULL;
|
||||
isc_result_t result;
|
||||
bool header_nx;
|
||||
|
|
@ -2619,7 +2613,6 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
{
|
||||
mark_ancient(topheader);
|
||||
}
|
||||
ntypes = 0; /* Always add the negative entry */
|
||||
goto find_header;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2631,6 +2624,7 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
{
|
||||
if (topheader->type == sigtype) {
|
||||
sigheader = topheader;
|
||||
break;
|
||||
}
|
||||
}
|
||||
negtype = DNS_TYPEPAIR_VALUE(covers, 0);
|
||||
|
|
@ -2643,11 +2637,9 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
* check for an extant non-ancient NODATA ncache
|
||||
* entry which covers the same type as the RRSIG.
|
||||
*/
|
||||
ntypes = 0;
|
||||
for (topheader = rbtnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if ((topheader->type == RDATATYPE_NCACHEANY) ||
|
||||
(newheader->type == sigtype &&
|
||||
topheader->type ==
|
||||
|
|
@ -2690,12 +2682,16 @@ dns__rbtdb_add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode,
|
|||
}
|
||||
}
|
||||
|
||||
ntypes = 0;
|
||||
for (topheader = rbtnode->data; topheader != NULL;
|
||||
topheader = topheader->next)
|
||||
{
|
||||
++ntypes;
|
||||
if (prio_type(topheader->type)) {
|
||||
if (IS_CACHE(rbtdb) && ACTIVE(topheader, now)) {
|
||||
++ntypes;
|
||||
expireheader = topheader;
|
||||
} else if (!IS_CACHE(rbtdb)) {
|
||||
++ntypes;
|
||||
}
|
||||
if (prio_header(topheader)) {
|
||||
prioheader = topheader;
|
||||
}
|
||||
if (topheader->type == newheader->type ||
|
||||
|
|
@ -3088,17 +3084,14 @@ find_header:
|
|||
/*
|
||||
* No rdatasets of the given type exist at the node.
|
||||
*/
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (rbtdb->maxtypepername > 0 &&
|
||||
ntypes >= rbtdb->maxtypepername)
|
||||
{
|
||||
if (!IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) {
|
||||
dns_slabheader_destroy(&newheader);
|
||||
return (DNS_R_TOOMANYRECORDS);
|
||||
}
|
||||
|
||||
INSIST(newheader->down == NULL);
|
||||
|
||||
if (prio_type(newheader->type)) {
|
||||
if (prio_header(newheader)) {
|
||||
/* This is a priority type, prepend it */
|
||||
newheader->next = rbtnode->data;
|
||||
rbtnode->data = newheader;
|
||||
|
|
@ -3111,6 +3104,30 @@ find_header:
|
|||
newheader->next = rbtnode->data;
|
||||
rbtnode->data = newheader;
|
||||
}
|
||||
|
||||
if (IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) {
|
||||
if (expireheader == NULL) {
|
||||
expireheader = newheader;
|
||||
}
|
||||
if (NEGATIVE(newheader) &&
|
||||
!prio_header(newheader))
|
||||
{
|
||||
/*
|
||||
* Add the new non-priority negative
|
||||
* header to the database only
|
||||
* temporarily.
|
||||
*/
|
||||
expireheader = newheader;
|
||||
}
|
||||
|
||||
mark_ancient(expireheader);
|
||||
/*
|
||||
* FIXME: In theory, we should mark the RRSIG
|
||||
* and the header at the same time, but there is
|
||||
* no direct link between those two header, so
|
||||
* we would have to check the whole list again.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include <dns/rbt.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
#include "db_p.h" /* for db_nodelock_t */
|
||||
|
||||
/*%
|
||||
* Note that "impmagic" is not the first four bytes of the struct, so
|
||||
* ISC_MAGIC_VALID cannot be used.
|
||||
|
|
|
|||
Loading…
Reference in a new issue