#!/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. set -e . ../conf.sh dig_with_opts() { $DIG -p "${PORT}" +retries=0 "$@" } status=0 n=0 ns3_reset() { copy_setports $1 ns3/named.conf $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reconfig 2>&1 | sed 's/^/I:ns3 /' $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 else return 1 fi } # Check whether the number of queries ans2 received from ns3 (this value is # read from dig output stored in file $1) is as expected. The expected query # count is variable: # - if ns3 sends AAAA queries, the query count should equal $2, # - if ns3 does not send AAAA queries, the query count should equal $3. check_query_count() { count1=$(sed 's/[^0-9]//g;' $1) count2=$(sed 's/[^0-9]//g;' $2) count=$((count1 + count2)) #echo_i "count1=$count1 count2=$count2 count=$count" expected_count_with_aaaa=$3 expected_count_without_aaaa=$4 if ns3_sends_aaaa_queries; then expected_count=$expected_count_with_aaaa else expected_count=$expected_count_without_aaaa fi if [ $count -ne $expected_count ]; then echo_i "count $count (actual) != $expected_count (expected)" ret=1 fi } echo_i "set max-recursion-depth=12" n=$((n + 1)) echo_i "attempt excessive-depth lookup ($n)" ret=0 echo "1000" >ans2/ans.limit echo "1000" >ans4/ans.limit 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_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)) n=$((n + 1)) echo_i "attempt permissible lookup ($n)" ret=0 echo "12" >ans2/ans.limit echo "12" >ans4/ans.limit ns3_reset ns3/named1.conf.in 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_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)) echo_i "set max-recursion-depth=5" n=$((n + 1)) echo_i "attempt excessive-depth lookup ($n)" ret=0 echo "12" >ans2/ans.limit ns3_reset ns3/named2.conf.in 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_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)) n=$((n + 1)) echo_i "attempt permissible lookup ($n)" ret=0 echo "5" >ans2/ans.limit echo "5" >ans4/ans.limit ns3_reset ns3/named2.conf.in 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_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)) echo_i "set max-recursion-depth=100, max-recursion-queries=50" n=$((n + 1)) echo_i "attempt excessive-queries lookup ($n)" ret=0 echo "13" >ans2/ans.limit echo "13" >ans4/ans.limit ns3_reset ns3/named3.conf.in 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_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 echo_i "count ($count) !<= 50" } if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) n=$((n + 1)) echo_i "attempt permissible lookup ($n)" ret=0 echo "12" >ans2/ans.limit ns3_reset ns3/named3.conf.in 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_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 echo_i "count ($count) !<= 50" } if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) echo_i "set max-recursion-depth=100, max-recursion-queries=40" n=$((n + 1)) echo_i "attempt excessive-queries lookup ($n)" ret=0 echo "11" >ans2/ans.limit ns3_reset ns3/named4.conf.in 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_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 echo_i "count ($count) !<= 40" } if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) n=$((n + 1)) echo_i "attempt permissible lookup ($n)" ret=0 echo "9" >ans2/ans.limit ns3_reset ns3/named4.conf.in 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_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 echo_i "count ($count) !<= 40" } if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) n=$((n + 1)) echo_i "attempting NS explosion ($n)" ret=0 ns3_reset ns3/named4.conf.in 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_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 echo_i "count ($count) !<= 50" } if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) n=$((n + 1)) echo_i "checking RRset that exceeds max-records-per-type ($n)" ret=0 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 msg="error adding 'biganswer.big/A' in './IN' (cache): too many records (must not exceed 100)" wait_for_log 10 "$msg" ns3/named.run || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) ns3_reset ns3/named5.conf.in 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 name=$2 type=$3 expected=$4 exname=$5 extype=$6 ttl=$7 neq_ttl=$8 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)) ret=0 echo_i "checking that priority names under 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 120 || ret=1 done # Wait at least 1 second for rrtype in AAAA MX NS; do check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 120 || 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 120 || 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 "" 120 || 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 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || ret=1 done # 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}" "" 120 || 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 120 || ret=1 done # Wait at least 1 second for rrtype in AAAA MX NS; do check_manytypes 2 manytypes.big "${rrtype}" NOERROR big SOA "" 120 || 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 120 || 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 "" 120 || 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 120 || 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 "" 120 || ret=1 # This one was first in the list and should have been evicted check_manytypes 2 manytypes.big "TYPE65280" NOERROR manytypes.big TYPE65280 120 || 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}" 120 || ret=1 done # Wait at least one second sleep 1 # These should have TTL != 120 now for ntype in $(seq 65290 65299); do check_manytypes 2 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" "" 120 || 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}" 120 || 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}" 120 || 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}" 120 || ret=1 done # Wait at least one second sleep 1 # These should have TTL != 120 now for ntype in $(seq 65285 65289); do check_manytypes 2 manytypes.signed "TYPE${ntype}" NOERROR manytypes.signed "TYPE${ntype}" "" 120 || 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}" 120 || 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}" 120 || 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 1 manytypes.big "TYPE${ntype}" NOERROR manytypes.big "TYPE${ntype}" 120 || 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}" "" 120 || ret=1 done if [ $ret -ne 0 ]; then echo_i "failed"; fi status=$((status + ret)) echo_i "exit status: $status" [ $status -eq 0 ] || exit 1