1# Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 2# 3# Permission to use, copy, modify, and/or distribute this software for any 4# purpose with or without fee is hereby granted, provided that the above 5# copyright notice and this permission notice appear in all copies. 6# 7# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 8# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 10# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 12# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13# PERFORMANCE OF THIS SOFTWARE. 14 15# Id: tests.sh,v 1.12 2012/01/07 23:46:53 tbox Exp 16 17# test response policy zones (RPZ) 18 19SYSTEMTESTTOP=.. 20. $SYSTEMTESTTOP/conf.sh 21 22ns=10.53.0 23ns1=$ns.1 # root, defining the others 24ns2=$ns.2 # server whose answers are rewritten 25ns3=$ns.3 # resolve that does the rewriting 26ns4=$ns.4 # another server that is rewritten 27ns5=$ns.5 # check performance with this server 28 29HAVE_CORE= 30 31USAGE="$0: [-x]" 32while getopts "x" c; do 33 case $c in 34 x) set -x;; 35 *) echo "$USAGE" 1>&2; exit 1;; 36 esac 37done 38shift `expr $OPTIND - 1 || true` 39if test "$#" -ne 0; then 40 echo "$USAGE" 1>&2 41 exit 1 42fi 43# really quit on control-C 44trap 'exit 1' 1 2 15 45 46 47RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p 9953 -s" 48 49digcmd () { 50 digcmd_args="+noadd +nosearch +time=1 +tries=1 -p 5300 $*" 51 expr "$digcmd_args" : '.*@' >/dev/null || \ 52 digcmd_args="$digcmd_args @$ns3" 53 expr "$digcmd_args" : '.*+[no]*auth' >/dev/null || \ 54 digcmd_args="+noauth $digcmd_args" 55 #echo I:dig $digcmd_args 1>&2 56 $DIG $digcmd_args 57} 58 59# set DIGNM=file name for dig output 60GROUP_NM= 61TEST_NUM=0 62make_dignm () { 63 TEST_NUM=`expr $TEST_NUM + 1` 64 DIGNM=dig.out$GROUP_NM-$TEST_NUM 65 while test -f $DIGNM; do 66 TEST_NUM="$TEST_NUM+" 67 DIGNM=dig.out$GROUP_NM-$TEST_NUM 68 done 69} 70 71setret () { 72 ret=1 73 echo "$*" 74} 75 76# (re)load the reponse policy zones with the rules in the file $TEST_FILE 77load_db () { 78 if test -n "$TEST_FILE"; then 79 if $NSUPDATE -v $TEST_FILE; then : ; else 80 echo "I:failed to update policy zone with $TEST_FILE" 81 exit 1 82 fi 83 fi 84} 85 86restart () { 87 # try to ensure that the server really has stopped 88 # and won't mess with ns$1/name.pid 89 if test -z "$HAVE_CORE" -a -f ns$1/named.pid; then 90 $RNDCCMD $ns$1 halt >/dev/null 2>&1 91 if test -f ns$1/named.pid; then 92 sleep 1 93 PID=`cat ns$1/named.pid 2>/dev/null` 94 if test -n "$PID"; then 95 echo "I:killing ns$1 server $PID" 96 kill -9 $PID 97 fi 98 fi 99 fi 100 rm -f ns$1/*.jnl 101 if test -f ns$1/base.db; then 102 for NM in ns$1/bl*.db; do 103 cp -f ns$1/base.db $NM 104 done 105 fi 106 $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns$1 107 load_db 108} 109 110# $1=server and irrelevant args $2=error message 111ckalive () { 112 CKALIVE_NS=`expr "$1" : '.*@ns\([1-9]\).*'` 113 if test -z "$CKALIVE_NS"; then 114 CKALIVE_NS=3 115 fi 116 eval CKALIVE_IP=\$ns$CKALIVE_NS 117 $RNDCCMD $CKALIVE_IP status >/dev/null 2>&1 && return 0 118 HAVE_CORE=yes 119 setret "$2" 120 # restart the server to avoid stalling waiting for it to stop 121 restart $CKALIVE_NS 122 return 1 123} 124 125# $1=message $2=optional test file name 126start_group () { 127 ret=0 128 test -n "$1" && echo "I:checking $1" 129 TEST_FILE=$2 130 if test -n "$TEST_FILE"; then 131 GROUP_NM="-$TEST_FILE" 132 load_db 133 else 134 GROUP_NM= 135 fi 136 TEST_NUM=0 137} 138 139end_group () { 140 if test -n "$TEST_FILE"; then 141 sed -e 's/[ ]add[ ]/ delete /' $TEST_FILE | $NSUPDATE 142 TEST_FILE= 143 fi 144 ckalive $ns3 "I:failed; ns3 server crashed and restarted" 145 if test "$status" -eq 0; then 146 # look for complaints from rpz.c 147 EMSGS=`grep -l 'invalid rpz' */*.run` 148 if test -n "$EMSGS"; then 149 setret "I:'invalid rpz' complaints in $EMSGS starting with:" 150 grep 'invalid rpz' */*.run | sed -e '4,$d' -e 's/^/I: /' 151 fi 152 # look for complaints from rpz.c and query.c 153 EMSGS=`grep -l 'rpz .*failed' */*.run` 154 if test -n "$EMSGS"; then 155 setret "I:'rpz failed' complaints in $EMSGS starting with:" 156 grep 'rpz .*failed' */*.run | sed -e '4,$d' -e 's/^/I: /' 157 fi 158 fi 159 status=`expr $status + $ret` 160 GROUP_NM= 161} 162 163# $1=dig args $2=other dig output file 164ckresult () { 165 #ckalive "$1" "I:server crashed by 'dig $1'" || return 1 166 if $PERL $SYSTEMTESTTOP/digcomp.pl $DIGNM $2 >/dev/null; then 167 rm -f ${DIGNM}* 168 return 0 169 fi 170 setret "I:'dig $1' wrong; diff $DIGNM $2" 171 return 1 172} 173 174# check only that the server does not crash 175# $1=target domain $2=optional query type 176nocrash () { 177 digcmd $* >/dev/null 178 ckalive "$*" "I:server crashed by 'dig $*'" 179} 180 181 182# check rewrite to NXDOMAIN 183# $1=target domain $2=optional query type 184nxdomain () { 185 make_dignm 186 digcmd $* \ 187 | sed -e 's/^[a-z].* IN CNAME /;xxx &/' \ 188 -e 's/^[a-z].* IN RRSIG /;xxx &/' \ 189 >$DIGNM 190 ckresult "$*" proto.nxdomain 191} 192 193# check rewrite to NODATA 194# $1=target domain $2=optional query type 195nodata () { 196 make_dignm 197 digcmd $* \ 198 | sed -e 's/^[a-z].* IN CNAME /;xxx &/' >$DIGNM 199 ckresult "$*" proto.nodata 200} 201 202# check rewrite to an address 203# modify the output so that it is easily compared, but save the original line 204# $1=IPv4 address $2=digcmd args $3=optional TTL 205addr () { 206 ADDR=$1 207 make_dignm 208 digcmd $2 >$DIGNM 209 #ckalive "$2" "I:server crashed by 'dig $2'" || return 1 210 ADDR_ESC=`echo "$ADDR" | sed -e 's/\./\\\\./g'` 211 ADDR_TTL=`sed -n -e "s/^[-.a-z0-9]\{1,\} *\([0-9]*\) IN A\{1,4\} ${ADDR_ESC}\$/\1/p" $DIGNM` 212 if test -z "$ADDR_TTL"; then 213 setret "I:'dig $2' wrong; no address $ADDR record in $DIGNM" 214 return 1 215 fi 216 if test -n "$3" && test "$ADDR_TTL" -ne "$3"; then 217 setret "I:'dig $2' wrong; TTL=$ADDR_TTL instead of $3 in $DIGNM" 218 return 1 219 fi 220 rm -f ${DIGNM}* 221} 222 223# check that a response is not rewritten 224# $1=target domain $2=optional query type 225nochange () { 226 make_dignm 227 digcmd $* >$DIGNM 228 digcmd $* @$ns2 >${DIGNM}_OK 229 ckresult "$*" ${DIGNM}_OK && rm -f ${DIGNM}_OK 230} 231 232# check against a 'here document' 233here () { 234 make_dignm 235 sed -e 's/^[ ]*//' >${DIGNM}_OK 236 digcmd $* >$DIGNM 237 ckresult "$*" ${DIGNM}_OK 238} 239 240# make prototype files to check against rewritten results 241digcmd nonexistent @$ns2 >proto.nxdomain 242digcmd txt-only.tld2 @$ns2 >proto.nodata 243 244 245status=0 246 247start_group "QNAME rewrites" test1 248nochange . # 1 do not crash or rewrite root 249nxdomain a0-1.tld2 # 2 250nodata a3-1.tld2 # 3 251nodata a3-2.tld2 # 4 no crash on DNAME 252nodata sub.a3-2.tld2 253nxdomain a4-2.tld2 # 6 rewrite based on CNAME target 254nxdomain a4-2-cname.tld2 # 7 255nodata a4-3-cname.tld2 # 8 256addr 12.12.12.12 a4-1.sub1.tld2 # 9 A replacement 257addr 12.12.12.12 a4-1.sub2.tld2 # 10 A replacement with wildcard 258addr 12.12.12.12 nxc1.sub1.tld2 # 11 replace NXDOMAIN with CNAME 259addr 12.12.12.12 nxc2.sub1.tld2 # 12 replace NXDOMAIN with CNAME chain 260addr 127.4.4.1 a4-4.tld2 # 13 prefer 1st conflicting QNAME zone 261nochange a6-1.tld2 # 14 262addr 127.6.2.1 a6-2.tld2 # 15 263addr 56.56.56.56 a3-6.tld2 # 16 wildcard CNAME 264addr 57.57.57.57 a3-7.sub1.tld2 # 17 wildcard CNAME 265addr 127.0.0.16 a4-5-cname3.tld2 # 18 CNAME chain 266addr 127.0.0.17 a4-6-cname3.tld2 # 19 stop short in CNAME chain 267nochange a0-1.tld2 +norecurse # 20 check that RD=1 is required 268nochange a3-1.tld2 +norecurse # 21 269nochange a3-2.tld2 +norecurse # 22 270nochange sub.a3-2.tld2 +norecurse # 23 271nxdomain c1.crash2.tld3 # 24 assert in rbtdb.c 272nxdomain a0-1.tld2 +dnssec # 25 simple DO=1 without signatures 273nxdomain a0-1.tld2s # 26 simple DO=0 with signatures 274nochange a0-1.tld2s +dnssec # 27 simple DO=1 with signatures 275nxdomain a0-1s-cname.tld2s +dnssec # 28 DNSSEC too early in CNAME chain 276nochange a0-1-scname.tld2 +dnssec # 29 DNSSEC on target in CNAME chain 277nochange a0-1.tld2s srv +auth +dnssec # 30 no write for +DNSSEC and no record 278nxdomain a0-1.tld2s srv # 31 279end_group 280 281start_group "IP rewrites" test2 282nodata a3-1.tld2 # 1 NODATA 283nochange a3-2.tld2 # 2 no policy record so no change 284nochange a4-1.tld2 # 3 obsolete PASSTHRU record style 285nxdomain a4-2.tld2 # 4 286nochange a4-2.tld2 -taaaa # 5 no A => no policy rewrite 287nochange a4-2.tld2 -ttxt # 6 no A => no policy rewrite 288nxdomain a4-2.tld2 -tany # 7 no A => no policy rewrite 289nodata a4-3.tld2 # 8 290nxdomain a3-1.tld2 -taaaa # 9 IPv6 policy 291nochange a4-1-aaaa.tld2 -taaaa # 10 292addr 127.0.0.1 a5-1-2.tld2 # 11 prefer smallest policy address 293addr 127.0.0.1 a5-3.tld2 # 12 prefer first conflicting IP zone 294addr 14.14.14.14 a5-4.tld2 # 13 prefer QNAME to IP 295nochange a5-4.tld2 +norecurse # 14 check that RD=1 is required 296nochange a4-4.tld2 # 15 PASSTHRU 297nxdomain c2.crash2.tld3 # 16 assert in rbtdb.c 298end_group 299 300# check that IP addresses for previous group were deleted from the radix tree 301start_group "radix tree deletions" 302nochange a3-1.tld2 303nochange a3-2.tld2 304nochange a4-1.tld2 305nochange a4-2.tld2 306nochange a4-2.tld2 -taaaa 307nochange a4-2.tld2 -ttxt 308nochange a4-2.tld2 -tany 309nochange a4-3.tld2 310nochange a3-1.tld2 -tAAAA 311nochange a4-1-aaaa.tld2 -tAAAA 312nochange a5-1-2.tld2 313end_group 314 315if ./rpz nsdname; then 316 start_group "NSDNAME rewrites" test3 317 nochange a3-1.tld2 318 nochange a3-1.tld2 +dnssec # 2 this once caused problems 319 nxdomain a3-1.sub1.tld2 # 3 NXDOMAIN *.sub1.tld2 by NSDNAME 320 nxdomain a3-1.subsub.sub1.tld2 321 nxdomain a3-1.subsub.sub1.tld2 -tany 322 addr 12.12.12.12 a4-2.subsub.sub2.tld2 # 6 walled garden for *.sub2.tld2 323 nochange a3-2.tld2. # 7 exempt rewrite by name 324 nochange a0-1.tld2. # 8 exempt rewrite by address block 325 addr 12.12.12.12 a4-1.tld2 # 9 prefer QNAME policy to NSDNAME 326 addr 127.0.0.1 a3-1.sub3.tld2 # 10 prefer policy for largest NSDNAME 327 addr 127.0.0.2 a3-1.subsub.sub3.tld2 328 nxdomain xxx.crash1.tld2 # 12 dns_db_detachnode() crash 329 end_group 330else 331 echo "I:NSDNAME not checked; named not configured with --enable-rpz-nsdname" 332fi 333 334if ./rpz nsip; then 335 start_group "NSIP rewrites" test4 336 nxdomain a3-1.tld2 # 1 NXDOMAIN for all of tld2 by NSIP 337 nochange a3-2.tld2. # 2 exempt rewrite by name 338 nochange a0-1.tld2. # 3 exempt rewrite by address block 339 nochange a3-1.tld4 # 4 different NS IP address 340 end_group 341else 342 echo "I:NSIP not checked; named not configured with --enable-rpz-nsip" 343fi 344 345# policies in ./test5 overridden by response-policy{} in ns3/named.conf 346# and in ns5/named.conf 347start_group "policy overrides" test5 348addr 127.0.0.1 a3-1.tld2 # 1 bl-given 349nochange a3-2.tld2 # 2 bl-passthru 350nochange a3-3.tld2 # 3 bl-no-op obsolete for passthru 351nochange a3-4.tld2 # 4 bl-disabled 352nodata a3-5.tld2 # 5 bl-nodata 353nodata a3-5.tld2 +norecurse # 6 bl-nodata recursive-only no 354nodata a3-5.tld2 # 7 bl-nodata 355nodata a3-5.tld2 +norecurse @$ns5 # 8 bl-nodata recursive-only no 356nodata a3-5.tld2s @$ns5 # 9 bl-nodata 357nodata a3-5.tld2s +dnssec @$ns5 # 10 bl-nodata break-dnssec 358nxdomain a3-6.tld2 # 11 bl-nxdomain 359here a3-7.tld2 -tany <<'EOF' 360 ;; status: NOERROR, x 361 a3-7.tld2. x IN CNAME txt-only.tld2. 362 txt-only.tld2. x IN TXT "txt-only-tld2" 363EOF 364addr 58.58.58.58 a3-8.tld2 # 13 bl_wildcname 365addr 59.59.59.59 a3-9.sub9.tld2 # 14 bl_wildcname 366addr 12.12.12.12 a3-15.tld2 # 15 bl-garden via CNAME to a12.tld2 367addr 127.0.0.16 a3-16.tld2 100 # 16 bl max-policy-ttl 100 368addr 17.17.17.17 "a3-17.tld2 @$ns5" 90 # 17 ns5 bl max-policy-ttl 90 369end_group 370 371# check that miscellaneous bugs are still absent 372start_group "crashes" 373for Q in RRSIG SIG ANY 'ANY +dnssec'; do 374 nocrash a3-1.tld2 -t$Q 375 nocrash a3-2.tld2 -t$Q 376 nocrash a3-5.tld2 -t$Q 377 nocrash www.redirect -t$Q 378 nocrash www.credirect -t$Q 379done 380end_group 381 382 383# superficial test for major performance bugs 384QPERF=`sh qperf.sh` 385if test -n "$QPERF"; then 386 perf () { 387 echo "I:checking performance $1" 388 # don't measure the costs of -d99 389 $RNDCCMD $ns5 notrace >/dev/null 390 $QPERF -1 -l2 -d ns5/requests -s $ns5 -p 5300 >ns5/$2.perf 391 ckalive $ns5 "I:failed; server #5 crashed" 392 } 393 trim () { 394 sed -n -e 's/.*Queries per second: *\([0-9]*\).*/\1/p' ns5/$1.perf 395 } 396 397 # Dry run to prime disk cache 398 # Otherwise a first test of either flavor is 25% low 399 perf 'to prime disk cache' rpz 400 401 # get queries/second with rpz 402 perf 'with rpz' rpz 403 404 # turn off rpz and measure queries/second again 405 # Don't wait for a clean stop. Clean stops of this server need seconds 406 # until the sockets are closed. 5 or 10 seconds after that, the 407 # server really stops and deletes named.pid. 408 echo "# rpz off" >ns5/rpz-switch 409 PID=`cat ns5/named.pid` 410 test -z "$PID" || kill -9 "$PID" 411 $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns5 412 perf 'without rpz' norpz 413 414 # Don't wait for a clean stop. Clean stops of this server need seconds 415 # until the sockets are closed. 5 or 10 seconds after that, the 416 # server really stops and deletes named.pid. 417 echo "# rpz off" >ns5/rpz-switch 418 PID=`cat ns5/named.pid` 419 test -z "$PID" || kill -9 "$PID" && rm -f ns5/named.pid 420 421 NORPZ=`trim norpz` 422 RPZ=`trim rpz` 423 echo "I:$RPZ qps with RPZ versus $NORPZ qps without" 424 425 # fail if RPZ costs more than 100% 426 NORPZ2=`expr "$NORPZ" / 2` 427 if test "$RPZ" -le "$NORPZ2"; then 428 echo "I:rpz $RPZ qps too far below non-RPZ $NORPZ qps" 429 status=`expr $status + 1` 430 fi 431else 432 echo "I:performance not checked; queryperf not available" 433fi 434 435 436# restart the main test RPZ server to see if that creates a core file 437if test -z "$HAVE_CORE"; then 438 $PERL $SYSTEMTESTTOP/stop.pl . ns3 439 restart 3 440 HAVE_CORE=`find ns* -name '*core*' -print` 441 test -z "$HAVE_CORE" || setret "I:found $HAVE_CORE; memory leak?" 442fi 443 444 445echo "I:exit status: $status" 446exit $status 447