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 14set -e 15 16# shellcheck source=../conf.sh 17. ../conf.sh 18 19dig_with_opts() { 20 "${DIG}" -p "${PORT}" "${@}" 21} 22 23resolve_with_opts() { 24 "${RESOLVE}" -p "${PORT}" "${@}" 25} 26 27rndccmd() { 28 "${RNDC}" -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${@}" 29} 30 31status=0 32n=0 33 34n=$((n + 1)) 35echo_i "checking non-cachable NXDOMAIN response handling ($n)" 36ret=0 37dig_with_opts +tcp nxdomain.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 38grep "status: NXDOMAIN" dig.out.ns1.test${n} >/dev/null || ret=1 39if [ $ret != 0 ]; then echo_i "failed"; fi 40status=$((status + ret)) 41 42if [ -x "${RESOLVE}" ]; then 43 n=$((n + 1)) 44 echo_i "checking non-cachable NXDOMAIN response handling using dns_client ($n)" 45 ret=0 46 resolve_with_opts -t a -s 10.53.0.1 nxdomain.example.net 2>resolve.out.ns1.test${n} || ret=1 47 grep "resolution failed: ncache nxdomain" resolve.out.ns1.test${n} >/dev/null || ret=1 48 if [ $ret != 0 ]; then echo_i "failed"; fi 49 status=$((status + ret)) 50fi 51 52if [ -x "${RESOLVE}" ]; then 53 n=$((n + 1)) 54 echo_i "checking that local bound address can be set (Can't query from a denied address) ($n)" 55 ret=0 56 resolve_with_opts -b 10.53.0.8 -t a -s 10.53.0.1 www.example.org 2>resolve.out.ns1.test${n} || ret=1 57 grep "resolution failed: SERVFAIL" resolve.out.ns1.test${n} >/dev/null || ret=1 58 if [ $ret != 0 ]; then echo_i "failed"; fi 59 status=$((status + ret)) 60 61 n=$((n + 1)) 62 echo_i "checking that local bound address can be set (Can query from an allowed address) ($n)" 63 ret=0 64 resolve_with_opts -b 10.53.0.1 -t a -s 10.53.0.1 www.example.org >resolve.out.ns1.test${n} || ret=1 65 grep "www.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 66 if [ $ret != 0 ]; then echo_i "failed"; fi 67 status=$((status + ret)) 68fi 69 70n=$((n + 1)) 71echo_i "checking non-cachable NODATA response handling ($n)" 72ret=0 73dig_with_opts +tcp nodata.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 74grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 75if [ $ret != 0 ]; then echo_i "failed"; fi 76status=$((status + ret)) 77 78if [ -x "${RESOLVE}" ]; then 79 n=$((n + 1)) 80 echo_i "checking non-cachable NODATA response handling using dns_client ($n)" 81 ret=0 82 resolve_with_opts -t a -s 10.53.0.1 nodata.example.net 2>resolve.out.ns1.test${n} || ret=1 83 grep "resolution failed: ncache nxrrset" resolve.out.ns1.test${n} >/dev/null || ret=1 84 if [ $ret != 0 ]; then echo_i "failed"; fi 85 status=$((status + ret)) 86fi 87 88n=$((n + 1)) 89echo_i "checking handling of bogus referrals ($n)" 90# If the server has the "INSIST(!external)" bug, this query will kill it. 91dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { 92 echo_i "failed" 93 status=$((status + 1)) 94} 95 96if [ -x "${RESOLVE}" ]; then 97 n=$((n + 1)) 98 echo_i "checking handling of bogus referrals using dns_client ($n)" 99 ret=0 100 resolve_with_opts -t a -s 10.53.0.1 www.example.com 2>resolve.out.ns1.test${n} || ret=1 101 grep "resolution failed: SERVFAIL" resolve.out.ns1.test${n} >/dev/null || ret=1 102 if [ $ret != 0 ]; then echo_i "failed"; fi 103 status=$((status + ret)) 104fi 105 106n=$((n + 1)) 107echo_i "check handling of cname + other data / 1 ($n)" 108dig_with_opts +tcp cname1.example.com. a @10.53.0.1 >/dev/null || { 109 echo_i "failed" 110 status=$((status + 1)) 111} 112 113n=$((n + 1)) 114echo_i "check handling of cname + other data / 2 ($n)" 115dig_with_opts +tcp cname2.example.com. a @10.53.0.1 >/dev/null || { 116 echo_i "failed" 117 status=$((status + 1)) 118} 119 120n=$((n + 1)) 121echo_i "check that server is still running ($n)" 122dig_with_opts +tcp www.example.com. a @10.53.0.1 >/dev/null || { 123 echo_i "failed" 124 status=$((status + 1)) 125} 126 127n=$((n + 1)) 128echo_i "checking answer IPv4 address filtering (deny) ($n)" 129ret=0 130dig_with_opts +tcp www.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 131grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 132if [ $ret != 0 ]; then echo_i "failed"; fi 133status=$((status + ret)) 134 135n=$((n + 1)) 136echo_i "checking answer IPv6 address filtering (deny) ($n)" 137ret=0 138dig_with_opts +tcp www.example.net @10.53.0.1 aaaa >dig.out.ns1.test${n} || ret=1 139grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 140if [ $ret != 0 ]; then echo_i "failed"; fi 141status=$((status + ret)) 142 143n=$((n + 1)) 144echo_i "checking answer IPv4 address filtering (accept) ($n)" 145ret=0 146dig_with_opts +tcp www.example.org @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 147grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 148if [ $ret != 0 ]; then echo_i "failed"; fi 149status=$((status + ret)) 150 151if [ -x "${RESOLVE}" ]; then 152 n=$((n + 1)) 153 echo_i "checking answer IPv4 address filtering using dns_client (accept) ($n)" 154 ret=0 155 resolve_with_opts -t a -s 10.53.0.1 www.example.org >resolve.out.ns1.test${n} || ret=1 156 grep "www.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 157 if [ $ret != 0 ]; then echo_i "failed"; fi 158 status=$((status + ret)) 159fi 160 161n=$((n + 1)) 162echo_i "checking answer IPv6 address filtering (accept) ($n)" 163ret=0 164dig_with_opts +tcp www.example.org @10.53.0.1 aaaa >dig.out.ns1.test${n} || ret=1 165grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 166if [ $ret != 0 ]; then echo_i "failed"; fi 167status=$((status + ret)) 168 169if [ -x "${RESOLVE}" ]; then 170 n=$((n + 1)) 171 echo_i "checking answer IPv6 address filtering using dns_client (accept) ($n)" 172 ret=0 173 resolve_with_opts -t aaaa -s 10.53.0.1 www.example.org >resolve.out.ns1.test${n} || ret=1 174 grep "www.example.org..*.2001:db8:beef::1" resolve.out.ns1.test${n} >/dev/null || ret=1 175 if [ $ret != 0 ]; then echo_i "failed"; fi 176 status=$((status + ret)) 177fi 178 179n=$((n + 1)) 180echo_i "checking CNAME target filtering (deny) ($n)" 181ret=0 182dig_with_opts +tcp badcname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 183grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 184if [ $ret != 0 ]; then echo_i "failed"; fi 185status=$((status + ret)) 186 187n=$((n + 1)) 188echo_i "checking CNAME target filtering (accept) ($n)" 189ret=0 190dig_with_opts +tcp goodcname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 191grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 192if [ $ret != 0 ]; then echo_i "failed"; fi 193status=$((status + ret)) 194 195if [ -x "${RESOLVE}" ]; then 196 n=$((n + 1)) 197 echo_i "checking CNAME target filtering using dns_client (accept) ($n)" 198 ret=0 199 resolve_with_opts -t a -s 10.53.0.1 goodcname.example.net >resolve.out.ns1.test${n} || ret=1 200 grep "goodcname.example.net..*.goodcname.example.org." resolve.out.ns1.test${n} >/dev/null || ret=1 201 grep "goodcname.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 202 if [ $ret != 0 ]; then echo_i "failed"; fi 203 status=$((status + ret)) 204fi 205 206n=$((n + 1)) 207echo_i "checking CNAME target filtering (accept due to subdomain) ($n)" 208ret=0 209dig_with_opts +tcp cname.sub.example.org @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 210grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 211if [ $ret != 0 ]; then echo_i "failed"; fi 212status=$((status + ret)) 213 214if [ -x "${RESOLVE}" ]; then 215 n=$((n + 1)) 216 echo_i "checking CNAME target filtering using dns_client (accept due to subdomain) ($n)" 217 ret=0 218 resolve_with_opts -t a -s 10.53.0.1 cname.sub.example.org >resolve.out.ns1.test${n} || ret=1 219 grep "cname.sub.example.org..*.ok.sub.example.org." resolve.out.ns1.test${n} >/dev/null || ret=1 220 grep "ok.sub.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 221 if [ $ret != 0 ]; then echo_i "failed"; fi 222 status=$((status + ret)) 223fi 224 225n=$((n + 1)) 226echo_i "checking DNAME target filtering (deny) ($n)" 227ret=0 228dig_with_opts +tcp foo.baddname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 229grep "DNAME target foo.baddname.example.org denied for foo.baddname.example.net/IN" ns1/named.run >/dev/null || ret=1 230grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 231if [ $ret != 0 ]; then echo_i "failed"; fi 232status=$((status + ret)) 233 234n=$((n + 1)) 235echo_i "checking DNAME target filtering (accept) ($n)" 236ret=0 237dig_with_opts +tcp foo.gooddname.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 238grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 239if [ $ret != 0 ]; then echo_i "failed"; fi 240status=$((status + ret)) 241 242if [ -x "${RESOLVE}" ]; then 243 n=$((n + 1)) 244 echo_i "checking DNAME target filtering using dns_client (accept) ($n)" 245 ret=0 246 resolve_with_opts -t a -s 10.53.0.1 foo.gooddname.example.net >resolve.out.ns1.test${n} || ret=1 247 grep "foo.gooddname.example.net..*.gooddname.example.org" resolve.out.ns1.test${n} >/dev/null || ret=1 248 grep "foo.gooddname.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 249 if [ $ret != 0 ]; then echo_i "failed"; fi 250 status=$((status + ret)) 251fi 252 253n=$((n + 1)) 254echo_i "checking DNAME target filtering (accept due to subdomain) ($n)" 255ret=0 256dig_with_opts +tcp www.dname.sub.example.org @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 257grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 258if [ $ret != 0 ]; then echo_i "failed"; fi 259status=$((status + ret)) 260 261if [ -x "${RESOLVE}" ]; then 262 n=$((n + 1)) 263 echo_i "checking DNAME target filtering using dns_client (accept due to subdomain) ($n)" 264 ret=0 265 resolve_with_opts -t a -s 10.53.0.1 www.dname.sub.example.org >resolve.out.ns1.test${n} || ret=1 266 grep "www.dname.sub.example.org..*.ok.sub.example.org." resolve.out.ns1.test${n} >/dev/null || ret=1 267 grep "www.ok.sub.example.org..*.192.0.2.1" resolve.out.ns1.test${n} >/dev/null || ret=1 268 if [ $ret != 0 ]; then echo_i "failed"; fi 269 status=$((status + ret)) 270fi 271 272n=$((n + 1)) 273echo_i "check that the resolver accepts a referral response with a non-empty ANSWER section ($n)" 274ret=0 275dig_with_opts @10.53.0.1 foo.glue-in-answer.example.org. A >dig.ns1.out.${n} || ret=1 276grep "status: NOERROR" dig.ns1.out.${n} >/dev/null || ret=1 277grep "foo.glue-in-answer.example.org.*192.0.2.1" dig.ns1.out.${n} >/dev/null || ret=1 278if [ $ret != 0 ]; then echo_i "failed"; fi 279status=$((status + ret)) 280 281n=$((n + 1)) 282echo_i "check that the resolver limits the number of NS records it follows in a referral response ($n)" 283# ns5 is the recusor being tested. ns4 holds the sourcens zone containing 284# names with varying numbers of NS records pointing to non-existent 285# nameservers in the targetns zone on ns6. 286ret=0 287rndccmd 10.53.0.5 flush || ret=1 # Ensure cache is empty before doing this test 288count_fetches() { 289 actual=$(nextpartpeek ns5/named.run | grep -c " fetch: ns.fake${nscount}") 290 [ "${actual:-0}" -eq "${expected}" ] || return 1 291 return 0 292} 293for nscount in 1 2 3 4 5 6 7 8 9 10; do 294 # Verify number of NS records at source server 295 dig_with_opts +norecurse @10.53.0.4 target${nscount}.sourcens ns >dig.ns4.out.${nscount}.${n} 296 sourcerecs=$(grep NS dig.ns4.out.${nscount}.${n} | grep -cv ';') 297 test "${sourcerecs}" -eq "${nscount}" || ret=1 298 test "${sourcerecs}" -eq "${nscount}" || echo_i "NS count incorrect for target${nscount}.sourcens" 299 300 # Expected queries = 2 * number of NS records, up to a maximum of 10. 301 expected=$((nscount * 2)) 302 if [ "$expected" -gt 10 ]; then expected=10; fi 303 # Count the number of logged fetches 304 nextpart ns5/named.run >/dev/null 305 dig_with_opts @10.53.0.5 target${nscount}.sourcens A >dig.ns5.out.${nscount}.${n} || ret=1 306 retry_quiet 5 count_fetches ns5/named.run $nscount $expected || { 307 echo_i "query count error: $nscount NS records: expected queries $expected, actual $actual" 308 ret=1 309 } 310done 311if [ $ret != 0 ]; then echo_i "failed"; fi 312status=$((status + ret)) 313 314n=$((n + 1)) 315echo_i "RT21594 regression test check setup ($n)" 316ret=0 317# Check that "aa" is not being set by the authoritative server. 318dig_with_opts +tcp . @10.53.0.4 soa >dig.ns4.out.${n} || ret=1 319grep 'flags: qr rd;' dig.ns4.out.${n} >/dev/null || ret=1 320if [ $ret != 0 ]; then echo_i "failed"; fi 321status=$((status + ret)) 322 323n=$((n + 1)) 324echo_i "RT21594 regression test positive answers ($n)" 325ret=0 326# Check that resolver accepts the non-authoritative positive answers. 327dig_with_opts +tcp . @10.53.0.5 soa >dig.ns5.out.${n} || ret=1 328grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 329if [ $ret != 0 ]; then echo_i "failed"; fi 330status=$((status + ret)) 331 332n=$((n + 1)) 333echo_i "RT21594 regression test NODATA answers ($n)" 334ret=0 335# Check that resolver accepts the non-authoritative nodata answers. 336dig_with_opts +tcp . @10.53.0.5 txt >dig.ns5.out.${n} || ret=1 337grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 338if [ $ret != 0 ]; then echo_i "failed"; fi 339status=$((status + ret)) 340 341n=$((n + 1)) 342echo_i "RT21594 regression test NXDOMAIN answers ($n)" 343ret=0 344# Check that resolver accepts the non-authoritative positive answers. 345dig_with_opts +tcp noexistent @10.53.0.5 txt >dig.ns5.out.${n} || ret=1 346grep "status: NXDOMAIN" dig.ns5.out.${n} >/dev/null || ret=1 347if [ $ret != 0 ]; then echo_i "failed"; fi 348status=$((status + ret)) 349 350n=$((n + 1)) 351echo_i "check that replacement of additional data by a negative cache no data entry clears the additional RRSIGs ($n)" 352ret=0 353dig_with_opts +tcp mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=1 354grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=1 355if [ $ret = 1 ]; then echo_i "mx priming failed"; fi 356$NSUPDATE <<EOF 357server 10.53.0.6 ${PORT} 358zone example.net 359update delete mail.example.net A 360update add mail.example.net 0 AAAA ::1 361send 362EOF 363dig_with_opts +tcp a mail.example.net @10.53.0.7 >dig.ns7.out.${n} || ret=2 364grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=2 365grep "ANSWER: 0" dig.ns7.out.${n} >/dev/null || ret=2 366if [ $ret = 2 ]; then echo_i "ncache priming failed"; fi 367dig_with_opts +tcp mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=3 368grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=3 369dig_with_opts +tcp rrsig mail.example.net +norec @10.53.0.7 >dig.ns7.out.${n} || ret=4 370grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=4 371grep "ANSWER: 0" dig.ns7.out.${n} >/dev/null || ret=4 372if [ $ret != 0 ]; then 373 echo_i "failed" 374 ret=1 375fi 376status=$((status + ret)) 377 378if [ $ret != 0 ]; then 379 echo_i "failed" 380 ret=1 381fi 382status=$((status + ret)) 383 384n=$((n + 1)) 385echo_i "checking that update a nameservers address has immediate effects ($n)" 386ret=0 387dig_with_opts +tcp TXT foo.moves @10.53.0.7 >dig.ns7.foo.${n} || ret=1 388grep "From NS 5" dig.ns7.foo.${n} >/dev/null || ret=1 389$NSUPDATE <<EOF 390server 10.53.0.7 ${PORT} 391zone server 392update delete ns.server A 393update add ns.server 300 A 10.53.0.4 394send 395EOF 396sleep 1 397dig_with_opts +tcp TXT bar.moves @10.53.0.7 >dig.ns7.bar.${n} || ret=1 398grep "From NS 4" dig.ns7.bar.${n} >/dev/null || ret=1 399 400if [ $ret != 0 ]; then 401 echo_i "failed" 402 status=1 403fi 404 405n=$((n + 1)) 406echo_i "checking that update a nameservers glue has immediate effects ($n)" 407ret=0 408dig_with_opts +tcp TXT foo.child.server @10.53.0.7 >dig.ns7.foo.${n} || ret=1 409grep "From NS 5" dig.ns7.foo.${n} >/dev/null || ret=1 410$NSUPDATE <<EOF 411server 10.53.0.7 ${PORT} 412zone server 413update delete ns.child.server A 414update add ns.child.server 300 A 10.53.0.4 415send 416EOF 417sleep 1 418dig_with_opts +tcp TXT bar.child.server @10.53.0.7 >dig.ns7.bar.${n} || ret=1 419grep "From NS 4" dig.ns7.bar.${n} >/dev/null || ret=1 420 421if [ $ret != 0 ]; then 422 echo_i "failed" 423 status=1 424fi 425 426n=$((n + 1)) 427echo_i "checking empty RFC 1918 reverse zones ($n)" 428ret=0 429# Check that "aa" is being set by the resolver for RFC 1918 zones 430# except the one that has been deliberately disabled 431dig_with_opts @10.53.0.7 -x 10.1.1.1 >dig.ns4.out.1.${n} || ret=1 432grep 'flags: qr aa rd ra;' dig.ns4.out.1.${n} >/dev/null || ret=1 433dig_with_opts @10.53.0.7 -x 192.168.1.1 >dig.ns4.out.2.${n} || ret=1 434grep 'flags: qr aa rd ra;' dig.ns4.out.2.${n} >/dev/null || ret=1 435dig_with_opts @10.53.0.7 -x 172.16.1.1 >dig.ns4.out.3.${n} || ret=1 436grep 'flags: qr aa rd ra;' dig.ns4.out.3.${n} >/dev/null || ret=1 437dig_with_opts @10.53.0.7 -x 172.17.1.1 >dig.ns4.out.4.${n} || ret=1 438grep 'flags: qr aa rd ra;' dig.ns4.out.4.${n} >/dev/null || ret=1 439dig_with_opts @10.53.0.7 -x 172.18.1.1 >dig.ns4.out.5.${n} || ret=1 440grep 'flags: qr aa rd ra;' dig.ns4.out.5.${n} >/dev/null || ret=1 441dig_with_opts @10.53.0.7 -x 172.19.1.1 >dig.ns4.out.6.${n} || ret=1 442grep 'flags: qr aa rd ra;' dig.ns4.out.6.${n} >/dev/null || ret=1 443dig_with_opts @10.53.0.7 -x 172.21.1.1 >dig.ns4.out.7.${n} || ret=1 444grep 'flags: qr aa rd ra;' dig.ns4.out.7.${n} >/dev/null || ret=1 445dig_with_opts @10.53.0.7 -x 172.22.1.1 >dig.ns4.out.8.${n} || ret=1 446grep 'flags: qr aa rd ra;' dig.ns4.out.8.${n} >/dev/null || ret=1 447dig_with_opts @10.53.0.7 -x 172.23.1.1 >dig.ns4.out.9.${n} || ret=1 448grep 'flags: qr aa rd ra;' dig.ns4.out.9.${n} >/dev/null || ret=1 449dig_with_opts @10.53.0.7 -x 172.24.1.1 >dig.ns4.out.11.${n} || ret=1 450grep 'flags: qr aa rd ra;' dig.ns4.out.11.${n} >/dev/null || ret=1 451dig_with_opts @10.53.0.7 -x 172.25.1.1 >dig.ns4.out.12.${n} || ret=1 452grep 'flags: qr aa rd ra;' dig.ns4.out.12.${n} >/dev/null || ret=1 453dig_with_opts @10.53.0.7 -x 172.26.1.1 >dig.ns4.out.13.${n} || ret=1 454grep 'flags: qr aa rd ra;' dig.ns4.out.13.${n} >/dev/null || ret=1 455dig_with_opts @10.53.0.7 -x 172.27.1.1 >dig.ns4.out.14.${n} || ret=1 456grep 'flags: qr aa rd ra;' dig.ns4.out.14.${n} >/dev/null || ret=1 457dig_with_opts @10.53.0.7 -x 172.28.1.1 >dig.ns4.out.15.${n} || ret=1 458grep 'flags: qr aa rd ra;' dig.ns4.out.15.${n} >/dev/null || ret=1 459dig_with_opts @10.53.0.7 -x 172.29.1.1 >dig.ns4.out.16.${n} || ret=1 460grep 'flags: qr aa rd ra;' dig.ns4.out.16.${n} >/dev/null || ret=1 461dig_with_opts @10.53.0.7 -x 172.30.1.1 >dig.ns4.out.17.${n} || ret=1 462grep 'flags: qr aa rd ra;' dig.ns4.out.17.${n} >/dev/null || ret=1 463dig_with_opts @10.53.0.7 -x 172.31.1.1 >dig.ns4.out.18.${n} || ret=1 464grep 'flags: qr aa rd ra;' dig.ns4.out.18.${n} >/dev/null || ret=1 465# but this one should NOT be authoritative 466dig_with_opts @10.53.0.7 -x 172.20.1.1 >dig.ns4.out.19.${n} || ret=1 467grep 'flags: qr rd ra;' dig.ns4.out.19.${n} >/dev/null || ret=1 468if [ $ret != 0 ]; then 469 echo_i "failed" 470 status=1 471fi 472 473n=$((n + 1)) 474echo_i "checking that removal of a delegation is honoured ($n)" 475ret=0 476dig_with_opts @10.53.0.5 www.to-be-removed.tld A >dig.ns5.prime.${n} 477grep "status: NOERROR" dig.ns5.prime.${n} >/dev/null || { 478 ret=1 479 echo_i "priming failed" 480} 481cp ns4/tld2.db ns4/tld.db 482rndc_reload ns4 10.53.0.4 tld 483old= 484for i in 0 1 2 3 4 5 6 7 8 9; do 485 foo=0 486 dig_with_opts @10.53.0.5 ns$i.to-be-removed.tld A >/dev/null 487 dig_with_opts @10.53.0.5 www.to-be-removed.tld A >dig.ns5.out.${n} 488 grep "status: NXDOMAIN" dig.ns5.out.${n} >/dev/null || foo=1 489 [ $foo = 0 ] && break 490 $NSUPDATE <<EOF 491server 10.53.0.6 ${PORT} 492zone to-be-removed.tld 493update add to-be-removed.tld 100 NS ns${i}.to-be-removed.tld 494update delete to-be-removed.tld NS ns${old}.to-be-removed.tld 495send 496EOF 497 old=$i 498 sleep 1 499done 500[ $ret = 0 ] && ret=$foo 501if [ $ret != 0 ]; then 502 echo_i "failed" 503 status=1 504fi 505 506n=$((n + 1)) 507echo_i "check for improved error message with SOA mismatch ($n)" 508ret=0 509dig_with_opts @10.53.0.1 www.sub.broken aaaa >dig.out.ns1.test${n} || ret=1 510grep "not subdomain of zone" ns1/named.run >/dev/null || ret=1 511if [ $ret != 0 ]; then echo_i "failed"; fi 512status=$((status + ret)) 513 514copy_setports ns7/named2.conf.in ns7/named.conf 515rndccmd 10.53.0.7 reconfig 2>&1 | sed 's/^/ns7 /' | cat_i 516 517n=$((n + 1)) 518echo_i "check resolution on the listening port ($n)" 519ret=0 520dig_with_opts +tcp +tries=2 +time=5 mx example.net @10.53.0.7 >dig.ns7.out.${n} || ret=2 521grep "status: NOERROR" dig.ns7.out.${n} >/dev/null || ret=1 522grep "ANSWER: 1" dig.ns7.out.${n} >/dev/null || ret=1 523if [ $ret != 0 ]; then 524 echo_i "failed" 525 ret=1 526fi 527status=$((status + ret)) 528 529n=$((n + 1)) 530echo_i "check prefetch (${n})" 531ret=0 532# read prefetch value from config. 533PREFETCH=$(sed -n "s/[[:space:]]*prefetch \([0-9]\).*/\1/p" ns5/named.conf) 534dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.1.${n} || ret=1 535ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n}) 536interval=$((ttl1 - PREFETCH + 1)) 537# sleep so we are in prefetch range 538sleep ${interval:-0} 539# trigger prefetch 540dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.2.${n} || ret=1 541ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) 542sleep 1 543# check that prefetch occurred 544dig_with_opts @10.53.0.5 fetch.tld txt >dig.out.3.${n} || ret=1 545ttl=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.3.${n}) 546test "${ttl:-0}" -gt "${ttl2:-1}" || ret=1 547if [ $ret != 0 ]; then echo_i "failed"; fi 548status=$((status + ret)) 549 550n=$((n + 1)) 551echo_i "check prefetch of validated DS's RRSIG TTL is updated (${n})" 552ret=0 553dig_with_opts +dnssec @10.53.0.5 ds.example.net ds >dig.out.1.${n} || ret=1 554dsttl1=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.1.${n}) 555interval=$((dsttl1 - PREFETCH + 1)) 556# sleep so we are in prefetch range 557sleep ${interval:-0} 558# trigger prefetch 559dig_with_opts @10.53.0.5 ds.example.net ds >dig.out.2.${n} || ret=1 560dsttl2=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.2.${n}) 561sleep 1 562# check that prefetch occurred 563dig_with_opts @10.53.0.5 ds.example.net ds +dnssec >dig.out.3.${n} || ret=1 564dsttl=$(awk '$4 == "DS" && $7 == "2" { print $2 }' dig.out.3.${n}) 565sigttl=$(awk '$4 == "RRSIG" && $5 == "DS" { print $2 }' dig.out.3.${n}) 566test "${dsttl:-0}" -gt "${dsttl2:-1}" || ret=1 567test "${sigttl:-0}" -gt "${dsttl2:-1}" || ret=1 568test "${dsttl:-0}" -eq "${sigttl:-1}" || ret=1 569if [ $ret != 0 ]; then echo_i "failed"; fi 570status=$((status + ret)) 571 572n=$((n + 1)) 573echo_i "check prefetch disabled (${n})" 574ret=0 575dig_with_opts @10.53.0.7 fetch.example.net txt >dig.out.1.${n} || ret=1 576ttl1=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.1.${n}) 577interval=$((ttl1 - PREFETCH + 1)) 578# sleep so we are in expire range 579sleep ${interval:-0} 580tmp_ttl=$ttl1 581no_prefetch() { 582 # fetch record and ensure its ttl is in range 0 < ttl < tmp_ttl. 583 # since prefetch is disabled, updated ttl must be a lower value than 584 # the previous one. 585 dig_with_opts @10.53.0.7 fetch.example.net txt >dig.out.2.${n} || return 1 586 ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) 587 # check that prefetch has not occurred 588 if [ "$ttl2" -ge "${tmp_ttl}" ]; then 589 return 1 590 fi 591 tmp_ttl=$ttl2 592} 593retry_quiet 3 no_prefetch || ret=1 594if [ $ret != 0 ]; then echo_i "failed"; fi 595status=$((status + ret)) 596 597n=$((n + 1)) 598echo_i "check prefetch qtype * (${n})" 599ret=0 600dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.1.${n} || ret=1 601ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 3 }' dig.out.1.${n}) 602# sleep so we are in prefetch range 603sleep "${ttl1:-0}" 604# trigger prefetch 605dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.2.${n} || ret=1 606ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) 607sleep 1 608# check that prefetch occurred; 609# note that only one record is prefetched, which is the TXT record in this case, 610# because of the order of the records in the cache 611dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.3.${n} || ret=1 612ttl3=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.3.${n}) 613test "${ttl3:-0}" -gt "${ttl2:-1}" || ret=1 614if [ $ret != 0 ]; then echo_i "failed"; fi 615status=$((status + ret)) 616 617n=$((n + 1)) 618echo_i "check that E was logged on EDNS queries in the query log (${n})" 619ret=0 620dig_with_opts @10.53.0.5 +edns edns.fetchall.tld any >dig.out.2.${n} || ret=1 621grep "query: edns.fetchall.tld IN ANY +E" ns5/named.run >/dev/null || ret=1 622dig_with_opts @10.53.0.5 +noedns noedns.fetchall.tld any >dig.out.2.${n} || ret=1 623grep "query: noedns.fetchall.tld IN ANY" ns5/named.run >/dev/null || ret=1 624grep "query: noedns.fetchall.tld IN ANY +E" ns5/named.run >/dev/null && ret=1 625if [ $ret != 0 ]; then echo_i "failed"; fi 626status=$((status + ret)) 627 628n=$((n + 1)) 629echo_i "check that '-t aaaa' in .digrc does not have unexpected side effects ($n)" 630ret=0 631echo "-t aaaa" >.digrc 632(HOME="$(pwd)" dig_with_opts @10.53.0.4 . >dig.out.1.${n}) || ret=1 633(HOME="$(pwd)" dig_with_opts @10.53.0.4 . A >dig.out.2.${n}) || ret=1 634(HOME="$(pwd)" dig_with_opts @10.53.0.4 -x 127.0.0.1 >dig.out.3.${n}) || ret=1 635grep ';\..*IN.*AAAA$' dig.out.1.${n} >/dev/null || ret=1 636grep ';\..*IN.*A$' dig.out.2.${n} >/dev/null || ret=1 637grep 'extra type option' dig.out.2.${n} >/dev/null && ret=1 638grep ';1\.0\.0\.127\.in-addr\.arpa\..*IN.*PTR$' dig.out.3.${n} >/dev/null || ret=1 639if [ $ret != 0 ]; then echo_i "failed"; fi 640status=$((status + ret)) 641 642edns=$($FEATURETEST --edns-version) 643 644n=$((n + 1)) 645echo_i "check that EDNS version is logged (${n})" 646ret=0 647dig_with_opts @10.53.0.5 +edns edns0.fetchall.tld any >dig.out.2.${n} || ret=1 648grep "query: edns0.fetchall.tld IN ANY +E(0)" ns5/named.run >/dev/null || ret=1 649if test "${edns:-0}" != 0; then 650 dig_with_opts @10.53.0.5 +edns=1 edns1.fetchall.tld any >dig.out.2.${n} || ret=1 651 grep "query: edns1.fetchall.tld IN ANY +E(1)" ns5/named.run >/dev/null || ret=1 652fi 653if [ $ret != 0 ]; then echo_i "failed"; fi 654status=$((status + ret)) 655 656if test "${edns:-0}" != 0; then 657 n=$((n + 1)) 658 echo_i "check that edns-version is honoured (${n})" 659 ret=0 660 dig_with_opts @10.53.0.5 +edns no-edns-version.tld >dig.out.1.${n} || ret=1 661 grep "query: no-edns-version.tld IN A -E(1)" ns6/named.run >/dev/null || ret=1 662 dig_with_opts @10.53.0.5 +edns edns-version.tld >dig.out.2.${n} || ret=1 663 grep "query: edns-version.tld IN A -E(0)" ns7/named.run >/dev/null || ret=1 664 if [ $ret != 0 ]; then echo_i "failed"; fi 665 status=$((status + ret)) 666fi 667 668n=$((n + 1)) 669echo_i "check that CNAME nameserver is logged correctly (${n})" 670ret=0 671dig_with_opts soa all-cnames @10.53.0.5 >dig.out.ns5.test${n} || ret=1 672grep "status: SERVFAIL" dig.out.ns5.test${n} >/dev/null || ret=1 673grep "skipping nameserver 'cname.tld' because it is a CNAME, while resolving 'all-cnames/SOA'" ns5/named.run >/dev/null || ret=1 674if [ $ret != 0 ]; then echo_i "failed"; fi 675status=$((status + ret)) 676 677n=$((n + 1)) 678echo_i "check that unexpected opcodes are handled correctly (${n})" 679ret=0 680dig_with_opts soa all-cnames @10.53.0.5 +opcode=15 +cd +rec +ad +zflag >dig.out.ns5.test${n} || ret=1 681grep "status: NOTIMP" dig.out.ns5.test${n} >/dev/null || ret=1 682grep "flags:[^;]* qr[; ]" dig.out.ns5.test${n} >/dev/null || ret=1 683grep "flags:[^;]* ra[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 684grep "flags:[^;]* rd[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 685grep "flags:[^;]* cd[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 686grep "flags:[^;]* ad[; ]" dig.out.ns5.test${n} >/dev/null && ret=1 687grep "flags:[^;]*; MBZ: " dig.out.ns5.test${n} >/dev/null && ret=1 688if [ $ret != 0 ]; then echo_i "failed"; fi 689status=$((status + ret)) 690 691n=$((n + 1)) 692echo_i "check that EDNS client subnet with non-zeroed bits is handled correctly (${n})" 693ret=0 694# 0001 (IPv4) 1f (31 significant bits) 00 (0) ffffffff (255.255.255.255) 695dig_with_opts soa . @10.53.0.5 +ednsopt=8:00011f00ffffffff >dig.out.ns5.test${n} || ret=1 696grep "status: FORMERR" dig.out.ns5.test${n} >/dev/null || ret=1 697grep "; EDNS: version:" dig.out.ns5.test${n} >/dev/null || ret=1 698if [ $ret != 0 ]; then echo_i "failed"; fi 699status=$((status + ret)) 700 701n=$((n + 1)) 702echo_i "check that dig +subnet zeros address bits correctly (${n})" 703ret=0 704dig_with_opts soa . @10.53.0.5 +subnet=255.255.255.255/23 >dig.out.ns5.test${n} || ret=1 705grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 706grep "CLIENT-SUBNET: 255.255.254.0/23/0" dig.out.ns5.test${n} >/dev/null || ret=1 707if [ $ret != 0 ]; then echo_i "failed"; fi 708status=$((status + ret)) 709 710n=$((n + 1)) 711echo_i "check that SOA query returns data for delegation-only apex (${n})" 712ret=0 713dig_with_opts soa delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 714grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 715grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 716if [ $ret != 0 ]; then echo_i "failed"; fi 717status=$((status + ret)) 718n=$((n + 1)) 719 720n=$((n + 1)) 721echo_i "check that NS query returns data for delegation-only apex (${n})" 722ret=0 723dig_with_opts ns delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 724grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 725grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 726if [ $ret != 0 ]; then echo_i "failed"; fi 727status=$((status + ret)) 728 729n=$((n + 1)) 730echo_i "check that A query returns data for delegation-only A apex (${n})" 731ret=0 732dig_with_opts a delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 733grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 734grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 735if [ $ret != 0 ]; then echo_i "failed"; fi 736status=$((status + ret)) 737 738n=$((n + 1)) 739echo_i "check that CDS query returns data for delegation-only apex (${n})" 740ret=0 741dig_with_opts cds delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 742grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 743grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 744if [ $ret != 0 ]; then echo_i "failed"; fi 745status=$((status + ret)) 746 747n=$((n + 1)) 748echo_i "check that AAAA query returns data for delegation-only AAAA apex (${n})" 749ret=0 750dig_with_opts a delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 751grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 752grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 753if [ $ret != 0 ]; then echo_i "failed"; fi 754status=$((status + ret)) 755n=$((n + 1)) 756 757echo_i "check that DNSKEY query returns data for delegation-only apex (${n})" 758ret=0 759dig_with_opts dnskey delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 760grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 761grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 762if [ $ret != 0 ]; then echo_i "failed"; fi 763status=$((status + ret)) 764 765n=$((n + 1)) 766echo_i "check that CDNSKEY query returns data for delegation-only apex (${n})" 767ret=0 768dig_with_opts cdnskey delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 769grep "status: NOERROR" dig.out.ns5.test${n} >/dev/null || ret=1 770grep "ANSWER: 1," dig.out.ns5.test${n} >/dev/null || ret=1 771if [ $ret != 0 ]; then echo_i "failed"; fi 772status=$((status + ret)) 773 774n=$((n + 1)) 775echo_i "check that NXDOMAIN is returned for delegation-only non-apex A data (${n})" 776ret=0 777dig_with_opts a a.delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 778grep "status: NXDOMAIN" dig.out.ns5.test${n} >/dev/null || ret=1 779if [ $ret != 0 ]; then echo_i "failed"; fi 780status=$((status + ret)) 781 782n=$((n + 1)) 783echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDS data (${n})" 784ret=0 785dig_with_opts cds cds.delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 786grep "status: NXDOMAIN" dig.out.ns5.test${n} >/dev/null || ret=1 787if [ $ret != 0 ]; then echo_i "failed"; fi 788status=$((status + ret)) 789 790n=$((n + 1)) 791echo_i "check that NXDOMAIN is returned for delegation-only non-apex AAAA data (${n})" 792ret=0 793dig_with_opts aaaa aaaa.delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 794grep "status: NXDOMAIN" dig.out.ns5.test${n} >/dev/null || ret=1 795if [ $ret != 0 ]; then echo_i "failed"; fi 796status=$((status + ret)) 797n=$((n + 1)) 798 799echo_i "check that NXDOMAIN is returned for delegation-only non-apex CDNSKEY data (${n})" 800ret=0 801dig_with_opts cdnskey cdnskey.delegation-only @10.53.0.5 >dig.out.ns5.test${n} || ret=1 802grep "status: NXDOMAIN" dig.out.ns5.test${n} >/dev/null || ret=1 803if [ $ret != 0 ]; then echo_i "failed"; fi 804status=$((status + ret)) 805 806n=$((n + 1)) 807echo_i "check zero ttl not returned for learnt non zero ttl records (${n})" 808ret=0 809# use prefetch disabled server 810dig_with_opts @10.53.0.7 non-zero.example.net txt >dig.out.1.${n} || ret=1 811ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}) 812# sleep so we are in expire range 813sleep "${ttl1:-0}" 814# look for ttl = 1, allow for one miss at getting zero ttl 815zerotonine="0 1 2 3 4 5 6 7 8 9" 816zerotonine="$zerotonine $zerotonine $zerotonine" 817for i in $zerotonine $zerotonine $zerotonine $zerotonine; do 818 dig_with_opts @10.53.0.7 non-zero.example.net txt >dig.out.2.${n} || ret=1 819 ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) 820 test "${ttl2:-1}" -eq 0 && break 821 test "${ttl2:-1}" -ge "${ttl1:-0}" && break 822 "${PERL}" -e 'select(undef, undef, undef, 0.05);' 823done 824test "${ttl2:-1}" -eq 0 && ret=1 825test "${ttl2:-1}" -ge "${ttl1:-0}" || ret=1 826if [ $ret != 0 ]; then echo_i "failed"; fi 827status=$((status + ret)) 828 829n=$((n + 1)) 830echo_i "check zero ttl is returned for learnt zero ttl records (${n})" 831ret=0 832dig_with_opts @10.53.0.7 zero.example.net txt >dig.out.1.${n} || ret=1 833ttl=$(awk '/"A" "zero" "ttl"/ { print $2 }' dig.out.1.${n}) 834test "${ttl:-1}" -eq 0 || ret=1 835if [ $ret != 0 ]; then echo_i "failed"; fi 836status=$((status + ret)) 837 838n=$((n + 1)) 839echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +ad (${n})" 840ret=0 841dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +ad +nodnssec +ignore +norec >dig.out.$n 842grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 843if [ $ret != 0 ]; then echo_i "failed"; fi 844status=$((status + ret)) 845 846n=$((n + 1)) 847echo_i "check that 'ad' in not returned in truncated answer with empty answer and authority sections to request with +dnssec (${n})" 848ret=0 849dig_with_opts @10.53.0.6 dnskey ds.example.net +bufsize=512 +noad +dnssec +ignore +norec >dig.out.$n 850grep "flags: qr aa tc; QUERY: 1, ANSWER: 0, AUTHORITY: 0" dig.out.$n >/dev/null || ret=1 851if [ $ret != 0 ]; then echo_i "failed"; fi 852status=$((status + ret)) 853 854n=$((n + 1)) 855echo_i "check that the resolver accepts a reply with empty question section with TC=1 and retries over TCP ($n)" 856ret=0 857dig_with_opts @10.53.0.5 truncated.no-questions. a +tries=3 +time=4 >dig.ns5.out.${n} || ret=1 858grep "status: NOERROR" dig.ns5.out.${n} >/dev/null || ret=1 859grep "ANSWER: 1," dig.ns5.out.${n} >/dev/null || ret=1 860grep "1\.2\.3\.4" dig.ns5.out.${n} >/dev/null || ret=1 861if [ $ret != 0 ]; then echo_i "failed"; fi 862status=$((status + ret)) 863 864n=$((n + 1)) 865echo_i "check that the resolver rejects a reply with empty question section with TC=0 ($n)" 866ret=0 867dig_with_opts @10.53.0.5 not-truncated.no-questions. a +tries=3 +time=4 >dig.ns5.out.${n} || ret=1 868grep "status: NOERROR" dig.ns5.out.${n} >/dev/null && ret=1 869grep "ANSWER: 1," dig.ns5.out.${n} >/dev/null && ret=1 870grep "1\.2\.3\.4" dig.ns5.out.${n} >/dev/null && ret=1 871if [ $ret != 0 ]; then echo_i "failed"; fi 872status=$((status + ret)) 873 874if ${FEATURETEST} --enable-querytrace; then 875 n=$((n + 1)) 876 echo_i "check that SERVFAIL is returned for an empty question section via TCP ($n)" 877 ret=0 878 nextpart ns5/named.run >/dev/null 879 # bind to local address so that addresses in log messages are consistent 880 # between platforms 881 dig_with_opts @10.53.0.5 -b 10.53.0.5 tcpalso.no-questions. a +tries=2 +timeout=15 >dig.ns5.out.${n} || ret=1 882 grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null || ret=1 883 check_namedrun() { 884 nextpartpeek ns5/named.run >nextpart.out.${n} 885 grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section, accepting it anyway as TC=1' nextpart.out.${n} >/dev/null || return 1 886 grep '(tcpalso.no-questions/A): connecting via TCP' nextpart.out.${n} >/dev/null || return 1 887 grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section$' nextpart.out.${n} >/dev/null || return 1 888 grep '(tcpalso.no-questions/A): nextitem' nextpart.out.${n} >/dev/null || return 1 889 return 0 890 } 891 retry_quiet 12 check_namedrun || ret=1 892 if [ $ret != 0 ]; then echo_i "failed"; fi 893 status=$((status + ret)) 894fi 895 896n=$((n + 1)) 897echo_i "checking SERVFAIL is returned when all authoritative servers return FORMERR ($n)" 898ret=0 899dig_with_opts @10.53.0.5 ns.formerr-to-all. a >dig.ns5.out.${n} || ret=1 900grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null || ret=1 901if [ $ret != 0 ]; then echo_i "failed"; fi 902status=$((status + ret)) 903 904n=$((n + 1)) 905echo_i "checking SERVFAIL is not returned if only some authoritative servers return FORMERR ($n)" 906ret=0 907dig_with_opts @10.53.0.5 ns.partial-formerr. a >dig.ns5.out.${n} || ret=1 908grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null && ret=1 909if [ $ret != 0 ]; then echo_i "failed"; fi 910status=$((status + ret)) 911 912n=$((n + 1)) 913echo_i "check logged command line ($n)" 914ret=0 915grep "running as: .* -m record " ns1/named.run >/dev/null || ret=1 916if [ $ret != 0 ]; then echo_i "failed"; fi 917status=$((status + ret)) 918 919n=$((n + 1)) 920echo_i "checking NXDOMAIN is returned when querying non existing domain in CH class ($n)" 921ret=0 922dig_with_opts @10.53.0.1 id.hostname txt ch >dig.ns1.out.${n} || ret=1 923grep "status: NXDOMAIN" dig.ns1.out.${n} >/dev/null || ret=1 924if [ $ret != 0 ]; then echo_i "failed"; fi 925status=$((status + ret)) 926 927n=$((n + 1)) 928echo_i "check that the addition section for HTTPS is populated on initial query to a recursive server ($n)" 929ret=0 930dig_with_opts @10.53.0.7 www.example.net https >dig.out.ns7.${n} || ret=1 931grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 932grep "flags:[^;]* ra[ ;]" dig.out.ns7.${n} >/dev/null || ret=1 933grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 934grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 935grep "http-server\.example\.net\..*A.*10\.53\.0\.6" dig.out.ns7.${n} >/dev/null || ret=1 936if [ $ret != 0 ]; then echo_i "failed"; fi 937status=$((status + ret)) 938 939n=$((n + 1)) 940echo_i "check HTTPS loop is handled properly ($n)" 941ret=0 942dig_with_opts @10.53.0.7 https-loop.example.net https >dig.out.ns7.${n} || ret=1 943grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 944grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 945grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 946if [ $ret != 0 ]; then echo_i "failed"; fi 947status=$((status + ret)) 948 949n=$((n + 1)) 950echo_i "check HTTPS -> CNAME loop is handled properly ($n)" 951ret=0 952dig_with_opts @10.53.0.7 https-cname-loop.example.net https >dig.out.ns7.${n} || ret=1 953grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 954grep "ADDITIONAL: 2" dig.out.ns7.${n} >/dev/null || ret=1 955grep "ANSWER: 1," dig.out.ns7.${n} >/dev/null || ret=1 956if [ $ret != 0 ]; then echo_i "failed"; fi 957status=$((status + ret)) 958 959n=$((n + 1)) 960echo_i "check HTTPS cname chains are followed ($n)" 961ret=0 962dig_with_opts @10.53.0.7 https-cname.example.net https >dig.out.ns7.${n} || ret=1 963grep "status: NOERROR" dig.out.ns7.${n} >/dev/null || ret=1 964grep "ADDITIONAL: 4" dig.out.ns7.${n} >/dev/null || ret=1 965grep 'http-server\.example\.net\..*A.10\.53\.0\.6' dig.out.ns7.${n} >/dev/null || ret=1 966grep 'cname-server\.example\.net\..*CNAME.cname-next\.example\.net\.' dig.out.ns7.${n} >/dev/null || ret=1 967grep 'cname-next\.example\.net\..*CNAME.http-server\.example\.net\.' dig.out.ns7.${n} >/dev/null || ret=1 968if [ $ret != 0 ]; then echo_i "failed"; fi 969status=$((status + ret)) 970 971n=$((n + 1)) 972echo_i "check ADB find loops are detected ($n)" 973ret=0 974dig_with_opts +tcp +tries=1 +timeout=5 @10.53.0.1 fake.lame.example.org >dig.out.ns1.${n} || ret=1 975grep "status: SERVFAIL" dig.out.ns1.${n} >/dev/null || ret=1 976if [ $ret != 0 ]; then echo_i "failed"; fi 977status=$((status + ret)) 978 979n=$((n + 1)) 980echo_i "check handling of large referrals to unresponsive name servers ($n)" 981ret=0 982dig_with_opts +timeout=15 large-referral.example.net @10.53.0.1 a >dig.out.ns1.test${n} || ret=1 983grep "status: SERVFAIL" dig.out.ns1.test${n} >/dev/null || ret=1 984# Check the total number of findname() calls triggered by a single query 985# for large-referral.example.net/A. 986findname_call_count="$(grep -c "large-referral\.example\.net.*FINDNAME" ns1/named.run || true)" 987if [ "${findname_call_count}" -gt 1000 ]; then 988 echo_i "failed: ${findname_call_count} (> 1000) findname() calls detected for large-referral.example.net" 989 ret=1 990fi 991# Check whether the limit of NS RRs processed for any delegation 992# encountered was not exceeded. 993if grep -Eq "dns_adb_createfind: started (A|AAAA) fetch for name ns21.fake.redirect.com" ns1/named.run; then 994 echo_i "failed: unexpected address fetch(es) were triggered for ns21.fake.redirect.com" 995 ret=1 996fi 997if [ $ret != 0 ]; then echo_i "failed"; fi 998status=$((status + ret)) 999 1000n=$((n + 1)) 1001echo_i "checking query resolution for a domain with a valid glueless delegation chain ($n)" 1002ret=0 1003rndccmd 10.53.0.1 flush || ret=1 1004dig_with_opts foo.bar.sub.tld1 @10.53.0.1 TXT >dig.out.ns1.test${n} || ret=1 1005grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 1006grep "IN.*TXT.*baz" dig.out.ns1.test${n} >/dev/null || ret=1 1007if [ $ret != 0 ]; then echo_i "failed"; fi 1008status=$((status + ret)) 1009 1010n=$((n + 1)) 1011echo_i "check that correct namespace is chosen for dual-stack-servers ($n)" 1012ret=0 1013# 1014# The two priming queries are needed until we fix dual-stack-servers fully 1015# 1016dig_with_opts @fd92:7065:b8e:ffff::9 v4.nameserver A >dig.out.prime1.${n} || ret=1 1017dig_with_opts @fd92:7065:b8e:ffff::9 v4.nameserver AAAA >dig.out.prime2.${n} || ret=1 1018dig_with_opts @fd92:7065:b8e:ffff::9 foo.v4only.net A >dig.out.ns9.${n} || ret=1 1019grep "status: NOERROR" dig.out.ns9.${n} >/dev/null || ret=1 1020if [ $ret != 0 ]; then echo_i "failed"; fi 1021status=$((status + ret)) 1022 1023n=$((n + 1)) 1024echo_i "check expired TTLs with qtype * (${n})" 1025ret=0 1026dig_with_opts +tcp @10.53.0.5 mixedttl.tld any >dig.out.1.${n} || ret=1 1027ttl1=$(awk '$1 == "mixedttl.tld." && $4 == "A" { print $2 + 1 }' dig.out.1.${n}) 1028# sleep TTL + 1 so that record has expired 1029sleep "${ttl1:-0}" 1030dig_with_opts +tcp @10.53.0.5 mixedttl.tld any >dig.out.2.${n} || ret=1 1031# check preconditions 1032grep "ANSWER: 3," dig.out.1.${n} >/dev/null || ret=1 1033lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.1.${n} | wc -l) 1034test ${lines:-1} -ne 0 && ret=1 1035# check behaviour (there may be 1 answer on very slow machines) 1036grep "ANSWER: [12]," dig.out.2.${n} >/dev/null || ret=1 1037lines=$(awk '$1 == "mixedttl.tld." && $2 > 30 { print }' dig.out.2.${n} | wc -l) 1038test ${lines:-1} -ne 0 && ret=1 1039if [ $ret != 0 ]; then echo_i "failed"; fi 1040 1041n=$((n + 1)) 1042echo_i "check resolver behavior when FORMERR for EDNS options happens (${n})" 1043ret=0 1044msg="resolving options-formerr/A .* server sent FORMERR with echoed DNS COOKIE" 1045if [ $ret != 0 ]; then echo_i "failed"; fi 1046nextpart ns5/named.run >/dev/null 1047dig_with_opts +tcp @10.53.0.5 options-formerr A >dig.out.${n} || ret=1 1048grep "status: NOERROR" dig.out.${n} >/dev/null || ret=1 1049nextpart ns5/named.run | grep "$msg" >/dev/null || ret=1 1050if [ $ret != 0 ]; then echo_i "failed"; fi 1051 1052status=$((status + ret)) 1053 1054echo_i "exit status: $status" 1055[ $status -eq 0 ] || exit 1 1056