xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/rrl/tests.sh (revision 782713e6c126f1866c6d9cfdee4ceb49483b5828)
1#!/bin/sh
2
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# SPDX-License-Identifier: MPL-2.0
6#
7# This Source Code Form is subject to the terms of the Mozilla Public
8# License, v. 2.0.  If a copy of the MPL was not distributed with this
9# file, you can obtain one at https://mozilla.org/MPL/2.0/.
10#
11# See the COPYRIGHT file distributed with this work for additional
12# information regarding copyright ownership.
13
14# test response rate limiting
15
16SYSTEMTESTTOP=..
17. $SYSTEMTESTTOP/conf.sh
18
19RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
20
21#set -x
22
23ns1=10.53.0.1			    # root, defining the others
24ns2=10.53.0.2			    # test server
25ns3=10.53.0.3			    # secondary test server
26ns4=10.53.0.4			    # log-only test server
27ns7=10.53.0.7			    # whitelisted client
28
29USAGE="$0: [-x]"
30while getopts "x" c; do
31    case $c in
32	x) set -x;;
33	*) echo "$USAGE" 1>&2; exit 1;;
34    esac
35done
36shift `expr $OPTIND - 1 || true`
37if test "$#" -ne 0; then
38    echo "$USAGE" 1>&2
39    exit 1
40fi
41# really quit on control-C
42trap 'exit 1' 1 2 15
43
44
45ret=0
46setret () {
47    ret=1
48    echo_i "$*"
49}
50
51
52# Wait until soon after the start of a second to make results consistent.
53#   The start of a second credits a rate limit.
54#   This would be far easier in C or by assuming a modern version of perl.
55sec_start () {
56    START=`date`
57    while true; do
58	NOW=`date`
59	if test "$START" != "$NOW"; then
60	    return
61	fi
62	$PERL -e 'select(undef, undef, undef, 0.05)' || true
63    done
64}
65
66
67# turn off ${HOME}/.digrc
68HOME=/dev/null; export HOME
69
70#   $1=number of tests  $2=target domain  $3=dig options
71QNUM=1
72burst () {
73    BURST_LIMIT=$1; shift
74    BURST_DOM_BASE="$1"; shift
75
76    XCNT=$CNT
77    CNT='XXX'
78    eval FILENAME="mdig.out-$BURST_DOM_BASE"
79    CNT=$XCNT
80
81    DOMS=""
82    CNTS=`$PERL -e 'for ( $i = 0; $i < '$BURST_LIMIT'; $i++) { printf "%03d\n", '$QNUM' + $i; }'`
83    for CNT in $CNTS
84    do
85        eval BURST_DOM="$BURST_DOM_BASE"
86        DOMS="$DOMS $BURST_DOM"
87    done
88    ARGS="+burst +nocookie +continue +time=1 +tries=1 -p ${PORT} $* @$ns2 $DOMS"
89    $MDIG $ARGS 2>&1 |                                                  \
90        tr -d '\r' |                                                    \
91        tee -a full-$FILENAME |                                         \
92        sed -n -e '/^;; AUTHORITY/,/^$/d'			        \
93		-e '/^;; ADDITIONAL/,/^$/d'				\
94		-e 's/^[^;].*	\([^	 ]\{1,\}\)$/\1/p'		\
95		-e 's/;; flags.* tc .*/TC/p'				\
96		-e 's/;; .* status: NXDOMAIN.*/NXDOMAIN/p'		\
97		-e 's/;; .* status: NOERROR.*/NOERROR/p'		\
98		-e 's/;; .* status: SERVFAIL.*/SERVFAIL/p'		\
99		-e 's/response failed with timed out.*/drop/p'		\
100		-e 's/;; communications error to.*/drop/p' >> $FILENAME &
101    QNUM=`expr $QNUM + $BURST_LIMIT`
102}
103
104# compare integers $1 and $2; ensure the difference is no more than $3
105range () {
106    $PERL -e 'if (abs(int($ARGV[0]) - int($ARGV[1])) > int($ARGV[2])) { exit(1) }' $1 $2 $3
107}
108
109#   $1=domain  $2=IP address  $3=# of IP addresses  $4=TC  $5=drop
110#	$6=NXDOMAIN  $7=SERVFAIL or other errors
111ck_result() {
112    # wait to the background mdig calls to complete.
113    wait
114    BAD=no
115    ADDRS=`grep -E "^$2$" mdig.out-$1				2>/dev/null | wc -l`
116    # count simple truncated and truncated NXDOMAIN as TC
117    TC=`grep -E "^TC|NXDOMAINTC$" mdig.out-$1			2>/dev/null | wc -l`
118    DROP=`grep -E "^drop$" mdig.out-$1				2>/dev/null | wc -l`
119    # count NXDOMAIN and truncated NXDOMAIN as NXDOMAIN
120    NXDOMAIN=`grep -E "^NXDOMAIN|NXDOMAINTC$" mdig.out-$1		2>/dev/null | wc -l`
121    SERVFAIL=`grep -E "^SERVFAIL$" mdig.out-$1			2>/dev/null | wc -l`
122    NOERROR=`grep -E "^NOERROR$" mdig.out-$1			2>/dev/null | wc -l`
123
124    range $ADDRS "$3" 1 ||
125    setret "$ADDRS instead of $3 '$2' responses for $1" &&
126    BAD=yes
127
128    range $TC "$4" 1 ||
129    setret "$TC instead of $4 truncation responses for $1" &&
130    BAD=yes
131
132    range $DROP "$5" 1 ||
133    setret "$DROP instead of $5 dropped responses for $1" &&
134    BAD=yes
135
136    range $NXDOMAIN "$6" 1 ||
137    setret "$NXDOMAIN instead of $6 NXDOMAIN responses for $1" &&
138    BAD=yes
139
140    range $SERVFAIL "$7" 1 ||
141    setret "$SERVFAIL instead of $7 error responses for $1" &&
142    BAD=yes
143
144    range $NOERROR "$8" 1 ||
145    setret "$NOERROR instead of $8 NOERROR responses for $1" &&
146    BAD=yes
147
148    if test -z "$BAD"; then
149	rm -f mdig.out-$1
150    fi
151}
152
153
154ckstats () {
155    LABEL="$1"; shift
156    TYPE="$1"; shift
157    EXPECTED="$1"; shift
158    C=`tr -d '\r' < ns2/named.stats |
159        sed -n -e "s/[	 ]*\([0-9]*\).responses $TYPE for rate limits.*/\1/p" |
160        tail -1`
161    C=`expr 0$C + 0`
162
163    range "$C" $EXPECTED 1 ||
164    setret "wrong $LABEL $TYPE statistics of $C instead of $EXPECTED"
165}
166
167
168#########
169sec_start
170
171# Tests of referrals to "." must be done before the hints are loaded
172#   or with "additional-from-cache no"
173burst 5 a1.tld3 +norec
174# basic rate limiting
175burst 3 a1.tld2
176# delay allows an additional response.
177sleep 1
178burst 10 a1.tld2
179# Request 30 different qnames to try a wildcard.
180burst 30 'y.x$CNT.a2.tld2'
181
182#					IP      TC      drop  NXDOMAIN SERVFAIL NOERROR
183# referrals to "."
184ck_result   a1.tld3	x		0	1	2	0	0	2
185# check 13 results including 1 second delay that allows an additional response
186ck_result   a1.tld2	192.0.2.1	3	4	6	0	0	8
187
188# Check the wildcard answers.
189# The zone origin name of the 30 requests is counted.
190ck_result 'y.x*.a2.tld2'	192.0.2.2	2	10	18	0	0	12
191
192#########
193sec_start
194
195burst 10 'x.a3.tld3'
196burst 10 'y$CNT.a3.tld3'
197burst 10 'z$CNT.a4.tld2'
198
199# 10 identical recursive responses are limited
200ck_result 'x.a3.tld3'	192.0.3.3	2	3	5	0	0	5
201
202# 10 different recursive responses are not limited
203ck_result 'y*.a3.tld3'	192.0.3.3	10	0	0	0	0	10
204
205# 10 different NXDOMAIN responses are limited based on the parent name.
206#   We count 13 responses because we count truncated NXDOMAIN responses
207#   as both truncated and NXDOMAIN.
208ck_result 'z*.a4.tld2'	x		0	3	5	5	0	0
209
210$RNDCCMD $ns2 stats
211ckstats first dropped 36
212ckstats first truncated 21
213
214
215#########
216sec_start
217
218burst 10 a5.tld2 +tcp
219burst 10 a6.tld2 -b $ns7
220burst 10 a7.tld4
221burst 2 a8.tld2 -t AAAA
222burst 2 a8.tld2 -t TXT
223burst 2 a8.tld2 -t SPF
224
225#					IP      TC      drop  NXDOMAIN SERVFAIL NOERROR
226# TCP responses are not rate limited
227ck_result a5.tld2	192.0.2.5	10	0	0	0	0	10
228
229# whitelisted client is not rate limited
230ck_result a6.tld2	192.0.2.6	10	0	0	0	0	10
231
232# Errors such as SERVFAIL are rate limited.
233ck_result a7.tld4	x		0	0	8	0	2	0
234
235# NODATA responses are counted as the same regardless of qtype.
236ck_result a8.tld2	x		0	2	2	0	0	4
237
238$RNDCCMD $ns2 stats
239ckstats second dropped 46
240ckstats second truncated 23
241
242
243#########
244sec_start
245
246#					IP      TC      drop  NXDOMAIN SERVFAIL NOERROR
247# all-per-second
248#   The qnames are all unique but the client IP address is constant.
249QNUM=101
250burst 60 'all$CNT.a9.tld2'
251
252ck_result 'a*.a9.tld2'	192.0.2.8	50	0	10	0	0	50
253
254$RNDCCMD $ns2 stats
255ckstats final dropped 56
256ckstats final truncated 23
257
258#########
259sec_start
260
261DIGOPTS="+nocookie +nosearch +time=1 +tries=1 +ignore -p ${PORT}"
262$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
263$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
264$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
265$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
266$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
267$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
268$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
269$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
270$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
271$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
272$DIG $DIGOPTS @$ns4 A a7.tld4 > /dev/null 2>&1
273
274# regression test for GL #2839
275DIGOPTS="+bufsize=4096 +ignore -p ${PORT}"
276$DIG $DIGOPTS @$ns4 TXT big.tld4 > /dev/null 2>&1
277
278grep "would limit" ns4/named.run >/dev/null 2>&1 ||
279setret "\"would limit\" not found in log file."
280
281$NAMED -D rrl-ns5 -gc broken.conf > broken.out 2>&1 &
282sleep 2
283grep "min-table-size 1" broken.out > /dev/null || setret "min-table-size 0 was not changed to 1"
284
285if [ -f named.pid ]; then
286    $KILL `cat named.pid`
287    setret "named should not have started, but did"
288fi
289
290echo_i "exit status: $ret"
291[ $ret -eq 0 ] || exit 1
292