xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/digdelv/tests.sh (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1#!/bin/sh
2#
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# This Source Code Form is subject to the terms of the Mozilla Public
6# License, v. 2.0. If a copy of the MPL was not distributed with this
7# file, You can obtain one at http://mozilla.org/MPL/2.0/.
8#
9# See the COPYRIGHT file distributed with this work for additional
10# information regarding copyright ownership.
11
12# shellcheck source=conf.sh
13SYSTEMTESTTOP=..
14. "$SYSTEMTESTTOP/conf.sh"
15
16set -e
17
18status=0
19n=0
20
21sendcmd() {
22    "$PERL" "$SYSTEMTESTTOP/send.pl" "${1}" "$EXTRAPORT1"
23}
24
25dig_with_opts() {
26    "$DIG" -p "$PORT" "$@"
27}
28
29mdig_with_opts() {
30    "$MDIG" -p "$PORT" "$@"
31}
32
33# Check if response in file $1 has the correct TTL range.
34# The response record must have RRtype $2 and class IN (CLASS1).
35# Maximum TTL is given by $3.  This works in most cases where TTL is
36# the second word on the line.  TTL position can be adjusted with
37# setting the position $4, but that requires updating this function.
38check_ttl_range() {
39    file=$1
40    pos=$4
41
42    case "$pos" in
43    "3")
44    awk -v rrtype="$2" -v ttl="$3" '($4 == "IN" || $4 == "CLASS1" ) && $5 == rrtype { if ($3 <= ttl) { ok=1 } } END { exit(ok?0:1) }' < $file
45    ;;
46    *)
47    awk -v rrtype="$2" -v ttl="$3" '($3 == "IN" || $3 == "CLASS1" ) && $4 == rrtype { if ($2 <= ttl) { ok=1 } } END { exit(ok?0:1) }' < $file
48    ;;
49    esac
50
51   result=$?
52   [ $result -eq 0 ] || echo_i "ttl check failed"
53   return $result
54}
55
56# using delv insecure mode as not testing dnssec here
57delv_with_opts() {
58    "$DELV" +noroot -p "$PORT" "$@"
59}
60
61KEYID="$(cat ns2/keyid)"
62KEYDATA="$(< ns2/keydata sed -e 's/+/[+]/g')"
63NOSPLIT="$(< ns2/keydata sed -e 's/+/[+]/g' -e 's/ //g')"
64
65HAS_PYYAML=0
66if [ -n "$PYTHON" ] ; then
67	$PYTHON -c "import yaml" 2> /dev/null && HAS_PYYAML=1
68fi
69
70#
71# test whether ans7/ans.pl will be able to send a UPDATE response.
72# if it can't, we will log that below.
73#
74if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet; my $p = new Net::DNS::Packet; $p->header->opcode(5);' > /dev/null 2>&1
75then
76	checkupdate=1
77else
78	checkupdate=0
79fi
80
81if [ -x "$NSLOOKUP" -a $checkupdate -eq 1 ] ; then
82
83  n=$((n+1))
84  echo_i "check nslookup handles UPDATE response ($n)"
85  ret=0
86  "$NSLOOKUP" -q=CNAME "-port=$PORT" foo.bar 10.53.0.7 > nslookup.out.test$n 2>&1 && ret=1
87  grep "Opcode mismatch" nslookup.out.test$n > /dev/null || ret=1
88  if [ $ret -ne 0 ]; then echo_i "failed"; fi
89  status=$((status+ret))
90
91fi
92
93if [ -x "$HOST" -a $checkupdate -eq 1 ] ; then
94
95  n=$((n+1))
96  echo_i "check host handles UPDATE response ($n)"
97  ret=0
98  "$HOST" -t CNAME -p $PORT foo.bar 10.53.0.7 > host.out.test$n 2>&1 && ret=1
99  grep "Opcode mismatch" host.out.test$n > /dev/null || ret=1
100  if [ $ret -ne 0 ]; then echo_i "failed"; fi
101  status=$((status+ret))
102
103fi
104
105if [ -x "$DIG" ] ; then
106
107  if [ $checkupdate -eq 1 ] ; then
108
109    n=$((n+1))
110    echo_i "check dig handles UPDATE response ($n)"
111    ret=0
112    dig_with_opts @10.53.0.7 cname foo.bar > dig.out.test$n 2>&1 && ret=1
113    grep "Opcode mismatch" dig.out.test$n > /dev/null || ret=1
114    if [ $ret -ne 0 ]; then echo_i "failed"; fi
115    status=$((status+ret))
116  else
117    echo_i "Skipped UPDATE handling test"
118  fi
119
120  n=$((n+1))
121  echo_i "checking dig short form works ($n)"
122  ret=0
123  dig_with_opts @10.53.0.3 +short a a.example > dig.out.test$n || ret=1
124  test "$(wc -l < dig.out.test$n)" -eq 1 || ret=1
125  if [ $ret -ne 0 ]; then echo_i "failed"; fi
126  status=$((status+ret))
127
128  n=$((n+1))
129  echo_i "checking dig split width works ($n)"
130  ret=0
131  dig_with_opts @10.53.0.3 +split=4 -t sshfp foo.example > dig.out.test$n || ret=1
132  grep " 9ABC DEF6 7890 " < dig.out.test$n > /dev/null || ret=1
133  check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
134  if [ $ret -ne 0 ]; then echo_i "failed"; fi
135  status=$((status+ret))
136
137  n=$((n+1))
138  echo_i "checking dig +unknownformat works ($n)"
139  ret=0
140  dig_with_opts @10.53.0.3 +unknownformat a a.example > dig.out.test$n || ret=1
141  grep "CLASS1[ 	][ 	]*TYPE1[ 	][ 	]*\\\\# 4 0A000001" < dig.out.test$n > /dev/null || ret=1
142  check_ttl_range dig.out.test$n "TYPE1" 300 || ret=1
143  if [ $ret -ne 0 ]; then echo_i "failed"; fi
144  status=$((status+ret))
145
146  n=$((n+1))
147  echo_i "checking dig with reverse lookup works ($n)"
148  ret=0
149  dig_with_opts @10.53.0.3 -x 127.0.0.1 > dig.out.test$n 2>&1 || ret=1
150  # doesn't matter if has answer
151  grep -i "127\\.in-addr\\.arpa\\." < dig.out.test$n > /dev/null || ret=1
152  check_ttl_range dig.out.test$n "SOA" 86400 || ret=1
153  if [ $ret -ne 0 ]; then echo_i "failed"; fi
154  status=$((status+ret))
155
156  n=$((n+1))
157  echo_i "checking dig over TCP works ($n)"
158  ret=0
159  dig_with_opts +tcp @10.53.0.3 a a.example > dig.out.test$n || ret=1
160  grep "10\\.0\\.0\\.1$" < dig.out.test$n > /dev/null || ret=1
161  check_ttl_range dig.out.test$n "A" 300 || ret=1
162  if [ $ret -ne 0 ]; then echo_i "failed"; fi
163  status=$((status+ret))
164
165  n=$((n+1))
166  echo_i "checking dig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
167  ret=0
168  dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example > dig.out.test$n || ret=1
169  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n > /dev/null && ret=1
170  check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
171  if [ $ret -ne 0 ]; then echo_i "failed"; fi
172  status=$((status+ret))
173
174  n=$((n+1))
175  echo_i "checking dig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
176  ret=0
177  dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example > dig.out.test$n || ret=1
178  grep "; serial" dig.out.test$n > /dev/null && ret=1
179  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
180  if [ $ret -ne 0 ]; then echo_i "failed"; fi
181  status=$((status+ret))
182
183  n=$((n+1))
184  echo_i "checking dig +rrcomments works for DNSKEY($n)"
185  ret=0
186  dig_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example > dig.out.test$n || ret=1
187  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < dig.out.test$n > /dev/null || ret=1
188  check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
189  if [ $ret -ne 0 ]; then echo_i "failed"; fi
190  status=$((status+ret))
191
192  n=$((n+1))
193  echo_i "checking dig +short +rrcomments works for DNSKEY ($n)"
194  ret=0
195  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
196  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < dig.out.test$n > /dev/null || ret=1
197  if [ $ret -ne 0 ]; then echo_i "failed"; fi
198  status=$((status+ret))
199
200  n=$((n+1))
201  echo_i "checking dig +short +nosplit works($n)"
202  ret=0
203  dig_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example > dig.out.test$n || ret=1
204  grep "$NOSPLIT" < dig.out.test$n > /dev/null || ret=1
205  if [ $ret -ne 0 ]; then echo_i "failed"; fi
206  status=$((status+ret))
207
208  n=$((n+1))
209  echo_i "checking dig +short +rrcomments works($n)"
210  ret=0
211  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
212  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" < dig.out.test$n || ret=1
213  if [ $ret -ne 0 ]; then echo_i "failed"; fi
214  status=$((status+ret))
215
216  n=$((n+1))
217  echo_i "checking dig multi flag is local($n)"
218  ret=0
219  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +nomulti > dig.out.nn.$n || ret=1
220  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +nomulti > dig.out.mn.$n || ret=1
221  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +multi > dig.out.nm.$n || ret=1
222  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +multi > dig.out.mm.$n || ret=1
223  lcnn=$(wc -l < dig.out.nn.$n)
224  lcmn=$(wc -l < dig.out.mn.$n)
225  lcnm=$(wc -l < dig.out.nm.$n)
226  lcmm=$(wc -l < dig.out.mm.$n)
227  test "$lcmm" -ge "$lcnm" || ret=1
228  test "$lcmm" -ge "$lcmn" || ret=1
229  test "$lcnm" -ge "$lcnn" || ret=1
230  test "$lcmn" -ge "$lcnn" || ret=1
231  check_ttl_range dig.out.nn.$n "DNSKEY" 300 || ret=1
232  check_ttl_range dig.out.mn.$n "DNSKEY" 300 || ret=1
233  check_ttl_range dig.out.nm.$n "DNSKEY" 300 || ret=1
234  check_ttl_range dig.out.mm.$n "DNSKEY" 300 || ret=1
235  if [ $ret -ne 0 ]; then echo_i "failed"; fi
236  status=$((status+ret))
237
238  n=$((n+1))
239  echo_i "checking dig +noheader-only works ($n)"
240  ret=0
241  dig_with_opts +tcp @10.53.0.3 +noheader-only A example > dig.out.test$n || ret=1
242  grep "Got answer:" < dig.out.test$n > /dev/null || ret=1
243  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
244  if [ $ret -ne 0 ]; then echo_i "failed"; fi
245  status=$((status+ret))
246
247  n=$((n+1))
248  echo_i "checking dig +short +rrcomments works($n)"
249  ret=0
250  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > dig.out.test$n || ret=1
251  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" < dig.out.test$n || ret=1
252  if [ $ret -ne 0 ]; then echo_i "failed"; fi
253  status=$((status+ret))
254
255  n=$((n+1))
256  echo_i "checking dig +header-only works ($n)"
257  ret=0
258  dig_with_opts +tcp @10.53.0.3 +header-only example > dig.out.test$n || ret=1
259  grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
260  grep "^;; QUESTION SECTION:" < dig.out.test$n > /dev/null && ret=1
261  if [ $ret -ne 0 ]; then echo_i "failed"; fi
262  status=$((status+ret))
263
264  n=$((n+1))
265  echo_i "checking dig +raflag works ($n)"
266  ret=0
267  dig_with_opts +tcp @10.53.0.3 +raflag +qr example > dig.out.test$n || ret=1
268  grep "^;; flags: rd ra ad; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
269  grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
270  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
271  if [ $ret -ne 0 ]; then echo_i "failed"; fi
272  status=$((status+ret))
273
274  n=$((n+1))
275  echo_i "checking dig +tcflag works ($n)"
276  ret=0
277  dig_with_opts +tcp @10.53.0.3 +tcflag +qr example > dig.out.test$n || ret=1
278  grep "^;; flags: tc rd ad; QUERY: 1, ANSWER: 0" < dig.out.test$n > /dev/null || ret=1
279  grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
280  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
281  if [ $ret -ne 0 ]; then echo_i "failed"; fi
282  status=$((status+ret))
283
284  n=$((n+1))
285  echo_i "checking dig +header-only works (with class and type set) ($n)"
286  ret=0
287  dig_with_opts +tcp @10.53.0.3 +header-only -c IN -t A example > dig.out.test$n || ret=1
288  grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," < dig.out.test$n > /dev/null || ret=1
289  grep "^;; QUESTION SECTION:" < dig.out.test$n > /dev/null && ret=1
290  if [ $ret -ne 0 ]; then echo_i "failed"; fi
291  status=$((status+ret))
292
293  n=$((n+1))
294  echo_i "checking dig +zflag works, and that BIND properly ignores it ($n)"
295  ret=0
296  dig_with_opts +tcp @10.53.0.3 +zflag +qr A example > dig.out.test$n || ret=1
297  sed -n '/Sending:/,/Got answer:/p' dig.out.test$n | grep "^;; flags: rd ad; MBZ: 0x4;" > /dev/null || ret=1
298  sed -n '/Got answer:/,/AUTHORITY SECTION:/p' dig.out.test$n | grep "^;; flags: qr rd ra; QUERY: 1" > /dev/null || ret=1
299  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
300  if [ $ret -ne 0 ]; then echo_i "failed"; fi
301  status=$((status+ret))
302
303  n=$((n+1))
304  echo_i "checking dig +qr +ednsopt=08 does not cause an INSIST failure ($n)"
305  ret=0
306  dig_with_opts @10.53.0.3 +ednsopt=08 +qr a a.example > dig.out.test$n || ret=1
307  grep "INSIST" < dig.out.test$n > /dev/null && ret=1
308  grep "FORMERR" < dig.out.test$n > /dev/null || ret=1
309  if [ $ret -ne 0 ]; then echo_i "failed"; fi
310  status=$((status+ret))
311
312  n=$((n+1))
313  echo_i "checking dig +ttlunits works ($n)"
314  ret=0
315  dig_with_opts +tcp @10.53.0.2 +ttlunits A weeks.example > dig.out.test$n || ret=1
316  grep "^weeks.example.		3w" < dig.out.test$n > /dev/null || ret=1
317  dig_with_opts +tcp @10.53.0.2 +ttlunits A days.example > dig.out.test$n || ret=1
318  grep "^days.example.		3d" < dig.out.test$n > /dev/null || ret=1
319  dig_with_opts +tcp @10.53.0.2 +ttlunits A hours.example > dig.out.test$n || ret=1
320  grep "^hours.example.		3h" < dig.out.test$n > /dev/null || ret=1
321  dig_with_opts +tcp @10.53.0.2 +ttlunits A minutes.example > dig.out.test$n || ret=1
322  grep "^minutes.example.	45m" < dig.out.test$n > /dev/null || ret=1
323  dig_with_opts +tcp @10.53.0.2 +ttlunits A seconds.example > dig.out.test$n || ret=1
324  grep "^seconds.example.	45s" < dig.out.test$n > /dev/null || ret=1
325  if [ $ret -ne 0 ]; then echo_i "failed"; fi
326  status=$((status+ret))
327
328  n=$((n+1))
329  echo_i "checking dig respects precedence of options with +ttlunits ($n)"
330  ret=0
331  dig_with_opts +tcp @10.53.0.2 +ttlunits +nottlid A weeks.example > dig.out.test$n || ret=1
332  grep "^weeks.example.		IN" < dig.out.test$n > /dev/null || ret=1
333  dig_with_opts +tcp @10.53.0.2 +nottlid +ttlunits A weeks.example > dig.out.test$n || ret=1
334  grep "^weeks.example.		3w" < dig.out.test$n > /dev/null || ret=1
335  dig_with_opts +tcp @10.53.0.2 +nottlid +nottlunits A weeks.example > dig.out.test$n || ret=1
336  grep "^weeks.example.		1814400" < dig.out.test$n > /dev/null || ret=1
337  if [ $ret -ne 0 ]; then echo_i "failed"; fi
338  status=$((status+ret))
339
340  n=$((n+1))
341  echo_i "checking dig preserves origin on TCP retries ($n)"
342  ret=0
343  # Ask ans4 to still accept TCP connections, but not respond to queries
344  echo "//" | sendcmd 10.53.0.4
345  dig_with_opts -d +tcp @10.53.0.4 +retry=1 +time=1 +domain=bar foo > dig.out.test$n 2>&1 && ret=1
346  test "$(grep -c "trying origin bar" dig.out.test$n)" -eq 2 || ret=1
347  grep "using root origin" < dig.out.test$n > /dev/null && ret=1
348  if [ $ret -ne 0 ]; then echo_i "failed"; fi
349  status=$((status+ret))
350
351  n=$((n+1))
352  echo_i "checking dig -6 -4 ($n)"
353  ret=0
354  dig_with_opts +tcp @10.53.0.2 -4 -6 A a.example > dig.out.test$n 2>&1 && ret=1
355  grep "only one of -4 and -6 allowed" < dig.out.test$n > /dev/null || ret=1
356  if [ $ret -ne 0 ]; then echo_i "failed"; fi
357  status=$((status+ret))
358
359  n=$((n+1))
360  echo_i "checking dig @IPv6addr -4 A a.example ($n)"
361  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
362  then
363    ret=0
364    dig_with_opts +tcp @fd92:7065:b8e:ffff::2 -4 A a.example > dig.out.test$n 2>&1 && ret=1
365    grep "address family not supported" < dig.out.test$n > /dev/null || ret=1
366    if [ $ret -ne 0 ]; then echo_i "failed"; fi
367    status=$((status+ret))
368  else
369    echo_i "IPv6 unavailable; skipping"
370  fi
371
372  n=$((n+1))
373  echo_i "checking dig @IPv4addr -6 +mapped A a.example ($n)"
374  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null && [ "$(uname -s)" != "OpenBSD" ]
375  then
376    ret=0
377    dig_with_opts +tcp @10.53.0.2 -6 +mapped A a.example > dig.out.test$n 2>&1 || ret=1
378    grep "SERVER: ::ffff:10.53.0.2#$PORT" < dig.out.test$n > /dev/null || ret=1
379    if [ $ret -ne 0 ]; then echo_i "failed"; fi
380    status=$((status+ret))
381  else
382    echo_i "IPv6 or IPv4-to-IPv6 mapping unavailable; skipping"
383  fi
384
385  n=$((n+1))
386  echo_i "checking dig +tcp @IPv4addr -6 +nomapped A a.example ($n)"
387  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
388  then
389    ret=0
390    dig_with_opts +tcp @10.53.0.2 -6 +nomapped A a.example > dig.out.test$n 2>&1 || ret=1
391    grep "SERVER: ::ffff:10.53.0.2#$PORT" < dig.out.test$n > /dev/null && ret=1
392    if [ $ret -ne 0 ]; then echo_i "failed"; fi
393    status=$((status+ret))
394  else
395    echo_i "IPv6 unavailable; skipping"
396  fi
397  n=$((n+1))
398
399  echo_i "checking dig +notcp @IPv4addr -6 +nomapped A a.example ($n)"
400  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null
401  then
402    ret=0
403    dig_with_opts +notcp @10.53.0.2 -6 +nomapped A a.example > dig.out.test$n 2>&1 || ret=1
404    grep "SERVER: ::ffff:10.53.0.2#$PORT" < dig.out.test$n > /dev/null && ret=1
405    if [ $ret -ne 0 ]; then echo_i "failed"; fi
406    status=$((status+ret))
407  else
408    echo_i "IPv6 unavailable; skipping"
409  fi
410
411  n=$((n+1))
412  echo_i "checking dig +subnet ($n)"
413  ret=0
414  dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.1 A a.example > dig.out.test$n 2>&1 || ret=1
415  grep "CLIENT-SUBNET: 127.0.0.1/32/0" < dig.out.test$n > /dev/null || ret=1
416  check_ttl_range dig.out.test$n "A" 300 || ret=1
417  if [ $ret -ne 0 ]; then echo_i "failed"; fi
418  status=$((status+ret))
419
420  n=$((n+1))
421  echo_i "checking dig +subnet +subnet ($n)"
422  ret=0
423  dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.0 +subnet=127.0.0.1 A a.example > dig.out.test$n 2>&1 || ret=1
424  grep "CLIENT-SUBNET: 127.0.0.1/32/0" < dig.out.test$n > /dev/null || ret=1
425  check_ttl_range dig.out.test$n "A" 300 || ret=1
426  if [ $ret -ne 0 ]; then echo_i "failed"; fi
427  status=$((status+ret))
428
429  n=$((n+1))
430  echo_i "checking dig +subnet with various prefix lengths ($n)"
431  ret=0
432  for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24; do
433      dig_with_opts +tcp @10.53.0.2 +subnet=255.255.255.255/$i A a.example > dig.out.$i.test$n 2>&1 || ret=1
434      case $i in
435      1|9|17) octet=128 ;;
436      2|10|18) octet=192 ;;
437      3|11|19) octet=224 ;;
438      4|12|20) octet=240 ;;
439      5|13|21) octet=248 ;;
440      6|14|22) octet=252 ;;
441      7|15|23) octet=254 ;;
442      8|16|24) octet=255 ;;
443      esac
444      case $i in
445      1|2|3|4|5|6|7|8) addr="${octet}.0.0.0";;
446      9|10|11|12|13|14|15|16) addr="255.${octet}.0.0";;
447      17|18|19|20|21|22|23|24) addr="255.255.${octet}.0" ;;
448      esac
449      grep "FORMERR" < dig.out.$i.test$n > /dev/null && ret=1
450      grep "CLIENT-SUBNET: $addr/$i/0" < dig.out.$i.test$n > /dev/null || ret=1
451      check_ttl_range dig.out.$i.test$n "A" 300 || ret=1
452  done
453  if [ $ret -ne 0 ]; then echo_i "failed"; fi
454  status=$((status+ret))
455
456  n=$((n+1))
457  echo_i "checking dig +subnet=0/0 ($n)"
458  ret=0
459  dig_with_opts +tcp @10.53.0.2 +subnet=0/0 A a.example > dig.out.test$n 2>&1 || ret=1
460  grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
461  grep "CLIENT-SUBNET: 0.0.0.0/0/0" < dig.out.test$n > /dev/null || ret=1
462  grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
463  check_ttl_range dig.out.test$n "A" 300 || ret=1
464  if [ $ret -ne 0 ]; then echo_i "failed"; fi
465  status=$((status+ret))
466
467  n=$((n+1))
468  echo_i "checking dig +subnet=0 ($n)"
469  ret=0
470  dig_with_opts +tcp @10.53.0.2 +subnet=0 A a.example > dig.out.test$n 2>&1 || ret=1
471  grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
472  grep "CLIENT-SUBNET: 0.0.0.0/0/0" < dig.out.test$n > /dev/null || ret=1
473  grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
474  check_ttl_range dig.out.test$n "A" 300 || ret=1
475  if [ $ret -ne 0 ]; then echo_i "failed"; fi
476  status=$((status+ret))
477
478  n=$((n+1))
479  echo_i "checking dig +subnet=::/0 ($n)"
480  ret=0
481  dig_with_opts +tcp @10.53.0.2 +subnet=::/0 A a.example > dig.out.test$n 2>&1 || ret=1
482  grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
483  grep "CLIENT-SUBNET: ::/0/0" < dig.out.test$n > /dev/null || ret=1
484  grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
485  check_ttl_range dig.out.test$n "A" 300 || ret=1
486  if [ $ret -ne 0 ]; then echo_i "failed"; fi
487  status=$((status+ret))
488
489  n=$((n+1))
490  echo_i "checking dig +ednsopt=8:00000000 (family=0, source=0, scope=0) ($n)"
491  ret=0
492  dig_with_opts +tcp @10.53.0.2 +ednsopt=8:00000000 A a.example > dig.out.test$n 2>&1 || ret=1
493  grep "status: NOERROR" < dig.out.test$n > /dev/null || ret=1
494  grep "CLIENT-SUBNET: 0/0/0" < dig.out.test$n > /dev/null || ret=1
495  grep "10.0.0.1" < dig.out.test$n > /dev/null || ret=1
496  check_ttl_range dig.out.test$n "A" 300 || ret=1
497  if [ $ret -ne 0 ]; then echo_i "failed"; fi
498  status=$((status+ret))
499
500  n=$((n+1))
501  echo_i "checking dig +ednsopt=8:00030000 (family=3, source=0, scope=0) ($n)"
502  ret=0
503  dig_with_opts +qr +tcp @10.53.0.2 +ednsopt=8:00030000 A a.example > dig.out.test$n 2>&1 || ret=1
504  grep "status: FORMERR" < dig.out.test$n > /dev/null || ret=1
505  grep "CLIENT-SUBNET: 00 03 00 00" < dig.out.test$n > /dev/null || ret=1
506  test "$(grep -c "CLIENT-SUBNET: 00 03 00 00" dig.out.test$n)" -eq 1 || ret=1
507  if [ $ret -ne 0 ]; then echo_i "failed"; fi
508  status=$((status+ret))
509
510  n=$((n+1))
511  echo_i "checking dig +subnet with prefix lengths between byte boundaries ($n)"
512  ret=0
513  for p in 9 10 11 12 13 14 15; do
514    dig_with_opts +tcp @10.53.0.2 +subnet=10.53/$p A a.example > dig.out.test.$p.$n 2>&1 || ret=1
515    grep "FORMERR" < dig.out.test.$p.$n > /dev/null && ret=1
516    grep "CLIENT-SUBNET.*/$p/0" < dig.out.test.$p.$n > /dev/null || ret=1
517    check_ttl_range dig.out.test.$p.$n "A" 300 || ret=1
518  done
519  if [ $ret -ne 0 ]; then echo_i "failed"; fi
520  status=$((status+ret))
521
522  n=$((n+1))
523  echo_i "checking dig +sp works as an abbreviated form of split ($n)"
524  ret=0
525  dig_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example > dig.out.test$n || ret=1
526  grep " 9ABC DEF6 7890 " < dig.out.test$n > /dev/null || ret=1
527  check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
528  if [ $ret -ne 0 ]; then echo_i "failed"; fi
529  status=$((status+ret))
530
531  n=$((n+1))
532  echo_i "checking dig -c works ($n)"
533  ret=0
534  dig_with_opts @10.53.0.3 -c CHAOS -t txt version.bind > dig.out.test$n || ret=1
535  grep "version.bind.		0	CH	TXT" < dig.out.test$n > /dev/null || ret=1
536  if [ $ret -ne 0 ]; then echo_i "failed"; fi
537  status=$((status+ret))
538
539  n=$((n+1))
540  echo_i "checking dig +dscp ($n)"
541  ret=0
542  dig_with_opts @10.53.0.3 +dscp=32 a a.example > /dev/null 2>&1 || ret=1
543  dig_with_opts @10.53.0.3 +dscp=-1 a a.example > /dev/null 2>&1 && ret=1
544  dig_with_opts @10.53.0.3 +dscp=64 a a.example > /dev/null 2>&1 && ret=1
545  #TODO add a check to make sure dig is actually setting the dscp on the query
546  #we might have to add better logging to named for this
547  if [ $ret -ne 0 ]; then echo_i "failed"; fi
548  status=$((status+ret))
549
550  n=$((n+1))
551  echo_i "checking dig +ednsopt with option number ($n)"
552  ret=0
553  dig_with_opts @10.53.0.3 +ednsopt=3 a.example > dig.out.test$n 2>&1 || ret=1
554  grep 'NSID: .* ("ns3")' dig.out.test$n > /dev/null || ret=1
555  check_ttl_range dig.out.test$n "A" 300 || ret=1
556  if [ $ret -ne 0 ]; then echo_i "failed"; fi
557  status=$((status+ret))
558
559  n=$((n+1))
560  echo_i "checking dig +ednsopt with option name ($n)"
561  ret=0
562  dig_with_opts @10.53.0.3 +ednsopt=nsid a.example > dig.out.test$n 2>&1 || ret=1
563  grep 'NSID: .* ("ns3")' dig.out.test$n > /dev/null || ret=1
564  check_ttl_range dig.out.test$n "A" 300 || ret=1
565  if [ $ret -ne 0 ]; then echo_i "failed"; fi
566  status=$((status+ret))
567
568  n=$((n+1))
569  echo_i "checking ednsopt LLQ prints as expected ($n)"
570  ret=0
571  dig_with_opts @10.53.0.3 +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example > dig.out.test$n 2>&1 || ret=1
572  pat='LLQ: Version: 1, Opcode: 2, Error: 0, Identifier: 1311768465173141112, Lifetime: 4278124286$'
573  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
574  if [ $ret -ne 0 ]; then echo_i "failed"; fi
575  status=$((status+ret))
576
577  n=$((n+1))
578  echo_i "checking that dig warns about .local queries ($n)"
579  ret=0
580  dig_with_opts @10.53.0.3 local soa > dig.out.test$n 2>&1 || ret=1
581  grep ";; WARNING: .local is reserved for Multicast DNS" dig.out.test$n > /dev/null || ret=1
582  if [ $ret -ne 0 ]; then echo_i "failed"; fi
583  status=$((status+ret))
584
585  n=$((n+1))
586  echo_i "check that dig processes +ednsopt=key-tag and FORMERR is returned ($n)"
587  ret=0
588  dig_with_opts @10.53.0.3 +ednsopt=key-tag a.example +qr > dig.out.test$n 2>&1 || ret=1
589  grep "; KEY-TAG: *$" dig.out.test$n > /dev/null || ret=1
590  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
591  if [ $ret -ne 0 ]; then echo_i "failed"; fi
592  status=$((status+ret))
593
594  n=$((n+1))
595  echo_i "check that dig processes +ednsopt=key-tag:<value-list> ($n)"
596  ret=0
597  dig_with_opts @10.53.0.3 +ednsopt=key-tag:00010002 a.example +qr > dig.out.test$n 2>&1 || ret=1
598  grep "; KEY-TAG: 1, 2$" dig.out.test$n > /dev/null || ret=1
599  grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
600  check_ttl_range dig.out.test$n "A" 300 || ret=1
601  if [ $ret -ne 0 ]; then echo_i "failed"; fi
602  status=$((status+ret))
603
604  n=$((n+1))
605  echo_i "check that dig processes +ednsopt=key-tag:<malformed-value-list> and FORMERR is returned ($n)"
606  ret=0
607  dig_with_opts @10.53.0.3 +ednsopt=key-tag:0001000201 a.example +qr > dig.out.test$n 2>&1 || ret=1
608  grep "; KEY-TAG: 00 01 00 02 01" dig.out.test$n > /dev/null || ret=1
609  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
610  if [ $ret -ne 0 ]; then echo_i "failed"; fi
611  status=$((status+ret))
612
613  n=$((n+1))
614  echo_i "check that dig processes +ednsopt=client-tag:value ($n)"
615  ret=0
616  dig_with_opts @10.53.0.3 +ednsopt=client-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
617  grep "; CLIENT-TAG: 1$" dig.out.test$n > /dev/null || ret=1
618  grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
619  if [ $ret -ne 0 ]; then echo_i "failed"; fi
620  status=$((status+ret))
621
622  n=$((n+1))
623  echo_i "check that FORMERR is returned for a too short client-tag ($n)"
624  ret=0
625  dig_with_opts @10.53.0.3 +ednsopt=client-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
626  grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
627  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
628  if [ $ret -ne 0 ]; then echo_i "failed"; fi
629  status=$((status+ret))
630
631  n=$((n+1))
632  echo_i "check that FORMERR is returned for a too long client-tag ($n)"
633  ret=0
634  dig_with_opts @10.53.0.3 +ednsopt=client-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
635  grep "; CLIENT-TAG" dig.out.test$n > /dev/null || ret=1
636  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
637  if [ $ret -ne 0 ]; then echo_i "failed"; fi
638  status=$((status+ret))
639
640  n=$((n+1))
641  echo_i "check that dig processes +ednsopt=server-tag:value ($n)"
642  ret=0
643  dig_with_opts @10.53.0.3 +ednsopt=server-tag:0001 a.example +qr > dig.out.test$n 2>&1 || ret=1
644  grep "; SERVER-TAG: 1$" dig.out.test$n > /dev/null || ret=1
645  grep "status: FORMERR" dig.out.test$n > /dev/null && ret=1
646  if [ $ret -ne 0 ]; then echo_i "failed"; fi
647  status=$((status+ret))
648
649  n=$((n+1))
650  echo_i "check that FORMERR is returned for a too short server-tag ($n)"
651  ret=0
652  dig_with_opts @10.53.0.3 +ednsopt=server-tag:01 a.example +qr > dig.out.test$n 2>&1 || ret=1
653  grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
654  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
655  if [ $ret -ne 0 ]; then echo_i "failed"; fi
656  status=$((status+ret))
657
658  n=$((n+1))
659  echo_i "check that FORMERR is returned for a too long server-tag ($n)"
660  ret=0
661  dig_with_opts @10.53.0.3 +ednsopt=server-tag:000001 a.example +qr > dig.out.test$n 2>&1 || ret=1
662  grep "; SERVER-TAG" dig.out.test$n > /dev/null || ret=1
663  grep "status: FORMERR" dig.out.test$n > /dev/null || ret=1
664  if [ $ret -ne 0 ]; then echo_i "failed"; fi
665  status=$((status+ret))
666
667  n=$((n+1))
668  echo_i "check that Extended DNS Error 0 is printed correctly ($n)"
669  # First defined EDE code, additional text "foo".
670  dig_with_opts @10.53.0.3 +ednsopt=ede:0000666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
671  pat='^; EDE: 0 (Other): (foo)$'
672  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
673  if [ $ret -ne 0 ]; then echo_i "failed"; fi
674  status=$((status+ret))
675
676  n=$((n+1))
677  echo_i "check that Extended DNS Error 24 is printed correctly ($n)"
678  # Last defined EDE code, no additional text.
679  dig_with_opts @10.53.0.3 +ednsopt=ede:0018 a.example +qr > dig.out.test$n 2>&1 || ret=1
680  pat='^; EDE: 24 (Invalid Data)$'
681  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
682  if [ $ret -ne 0 ]; then echo_i "failed"; fi
683  status=$((status+ret))
684
685  n=$((n+1))
686  echo_i "check that Extended DNS Error 25 is printed correctly ($n)"
687  # First undefined EDE code, additional text "foo".
688  dig_with_opts @10.53.0.3 +ednsopt=ede:0019666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
689  pat='^; EDE: 25: (foo)$'
690  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
691  if [ $ret -ne 0 ]; then echo_i "failed"; fi
692  status=$((status+ret))
693
694  n=$((n+1))
695  echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
696  # EDE payload is too short
697  dig_with_opts @10.53.0.3 +ednsopt=ede a.example +qr > dig.out.test$n 2>&1 || ret=1
698  pat='^; EDE:$'
699  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
700  if [ $ret -ne 0 ]; then echo_i "failed"; fi
701  status=$((status+ret))
702
703  n=$((n+1))
704  echo_i "check that invalid Extended DNS Error (length 1) is printed ($n)"
705  # EDE payload is too short
706  dig_with_opts @10.53.0.3 +ednsopt=ede:00 a.example +qr > dig.out.test$n 2>&1 || ret=1
707  pat='^; EDE: 00 (".")$'
708  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
709  if [ $ret -ne 0 ]; then echo_i "failed"; fi
710  status=$((status+ret))
711
712  if [ $HAS_PYYAML -ne 0 ] ; then
713    n=$((n+1))
714    echo_i "check that +yaml Extended DNS Error 0 is printed correctly ($n)"
715    # First defined EDE code, additional text "foo".
716    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0000666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
717    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
718    read -r value < yamlget.out.test$n
719    [ "$value" = "0 (Other)" ] || ret=1
720    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 || ret=1
721    read -r value < yamlget.out.test$n
722    [ "$value" = "foo" ] || ret=1
723    if [ $ret -ne 0 ]; then echo_i "failed"; fi
724    status=$((status+ret))
725
726    n=$((n+1))
727    echo_i "check that +yaml Extended DNS Error 24 is printed correctly ($n)"
728    # Last defined EDE code, no additional text.
729    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0018 a.example +qr > dig.out.test$n 2>&1 || ret=1
730    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
731    read -r value < yamlget.out.test$n
732    [ "$value" = "24 (Invalid Data)" ] || ret=1
733    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 && ret=1
734    if [ $ret -ne 0 ]; then echo_i "failed"; fi
735    status=$((status+ret))
736
737    n=$((n+1))
738    echo_i "check that +yaml Extended DNS Error 25 is printed correctly ($n)"
739    # First undefined EDE code, additional text "foo".
740    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0019666f6f a.example +qr > dig.out.test$n 2>&1 || ret=1
741    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE INFO-CODE > yamlget.out.test$n 2>&1 || ret=1
742    read -r value < yamlget.out.test$n
743    [ "$value" = "25" ] || ret=1
744    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE EXTRA-TEXT > yamlget.out.test$n 2>&1 || ret=1
745    read -r value < yamlget.out.test$n
746    [ "$value" = "foo" ] || ret=1
747    if [ $ret -ne 0 ]; then echo_i "failed"; fi
748    status=$((status+ret))
749
750    n=$((n+1))
751    echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
752    # EDE payload is too short
753    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede a.example +qr > dig.out.test$n 2>&1 || ret=1
754    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE > yamlget.out.test$n 2>&1 || ret=1
755    read -r value < yamlget.out.test$n
756    [ "$value" = "None" ] || ret=1
757    if [ $ret -ne 0 ]; then echo_i "failed"; fi
758    status=$((status+ret))
759
760    n=$((n+1))
761    echo_i "check that invalid +yaml Extended DNS Error (length 1) is printed ($n)"
762    # EDE payload is too short
763    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:00 a.example +qr > dig.out.test$n 2>&1 || ret=1
764    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE > yamlget.out.test$n 2>&1 || ret=1
765    read -r value < yamlget.out.test$n
766    [ "$value" = '00 (".")' ] || ret=1
767    if [ $ret -ne 0 ]; then echo_i "failed"; fi
768    status=$((status+ret))
769  fi
770
771  n=$((n+1))
772  echo_i "check that dig handles malformed option '+ednsopt=:' gracefully ($n)"
773  ret=0
774  dig_with_opts @10.53.0.3 +ednsopt=: a.example > dig.out.test$n 2>&1 && ret=1
775  grep "ednsopt no code point specified" dig.out.test$n > /dev/null || ret=1
776  if [ $ret -ne 0 ]; then echo_i "failed"; fi
777  status=$((status+ret))
778
779  n=$((n+1))
780  echo_i "check that dig gracefully handles bad escape in domain name ($n)"
781  ret=0
782  digstatus=0
783  dig_with_opts @10.53.0.3 '\0.' > dig.out.test$n 2>&1 || digstatus=$?
784  echo digstatus=$digstatus >> dig.out.test$n
785  test $digstatus -eq 10 || ret=1
786  grep REQUIRE dig.out.test$n > /dev/null && ret=1
787  grep "is not a legal name (bad escape)" dig.out.test$n > /dev/null || ret=1
788  if [ $ret -ne 0 ]; then echo_i "failed"; fi
789  status=$((status+ret))
790
791  n=$((n+1))
792  echo_i "check that dig -q -m works ($n)"
793  ret=0
794  dig_with_opts @10.53.0.3 -q -m > dig.out.test$n 2>&1
795  pat='^;-m\..*IN.*A$'
796  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
797  grep "Dump of all outstanding memory allocations" dig.out.test$n > /dev/null && ret=1
798  if [ $ret -ne 0 ]; then echo_i "failed"; fi
799  status=$((status+ret))
800
801  n=$((n+1))
802  echo_i "checking exit code for a retry upon TCP EOF (immediate -> immediate) ($n)"
803  ret=0
804  echo "no_response no_response" | sendcmd 10.53.0.5
805  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 && ret=1
806  # Sanity check: ensure ans5 behaves as expected.
807  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 2 ] || ret=1
808  if [ $ret -ne 0 ]; then echo_i "failed"; fi
809  status=$((status+ret))
810
811  n=$((n+1))
812  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> partial AXFR) ($n)"
813  ret=0
814  echo "partial_axfr partial_axfr" | sendcmd 10.53.0.5
815  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 && ret=1
816  # Sanity check: ensure ans5 behaves as expected.
817  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 2 ] || ret=1
818  if [ $ret -ne 0 ]; then echo_i "failed"; fi
819  status=$((status+ret))
820
821  n=$((n+1))
822  echo_i "checking exit code for a retry upon TCP EOF (immediate -> partial AXFR) ($n)"
823  ret=0
824  echo "no_response partial_axfr" | sendcmd 10.53.0.5
825  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 && ret=1
826  # Sanity check: ensure ans5 behaves as expected.
827  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 2 ] || ret=1
828  if [ $ret -ne 0 ]; then echo_i "failed"; fi
829  status=$((status+ret))
830
831  n=$((n+1))
832  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> immediate) ($n)"
833  ret=0
834  echo "partial_axfr no_response" | sendcmd 10.53.0.5
835  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 && ret=1
836  # Sanity check: ensure ans5 behaves as expected.
837  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 2 ] || ret=1
838  if [ $ret -ne 0 ]; then echo_i "failed"; fi
839  status=$((status+ret))
840
841  n=$((n+1))
842  echo_i "checking exit code for a retry upon TCP EOF (immediate -> complete AXFR) ($n)"
843  ret=0
844  echo "no_response complete_axfr" | sendcmd 10.53.0.5
845  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 || ret=1
846  # Sanity check: ensure ans5 behaves as expected.
847  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 1 ] || ret=1
848  if [ $ret -ne 0 ]; then echo_i "failed"; fi
849  status=$((status+ret))
850
851  n=$((n+1))
852  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> complete AXFR) ($n)"
853  ret=0
854  echo "partial_axfr complete_axfr" | sendcmd 10.53.0.5
855  dig_with_opts @10.53.0.5 example AXFR +tries=1 > dig.out.test$n 2>&1 || ret=1
856  # Sanity check: ensure ans5 behaves as expected.
857  [ `grep "communications error.*end of file" dig.out.test$n | wc -l` -eq 1 ] || ret=1
858  if [ $ret -ne 0 ]; then echo_i "failed"; fi
859  status=$((status+ret))
860
861  n=$((n+1))
862  echo_i "check that dig +expandaaaa works ($n)"
863  ret=0
864  dig_with_opts @10.53.0.3 +expandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
865  grep "ns2.example.*fd92:7065:0b8e:ffff:0000:0000:0000:0002" dig.out.test$n > /dev/null || ret=1
866  if [ $ret -ne 0 ]; then echo_i "failed"; fi
867  status=$((status+ret))
868
869  n=$((n+1))
870  echo_i "check that dig +noexpandaaaa works ($n)"
871  ret=0
872  dig_with_opts @10.53.0.3 +noexpandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
873  grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n > /dev/null || ret=1
874  if [ $ret -ne 0 ]; then echo_i "failed"; fi
875  status=$((status+ret))
876
877  n=$((n+1))
878  echo_i "check that dig default for +[no]expandaaa (+noexpandaaaa) works ($n)"
879  ret=0
880  dig_with_opts @10.53.0.3 AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
881  grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n > /dev/null || ret=1
882  if [ $ret -ne 0 ]; then echo_i "failed"; fi
883  status=$((status+ret))
884
885  n=$((n+1))
886
887  echo_i "check that dig +short +expandaaaa works ($n)"
888  ret=0
889  dig_with_opts @10.53.0.3 +short +expandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
890  pat='^fd92:7065:0b8e:ffff:0000:0000:0000:0002$'
891  tr -d '\r' < dig.out.test$n | grep "$pat" > /dev/null || ret=1
892  if [ $ret -ne 0 ]; then echo_i "failed"; fi
893  status=$((status+ret))
894
895  if [ $HAS_PYYAML -ne 0 ] ; then
896    n=$((n+1))
897    echo_i "check dig +yaml output ($n)"
898    ret=0
899    dig_with_opts +qr +yaml @10.53.0.3 any ns2.example > dig.out.test$n 2>&1 || ret=1
900    value=$($PYTHON yamlget.py dig.out.test$n 0 message query_message_data status || ret=1)
901    [ "$value" = "NOERROR" ] || ret=1
902    value=$($PYTHON yamlget.py dig.out.test$n 1 message response_message_data status || ret=1)
903    [ "$value" = "NOERROR" ] || ret=1
904    value=$($PYTHON yamlget.py dig.out.test$n 1 message response_message_data QUESTION_SECTION 0 || ret=1)
905    [ "$value" = "ns2.example. IN ANY" ] || ret=1
906    if [ $ret -ne 0 ]; then echo_i "failed"; fi
907    status=$((status+ret))
908
909    n=$((n+1))
910    echo_i "check dig +yaml output of an IPv6 address ending in zeroes ($n)"
911    ret=0
912    dig_with_opts +qr +yaml @10.53.0.3 aaaa d.example > dig.out.test$n 2>&1 || ret=1
913    $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 > yamlget.out.test$n 2>&1 || ret=1
914    read -r value < yamlget.out.test$n
915    [ "$value" = "d.example. 300 IN AAAA fd92:7065:b8e:ffff::0" ] || ret=1
916    if [ $ret -ne 0 ]; then echo_i "failed"; fi
917    status=$((status+ret))
918  fi
919
920  n=$((n+1))
921  echo_i "check that dig +unexpected works ($n)"
922  ret=0
923  dig_with_opts @10.53.0.6 +unexpected a a.example > dig.out.test$n || ret=1
924  grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
925  grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
926  if [ $ret -ne 0 ]; then echo_i "failed"; fi
927  status=$((status+ret))
928
929  n=$((n+1))
930  echo_i "check that dig +nounexpected works ($n)"
931  ret=0
932  dig_with_opts @10.53.0.6 +nounexpected +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
933  grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
934  grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
935  if [ $ret -ne 0 ]; then echo_i "failed"; fi
936  status=$((status+ret))
937
938  n=$((n+1))
939  echo_i "check that dig default for +[no]unexpected (+nounexpected) works ($n)"
940  ret=0
941  dig_with_opts @10.53.0.6 +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
942  grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
943  grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
944  if [ $ret -ne 0 ]; then echo_i "failed"; fi
945  status=$((status+ret))
946
947else
948  echo_i "$DIG is needed, so skipping these dig tests"
949fi
950
951if [ -x "$MDIG" ] ; then
952  n=$((n+1))
953  echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)"
954  ret=0
955  mdig_with_opts @10.53.0.3 +ednsopt=: a.example > dig.out.test$n 2>&1 && ret=1
956  grep "ednsopt no code point specified" dig.out.test$n > /dev/null || ret=1
957  if [ $ret -ne 0 ]; then echo_i "failed"; fi
958  status=$((status+ret))
959
960  n=$((n+1))
961  echo_i "checking mdig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
962  ret=0
963  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example > dig.out.test$n || ret=1
964  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n && ret=1
965  if [ $ret -ne 0 ]; then echo_i "failed"; fi
966  status=$((status+ret))
967
968  n=$((n+1))
969  echo_i "checking mdig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
970  ret=0
971  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example > dig.out.test$n || ret=1
972  grep "; serial" < dig.out.test$n > /dev/null && ret=1
973  if [ $ret -ne 0 ]; then echo_i "failed"; fi
974  status=$((status+ret))
975
976  if [ $HAS_PYYAML -ne 0 ] ; then
977    n=$((n+1))
978    echo_i "check mdig +yaml output ($n)"
979    ret=0
980    mdig_with_opts +yaml @10.53.0.3 -t any ns2.example > dig.out.test$n 2>&1 || ret=1
981    value=$($PYTHON yamlget.py dig.out.test$n 0 message response_message_data status || ret=1)
982    [ "$value" = "NOERROR" ] || ret=1
983    value=$($PYTHON yamlget.py dig.out.test$n 0 message response_message_data QUESTION_SECTION 0 || ret=1)
984    [ "$value" = "ns2.example. IN ANY" ] || ret=1
985    if [ $ret -ne 0 ]; then echo_i "failed"; fi
986    status=$((status+ret))
987  fi
988else
989  echo_i "$MDIG is needed, so skipping these mdig tests"
990fi
991
992if [ -x "$DELV" ] ; then
993  n=$((n+1))
994  echo_i "checking delv short form works ($n)"
995  ret=0
996  delv_with_opts @10.53.0.3 +short a a.example > delv.out.test$n || ret=1
997  test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
998  if [ $ret -ne 0 ]; then echo_i "failed"; fi
999  status=$((status+ret))
1000
1001  n=$((n+1))
1002  echo_i "checking delv split width works ($n)"
1003  ret=0
1004  delv_with_opts @10.53.0.3 +split=4 -t sshfp foo.example > delv.out.test$n || ret=1
1005  grep " 9ABC DEF6 7890 " < delv.out.test$n > /dev/null || ret=1
1006  check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
1007  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1008  status=$((status+ret))
1009
1010  n=$((n+1))
1011  echo_i "checking delv +unknownformat works ($n)"
1012  ret=0
1013  delv_with_opts @10.53.0.3 +unknownformat a a.example > delv.out.test$n || ret=1
1014  grep "CLASS1[ 	][ 	]*TYPE1[ 	][ 	]*\\\\# 4 0A000001" < delv.out.test$n > /dev/null || ret=1
1015  check_ttl_range delv.out.test$n "TYPE1" 300 || ret=1
1016  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1017  status=$((status+ret))
1018
1019  n=$((n+1))
1020  echo_i "checking delv -4 -6 ($n)"
1021  ret=0
1022  delv_with_opts @10.53.0.3 -4 -6 A a.example > delv.out.test$n 2>&1 && ret=1
1023  grep "only one of -4 and -6 allowed" < delv.out.test$n > /dev/null || ret=1
1024  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1025  status=$((status+ret))
1026
1027  n=$((n+1))
1028  echo_i "checking delv with IPv6 on IPv4 does not work ($n)"
1029  if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null
1030  then
1031    ret=0
1032    # following should fail because @IPv4 overrides earlier @IPv6 above
1033    # and -6 forces IPv6 so this should fail, with a message
1034    # "Use of IPv4 disabled by -6"
1035    delv_with_opts @fd92:7065:b8e:ffff::3 @10.53.0.3 -6 -t txt foo.example > delv.out.test$n 2>&1 && ret=1
1036    # it should have no results but error output
1037    grep "testing" < delv.out.test$n > /dev/null && ret=1
1038    grep "Use of IPv4 disabled by -6" delv.out.test$n > /dev/null || ret=1
1039    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1040    status=$((status+ret))
1041  else
1042    echo_i "IPv6 unavailable; skipping"
1043  fi
1044
1045  n=$((n+1))
1046  echo_i "checking delv with IPv4 on IPv6 does not work ($n)"
1047  if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null
1048  then
1049    ret=0
1050    # following should fail because @IPv6 overrides earlier @IPv4 above
1051    # and -4 forces IPv4 so this should fail, with a message
1052    # "Use of IPv6 disabled by -4"
1053    delv_with_opts @10.53.0.3 @fd92:7065:b8e:ffff::3 -4 -t txt foo.example > delv.out.test$n 2>&1 && ret=1
1054    # it should have no results but error output
1055    grep "testing" delv.out.test$n > /dev/null && ret=1
1056    grep "Use of IPv6 disabled by -4" delv.out.test$n > /dev/null || ret=1
1057    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1058    status=$((status+ret))
1059  else
1060    echo_i "IPv6 unavailable; skipping"
1061  fi
1062
1063  n=$((n+1))
1064  echo_i "checking delv with reverse lookup works ($n)"
1065  ret=0
1066  delv_with_opts @10.53.0.3 -x 127.0.0.1 > delv.out.test$n 2>&1 || ret=1
1067  # doesn't matter if has answer
1068  grep -i "127\\.in-addr\\.arpa\\." < delv.out.test$n > /dev/null || ret=1
1069  check_ttl_range delv.out.test$n '\\-ANY' 10800 3 || ret=1
1070  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1071  status=$((status+ret))
1072
1073  n=$((n+1))
1074  echo_i "checking delv over TCP works ($n)"
1075  ret=0
1076  delv_with_opts +tcp @10.53.0.3 a a.example > delv.out.test$n || ret=1
1077  grep "10\\.0\\.0\\.1$" < delv.out.test$n > /dev/null || ret=1
1078  check_ttl_range delv.out.test$n "A" 300 || ret=1
1079  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1080  status=$((status+ret))
1081
1082  n=$((n+1))
1083  echo_i "checking delv +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
1084  ret=0
1085  delv_with_opts +tcp @10.53.0.3 +multi +norrcomments DNSKEY example > delv.out.test$n || ret=1
1086  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null && ret=1
1087  check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
1088  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1089  status=$((status+ret))
1090
1091  n=$((n+1))
1092  echo_i "checking delv +multi +norrcomments works for SOA (when default is rrcomments)($n)"
1093  ret=0
1094  delv_with_opts +tcp @10.53.0.3 +multi +norrcomments SOA example > delv.out.test$n || ret=1
1095  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null && ret=1
1096  check_ttl_range delv.out.test$n "SOA" 300 || ret=1
1097  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1098  status=$((status+ret))
1099
1100  n=$((n+1))
1101  echo_i "checking delv +rrcomments works for DNSKEY($n)"
1102  ret=0
1103  delv_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example > delv.out.test$n || ret=1
1104  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null || ret=1
1105  check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
1106  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1107  status=$((status+ret))
1108
1109  n=$((n+1))
1110  echo_i "checking delv +short +rrcomments works for DNSKEY ($n)"
1111  ret=0
1112  delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > delv.out.test$n || ret=1
1113  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n > /dev/null || ret=1
1114  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1115  status=$((status+ret))
1116
1117  n=$((n+1))
1118  echo_i "checking delv +short +rrcomments works ($n)"
1119  ret=0
1120  delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example > delv.out.test$n || ret=1
1121  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" < delv.out.test$n || ret=1
1122  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1123  status=$((status+ret))
1124
1125  n=$((n+1))
1126  echo_i "checking delv +short +nosplit works ($n)"
1127  ret=0
1128  delv_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example > delv.out.test$n || ret=1
1129  grep -q "$NOSPLIT" < delv.out.test$n || ret=1
1130  test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
1131  test "$(awk '{print NF}' < delv.out.test$n)" -eq 14 || ret=1
1132  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1133  status=$((status+ret))
1134
1135  n=$((n+1))
1136  echo_i "checking delv +short +nosplit +norrcomments works ($n)"
1137  ret=0
1138  delv_with_opts +tcp @10.53.0.3 +short +nosplit +norrcomments DNSKEY example > delv.out.test$n || ret=1
1139  grep -q "$NOSPLIT\$" < delv.out.test$n || ret=1
1140  test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
1141  test "$(awk '{print NF}' < delv.out.test$n)" -eq 4 || ret=1
1142  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1143  status=$((status+ret))
1144
1145  n=$((n+1))
1146  echo_i "checking delv +sp works as an abbriviated form of split ($n)"
1147  ret=0
1148  delv_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example > delv.out.test$n || ret=1
1149  grep " 9ABC DEF6 7890 " < delv.out.test$n > /dev/null || ret=1
1150  check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
1151  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1152  status=$((status+ret))
1153
1154  n=$((n+1))
1155  echo_i "checking delv +sh works as an abbriviated form of short ($n)"
1156  ret=0
1157  delv_with_opts @10.53.0.3 +sh a a.example > delv.out.test$n || ret=1
1158  test "$(wc -l < delv.out.test$n)" -eq 1 || ret=1
1159  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1160  status=$((status+ret))
1161
1162  n=$((n+1))
1163  echo_i "checking delv -c IN works ($n)"
1164  ret=0
1165  delv_with_opts @10.53.0.3 -c IN -t a a.example > delv.out.test$n || ret=1
1166  grep "a.example." < delv.out.test$n > /dev/null || ret=1
1167  check_ttl_range delv.out.test$n "A" 300 || ret=1
1168  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1169  status=$((status+ret))
1170
1171  n=$((n+1))
1172  echo_i "checking delv -c CH is ignored, and treated like IN ($n)"
1173  ret=0
1174  delv_with_opts @10.53.0.3 -c CH -t a a.example > delv.out.test$n || ret=1
1175  grep "a.example." < delv.out.test$n > /dev/null || ret=1
1176  check_ttl_range delv.out.test$n "A" 300 || ret=1
1177  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1178  status=$((status+ret))
1179
1180  n=$((n+1))
1181  echo_i "checking delv H is ignored, and treated like IN ($n)"
1182  ret=0
1183  delv_with_opts @10.53.0.3 -c CH -t a a.example > delv.out.test$n || ret=1
1184  grep "a.example." < delv.out.test$n > /dev/null || ret=1
1185  check_ttl_range delv.out.test$n "A" 300 || ret=1
1186  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1187  status=$((status+ret))
1188
1189  n=$((n+1))
1190  echo_i "check that delv -q -m works ($n)"
1191  ret=0
1192  delv_with_opts @10.53.0.3 -q -m > delv.out.test$n 2>&1 || ret=1
1193  grep '^; -m\..*[0-9]*.*IN.*ANY.*;' delv.out.test$n > /dev/null || ret=1
1194  grep "^add " delv.out.test$n > /dev/null && ret=1
1195  grep "^del " delv.out.test$n > /dev/null && ret=1
1196  check_ttl_range delv.out.test$n '\\-ANY' 300 3 || ret=1
1197  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1198  status=$((status+ret))
1199
1200  n=$((n+1))
1201  echo_i "check that delv -t ANY works ($n)"
1202  ret=0
1203  delv_with_opts @10.53.0.3 -t ANY example > delv.out.test$n 2>&1 || ret=1
1204  grep "^example." < delv.out.test$n > /dev/null || ret=1
1205  check_ttl_range delv.out.test$n NS 300 || ret=1
1206  check_ttl_range delv.out.test$n SOA 300 || ret=1
1207  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1208  status=$((status+ret))
1209
1210  n=$((n+1))
1211  echo_i "check that delv loads key-style trust anchors ($n)"
1212  ret=0
1213  delv_with_opts -a ns3/anchor.dnskey +root=example @10.53.0.3 -t DNSKEY example > delv.out.test$n 2>&1 || ret=1
1214  grep "fully validated" delv.out.test$n > /dev/null || ret=1
1215  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1216  status=$((status+ret))
1217
1218  n=$((n+1))
1219  echo_i "check that delv loads DS-style trust anchors ($n)"
1220  ret=0
1221  delv_with_opts -a ns3/anchor.ds +root=example @10.53.0.3 -t DNSKEY example > delv.out.test$n 2>&1 || ret=1
1222  grep "fully validated" delv.out.test$n > /dev/null || ret=1
1223  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1224  status=$((status+ret))
1225
1226  if [ $HAS_PYYAML -ne 0 ] ; then
1227    n=$((n+1))
1228    echo_i "check delv +yaml output ($n)"
1229    ret=0
1230    delv_with_opts +yaml @10.53.0.3 any ns2.example > delv.out.test$n 2>&1 || ret=1
1231    value=$($PYTHON yamlget.py delv.out.test$n status || ret=1)
1232    [ "$value" = "success" ] || ret=1
1233    value=$($PYTHON yamlget.py delv.out.test$n query_name || ret=1)
1234    [ "$value" = "ns2.example" ] || ret=1
1235    value=$($PYTHON yamlget.py delv.out.test$n records 0 answer_not_validated 0 || ret=1)
1236    count=$(echo $value | wc -w )
1237    [ ${count:-0} -eq 5 ] || ret=1
1238    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1239    status=$((status+ret))
1240  fi
1241else
1242  echo_i "$DELV is needed, so skipping these delv tests"
1243fi
1244
1245echo_i "exit status: $status"
1246[ $status -eq 0 ] || exit 1
1247