xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/digdelv/tests.sh (revision 9689912e6b171cbda866ec33f15ae94a04e2c02d)
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
19status=0
20n=0
21
22sendcmd() {
23  send "${1}" "$EXTRAPORT1"
24}
25
26dig_with_opts() {
27  "$DIG" -p "$PORT" "$@"
28}
29
30mdig_with_opts() {
31  "$MDIG" -p "$PORT" "$@"
32}
33
34# Check if response in file $1 has the correct TTL range.
35# The response record must have RRtype $2 and class IN (CLASS1).
36# Maximum TTL is given by $3.  This works in most cases where TTL is
37# the second word on the line.  TTL position can be adjusted with
38# setting the position $4, but that requires updating this function.
39check_ttl_range() {
40  file=$1
41  pos=$4
42
43  case "$pos" in
44    "3")
45      {
46        awk -v rrtype="$2" -v ttl="$3" '($4 == "IN" || $4 == "CLASS1" ) && $5 == rrtype { if ($3 <= ttl) { ok=1 } } END { exit(ok?0:1) }' <$file
47        result=$?
48      } || true
49      ;;
50    *)
51      {
52        awk -v rrtype="$2" -v ttl="$3" '($3 == "IN" || $3 == "CLASS1" ) && $4 == rrtype { if ($2 <= ttl) { ok=1 } } END { exit(ok?0:1) }' <$file
53        result=$?
54      } || true
55      ;;
56  esac
57
58  [ $result -eq 0 ] || echo_i "ttl check failed"
59  return $result
60}
61
62# use delv insecure mode by default, as we're mostly not testing dnssec
63delv_with_opts() {
64  "$DELV" +noroot -p "$PORT" "$@"
65}
66
67KEYID="$(cat ns2/keyid)"
68KEYDATA="$(sed <ns2/keydata -e 's/+/[+]/g')"
69NOSPLIT="$(sed <ns2/keydata -e 's/+/[+]/g' -e 's/ //g')"
70
71HAS_PYYAML=0
72if [ -x "$PYTHON" ]; then
73  $PYTHON -c "import yaml" 2>/dev/null && HAS_PYYAML=1
74fi
75
76#
77# test whether ans7/ans.pl will be able to send a UPDATE response.
78# if it can't, we will log that below.
79#
80if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet; my $p = new Net::DNS::Packet; $p->header->opcode(5);' >/dev/null 2>&1; then
81  checkupdate=1
82else
83  checkupdate=0
84fi
85
86if [ -x "$NSLOOKUP" -a $checkupdate -eq 1 ]; then
87
88  n=$((n + 1))
89  echo_i "check nslookup handles UPDATE response ($n)"
90  ret=0
91  "$NSLOOKUP" -q=CNAME -timeout=1 "-port=$PORT" foo.bar 10.53.0.7 >nslookup.out.test$n 2>&1 && ret=1
92  grep "Opcode mismatch" nslookup.out.test$n >/dev/null || ret=1
93  if [ $ret -ne 0 ]; then echo_i "failed"; fi
94  status=$((status + ret))
95
96fi
97
98if [ -x "$HOST" -a $checkupdate -eq 1 ]; then
99
100  n=$((n + 1))
101  echo_i "check host handles UPDATE response ($n)"
102  ret=0
103  "$HOST" -W 1 -t CNAME -p $PORT foo.bar 10.53.0.7 >host.out.test$n 2>&1 && ret=1
104  grep "Opcode mismatch" host.out.test$n >/dev/null || ret=1
105  if [ $ret -ne 0 ]; then echo_i "failed"; fi
106  status=$((status + ret))
107
108fi
109
110if [ -x "$NSUPDATE" -a $checkupdate -eq 1 ]; then
111
112  n=$((n + 1))
113  echo_i "check nsupdate handles UPDATE response to QUERY ($n)"
114  ret=0
115  res=0
116  $NSUPDATE <<EOF >nsupdate.out.test$n 2>&1 || res=$?
117server 10.53.0.7 ${PORT}
118add x.example.com 300 in a 1.2.3.4
119send
120EOF
121  test $res -eq 1 || ret=1
122  grep "invalid OPCODE in response to SOA query" nsupdate.out.test$n >/dev/null || ret=1
123  if [ $ret -ne 0 ]; then echo_i "failed"; fi
124  status=$((status + ret))
125
126fi
127
128if [ -x "$DIG" ]; then
129
130  if [ $checkupdate -eq 1 ]; then
131
132    n=$((n + 1))
133    echo_i "check dig handles UPDATE response ($n)"
134    ret=0
135    dig_with_opts @10.53.0.7 +tries=1 +timeout=1 cname foo.bar >dig.out.test$n 2>&1 && ret=1
136    grep "Opcode mismatch" dig.out.test$n >/dev/null || ret=1
137    if [ $ret -ne 0 ]; then echo_i "failed"; fi
138    status=$((status + ret))
139  else
140    echo_i "Skipped UPDATE handling test"
141  fi
142
143  n=$((n + 1))
144  echo_i "checking dig short form works ($n)"
145  ret=0
146  dig_with_opts @10.53.0.3 +short a a.example >dig.out.test$n || ret=1
147  test "$(wc -l <dig.out.test$n)" -eq 1 || ret=1
148  if [ $ret -ne 0 ]; then echo_i "failed"; fi
149  status=$((status + ret))
150
151  n=$((n + 1))
152  echo_i "checking dig split width works ($n)"
153  ret=0
154  dig_with_opts @10.53.0.3 +split=4 -t sshfp foo.example >dig.out.test$n || ret=1
155  grep " 9ABC DEF6 7890 " <dig.out.test$n >/dev/null || ret=1
156  check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
157  if [ $ret -ne 0 ]; then echo_i "failed"; fi
158  status=$((status + ret))
159
160  n=$((n + 1))
161  echo_i "checking dig +unknownformat works ($n)"
162  ret=0
163  dig_with_opts @10.53.0.3 +unknownformat a a.example >dig.out.test$n || ret=1
164  grep "CLASS1[ 	][ 	]*TYPE1[ 	][ 	]*\\\\# 4 0A000001" <dig.out.test$n >/dev/null || ret=1
165  check_ttl_range dig.out.test$n "TYPE1" 300 || ret=1
166  if [ $ret -ne 0 ]; then echo_i "failed"; fi
167  status=$((status + ret))
168
169  n=$((n + 1))
170  echo_i "checking dig with reverse lookup works ($n)"
171  ret=0
172  dig_with_opts @10.53.0.3 -x 127.0.0.1 >dig.out.test$n 2>&1 || ret=1
173  # doesn't matter if has answer
174  grep -i "127\\.in-addr\\.arpa\\." <dig.out.test$n >/dev/null || ret=1
175  check_ttl_range dig.out.test$n "SOA" 86400 || ret=1
176  if [ $ret -ne 0 ]; then echo_i "failed"; fi
177  status=$((status + ret))
178
179  n=$((n + 1))
180  echo_i "checking dig over TCP works ($n)"
181  ret=0
182  dig_with_opts +tcp @10.53.0.3 a a.example >dig.out.test$n || ret=1
183  grep "10\\.0\\.0\\.1$" <dig.out.test$n >/dev/null || ret=1
184  check_ttl_range dig.out.test$n "A" 300 || ret=1
185  if [ $ret -ne 0 ]; then echo_i "failed"; fi
186  status=$((status + ret))
187
188  n=$((n + 1))
189  echo_i "checking dig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
190  ret=0
191  dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example >dig.out.test$n || ret=1
192  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n >/dev/null && ret=1
193  check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
194  if [ $ret -ne 0 ]; then echo_i "failed"; fi
195  status=$((status + ret))
196
197  n=$((n + 1))
198  echo_i "checking dig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
199  ret=0
200  dig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example >dig.out.test$n || ret=1
201  grep "; serial" dig.out.test$n >/dev/null && ret=1
202  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
203  if [ $ret -ne 0 ]; then echo_i "failed"; fi
204  status=$((status + ret))
205
206  n=$((n + 1))
207  echo_i "checking dig +rrcomments works for DNSKEY($n)"
208  ret=0
209  dig_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example >dig.out.test$n || ret=1
210  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <dig.out.test$n >/dev/null || ret=1
211  check_ttl_range dig.out.test$n "DNSKEY" 300 || ret=1
212  if [ $ret -ne 0 ]; then echo_i "failed"; fi
213  status=$((status + ret))
214
215  n=$((n + 1))
216  echo_i "checking dig +short +rrcomments works for DNSKEY ($n)"
217  ret=0
218  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1
219  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <dig.out.test$n >/dev/null || ret=1
220  if [ $ret -ne 0 ]; then echo_i "failed"; fi
221  status=$((status + ret))
222
223  n=$((n + 1))
224  echo_i "checking dig +short +nosplit works($n)"
225  ret=0
226  dig_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example >dig.out.test$n || ret=1
227  grep "$NOSPLIT" <dig.out.test$n >/dev/null || ret=1
228  if [ $ret -ne 0 ]; then echo_i "failed"; fi
229  status=$((status + ret))
230
231  n=$((n + 1))
232  echo_i "checking dig +short +rrcomments works($n)"
233  ret=0
234  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1
235  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" <dig.out.test$n || ret=1
236  if [ $ret -ne 0 ]; then echo_i "failed"; fi
237  status=$((status + ret))
238
239  n=$((n + 1))
240  echo_i "checking dig multi flag is local($n)"
241  ret=0
242  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +nomulti >dig.out.nn.$n || ret=1
243  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +nomulti >dig.out.mn.$n || ret=1
244  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +nomulti example +multi >dig.out.nm.$n || ret=1
245  dig_with_opts +tcp @10.53.0.3 -t DNSKEY example +multi example +multi >dig.out.mm.$n || ret=1
246  lcnn=$(wc -l <dig.out.nn.$n)
247  lcmn=$(wc -l <dig.out.mn.$n)
248  lcnm=$(wc -l <dig.out.nm.$n)
249  lcmm=$(wc -l <dig.out.mm.$n)
250  test "$lcmm" -ge "$lcnm" || ret=1
251  test "$lcmm" -ge "$lcmn" || ret=1
252  test "$lcnm" -ge "$lcnn" || ret=1
253  test "$lcmn" -ge "$lcnn" || ret=1
254  check_ttl_range dig.out.nn.$n "DNSKEY" 300 || ret=1
255  check_ttl_range dig.out.mn.$n "DNSKEY" 300 || ret=1
256  check_ttl_range dig.out.nm.$n "DNSKEY" 300 || ret=1
257  check_ttl_range dig.out.mm.$n "DNSKEY" 300 || ret=1
258  if [ $ret -ne 0 ]; then echo_i "failed"; fi
259  status=$((status + ret))
260
261  n=$((n + 1))
262  echo_i "checking dig +noheader-only works ($n)"
263  ret=0
264  dig_with_opts +tcp @10.53.0.3 +noheader-only A example >dig.out.test$n || ret=1
265  grep "Got answer:" <dig.out.test$n >/dev/null || ret=1
266  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
267  if [ $ret -ne 0 ]; then echo_i "failed"; fi
268  status=$((status + ret))
269
270  n=$((n + 1))
271  echo_i "checking dig +short +rrcomments works($n)"
272  ret=0
273  dig_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >dig.out.test$n || ret=1
274  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID\$" <dig.out.test$n || ret=1
275  if [ $ret -ne 0 ]; then echo_i "failed"; fi
276  status=$((status + ret))
277
278  n=$((n + 1))
279  echo_i "checking dig +header-only works ($n)"
280  ret=0
281  dig_with_opts +tcp @10.53.0.3 +header-only example >dig.out.test$n || ret=1
282  grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," <dig.out.test$n >/dev/null || ret=1
283  grep "^;; QUESTION SECTION:" <dig.out.test$n >/dev/null && ret=1
284  if [ $ret -ne 0 ]; then echo_i "failed"; fi
285  status=$((status + ret))
286
287  n=$((n + 1))
288  echo_i "checking dig +raflag works ($n)"
289  ret=0
290  dig_with_opts +tcp @10.53.0.3 +raflag +qr example >dig.out.test$n || ret=1
291  grep "^;; flags: rd ra ad; QUERY: 1, ANSWER: 0," <dig.out.test$n >/dev/null || ret=1
292  grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," <dig.out.test$n >/dev/null || ret=1
293  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
294  if [ $ret -ne 0 ]; then echo_i "failed"; fi
295  status=$((status + ret))
296
297  n=$((n + 1))
298  echo_i "checking dig +tcflag works ($n)"
299  ret=0
300  dig_with_opts +tcp @10.53.0.3 +tcflag +qr example >dig.out.test$n || ret=1
301  grep "^;; flags: tc rd ad; QUERY: 1, ANSWER: 0" <dig.out.test$n >/dev/null || ret=1
302  grep "^;; flags: qr rd ra; QUERY: 1, ANSWER: 0," <dig.out.test$n >/dev/null || ret=1
303  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
304  if [ $ret -ne 0 ]; then echo_i "failed"; fi
305  status=$((status + ret))
306
307  n=$((n + 1))
308  echo_i "checking dig +header-only works (with class and type set) ($n)"
309  ret=0
310  dig_with_opts +tcp @10.53.0.3 +header-only -c IN -t A example >dig.out.test$n || ret=1
311  grep "^;; flags: qr rd; QUERY: 0, ANSWER: 0," <dig.out.test$n >/dev/null || ret=1
312  grep "^;; QUESTION SECTION:" <dig.out.test$n >/dev/null && ret=1
313  if [ $ret -ne 0 ]; then echo_i "failed"; fi
314  status=$((status + ret))
315
316  n=$((n + 1))
317  echo_i "checking dig +zflag works, and that BIND properly ignores it ($n)"
318  ret=0
319  dig_with_opts +tcp @10.53.0.3 +zflag +qr A example >dig.out.test$n || ret=1
320  sed -n '/Sending:/,/Got answer:/p' dig.out.test$n | grep "^;; flags: rd ad; MBZ: 0x4;" >/dev/null || ret=1
321  sed -n '/Got answer:/,/AUTHORITY SECTION:/p' dig.out.test$n | grep "^;; flags: qr rd ra; QUERY: 1" >/dev/null || ret=1
322  check_ttl_range dig.out.test$n "SOA" 300 || ret=1
323  if [ $ret -ne 0 ]; then echo_i "failed"; fi
324  status=$((status + ret))
325
326  n=$((n + 1))
327  echo_i "checking dig +qr +ednsopt=08 does not cause an INSIST failure ($n)"
328  ret=0
329  dig_with_opts @10.53.0.3 +ednsopt=08 +qr a a.example >dig.out.test$n || ret=1
330  grep "INSIST" <dig.out.test$n >/dev/null && ret=1
331  grep "FORMERR" <dig.out.test$n >/dev/null || ret=1
332  if [ $ret -ne 0 ]; then echo_i "failed"; fi
333  status=$((status + ret))
334
335  n=$((n + 1))
336  echo_i "checking dig +ttlunits works ($n)"
337  ret=0
338  dig_with_opts +tcp @10.53.0.2 +ttlunits A weeks.example >dig.out.test$n || ret=1
339  grep "^weeks.example.		3w" <dig.out.test$n >/dev/null || ret=1
340  dig_with_opts +tcp @10.53.0.2 +ttlunits A days.example >dig.out.test$n || ret=1
341  grep "^days.example.		3d" <dig.out.test$n >/dev/null || ret=1
342  dig_with_opts +tcp @10.53.0.2 +ttlunits A hours.example >dig.out.test$n || ret=1
343  grep "^hours.example.		3h" <dig.out.test$n >/dev/null || ret=1
344  dig_with_opts +tcp @10.53.0.2 +ttlunits A minutes.example >dig.out.test$n || ret=1
345  grep "^minutes.example.	45m" <dig.out.test$n >/dev/null || ret=1
346  dig_with_opts +tcp @10.53.0.2 +ttlunits A seconds.example >dig.out.test$n || ret=1
347  grep "^seconds.example.	45s" <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 respects precedence of options with +ttlunits ($n)"
353  ret=0
354  dig_with_opts +tcp @10.53.0.2 +ttlunits +nottlid A weeks.example >dig.out.test$n || ret=1
355  grep "^weeks.example.		IN" <dig.out.test$n >/dev/null || ret=1
356  dig_with_opts +tcp @10.53.0.2 +nottlid +ttlunits A weeks.example >dig.out.test$n || ret=1
357  grep "^weeks.example.		3w" <dig.out.test$n >/dev/null || ret=1
358  dig_with_opts +tcp @10.53.0.2 +nottlid +nottlunits A weeks.example >dig.out.test$n || ret=1
359  grep "^weeks.example.		1814400" <dig.out.test$n >/dev/null || ret=1
360  if [ $ret -ne 0 ]; then echo_i "failed"; fi
361  status=$((status + ret))
362
363  n=$((n + 1))
364  echo_i "checking dig preserves origin on TCP retries ($n)"
365  ret=0
366  # Ask ans4 to still accept TCP connections, but not respond to queries
367  echo "//" | sendcmd 10.53.0.4
368  dig_with_opts -d +tcp @10.53.0.4 +retry=1 +time=1 +domain=bar foo >dig.out.test$n 2>&1 && ret=1
369  test "$(grep -c "trying origin bar" dig.out.test$n)" -eq 2 || ret=1
370  grep "using root origin" <dig.out.test$n >/dev/null && ret=1
371  if [ $ret -ne 0 ]; then echo_i "failed"; fi
372  status=$((status + ret))
373
374  n=$((n + 1))
375  echo_i "checking dig -6 -4 ($n)"
376  ret=0
377  dig_with_opts +tcp @10.53.0.2 -4 -6 A a.example >dig.out.test$n 2>&1 && ret=1
378  grep "only one of -4 and -6 allowed" <dig.out.test$n >/dev/null || ret=1
379  if [ $ret -ne 0 ]; then echo_i "failed"; fi
380  status=$((status + ret))
381
382  n=$((n + 1))
383  echo_i "checking dig @IPv6addr -4 A a.example ($n)"
384  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then
385    ret=0
386    dig_with_opts +tcp @fd92:7065:b8e:ffff::2 -4 A a.example >dig.out.test$n 2>&1 && ret=1
387    grep "address family not supported" <dig.out.test$n >/dev/null || ret=1
388    if [ $ret -ne 0 ]; then echo_i "failed"; fi
389    status=$((status + ret))
390  else
391    echo_i "IPv6 unavailable; skipping"
392  fi
393
394  n=$((n + 1))
395  echo_i "checking dig +tcp @IPv4addr -6 A a.example ($n)"
396  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then
397    ret=0
398    dig_with_opts +tcp @10.53.0.2 -6 A a.example >dig.out.test$n 2>&1 || ret=1
399    grep "SERVER: ::ffff:10.53.0.2#$PORT" <dig.out.test$n >/dev/null && ret=1
400    if [ $ret -ne 0 ]; then echo_i "failed"; fi
401    status=$((status + ret))
402  else
403    echo_i "IPv6 unavailable; skipping"
404  fi
405  n=$((n + 1))
406
407  echo_i "checking dig +notcp @IPv4addr -6 A a.example ($n)"
408  if testsock6 fd92:7065:b8e:ffff::2 2>/dev/null; then
409    ret=0
410    dig_with_opts +notcp @10.53.0.2 -6 A a.example >dig.out.test$n 2>&1 || ret=1
411    grep "SERVER: ::ffff:10.53.0.2#$PORT" <dig.out.test$n >/dev/null && ret=1
412    if [ $ret -ne 0 ]; then echo_i "failed"; fi
413    status=$((status + ret))
414  else
415    echo_i "IPv6 unavailable; skipping"
416  fi
417
418  n=$((n + 1))
419  echo_i "checking dig +subnet ($n)"
420  ret=0
421  dig_with_opts +tcp @10.53.0.2 +subnet=127.0.0.1 A a.example >dig.out.test$n 2>&1 || ret=1
422  grep "CLIENT-SUBNET: 127.0.0.1/32/0" <dig.out.test$n >/dev/null || ret=1
423  check_ttl_range dig.out.test$n "A" 300 || ret=1
424  if [ $ret -ne 0 ]; then echo_i "failed"; fi
425  status=$((status + ret))
426
427  n=$((n + 1))
428  echo_i "checking dig +subnet +subnet ($n)"
429  ret=0
430  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
431  grep "CLIENT-SUBNET: 127.0.0.1/32/0" <dig.out.test$n >/dev/null || ret=1
432  check_ttl_range dig.out.test$n "A" 300 || ret=1
433  if [ $ret -ne 0 ]; then echo_i "failed"; fi
434  status=$((status + ret))
435
436  n=$((n + 1))
437  echo_i "checking dig +subnet with various prefix lengths ($n)"
438  ret=0
439  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
440    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
441    case $i in
442      1 | 9 | 17) octet=128 ;;
443      2 | 10 | 18) octet=192 ;;
444      3 | 11 | 19) octet=224 ;;
445      4 | 12 | 20) octet=240 ;;
446      5 | 13 | 21) octet=248 ;;
447      6 | 14 | 22) octet=252 ;;
448      7 | 15 | 23) octet=254 ;;
449      8 | 16 | 24) octet=255 ;;
450    esac
451    case $i in
452      1 | 2 | 3 | 4 | 5 | 6 | 7 | 8) addr="${octet}.0.0.0" ;;
453      9 | 10 | 11 | 12 | 13 | 14 | 15 | 16) addr="255.${octet}.0.0" ;;
454      17 | 18 | 19 | 20 | 21 | 22 | 23 | 24) addr="255.255.${octet}.0" ;;
455    esac
456    grep "FORMERR" <dig.out.$i.test$n >/dev/null && ret=1
457    grep "CLIENT-SUBNET: $addr/$i/0" <dig.out.$i.test$n >/dev/null || ret=1
458    check_ttl_range dig.out.$i.test$n "A" 300 || ret=1
459  done
460  if [ $ret -ne 0 ]; then echo_i "failed"; fi
461  status=$((status + ret))
462
463  n=$((n + 1))
464  echo_i "checking dig +subnet=0/0 ($n)"
465  ret=0
466  dig_with_opts +tcp @10.53.0.2 +subnet=0/0 A a.example >dig.out.test$n 2>&1 || ret=1
467  grep "status: NOERROR" <dig.out.test$n >/dev/null || ret=1
468  grep "CLIENT-SUBNET: 0.0.0.0/0/0" <dig.out.test$n >/dev/null || ret=1
469  grep "10.0.0.1" <dig.out.test$n >/dev/null || ret=1
470  check_ttl_range dig.out.test$n "A" 300 || ret=1
471  if [ $ret -ne 0 ]; then echo_i "failed"; fi
472  status=$((status + ret))
473
474  n=$((n + 1))
475  echo_i "checking dig +subnet=0 ($n)"
476  ret=0
477  dig_with_opts +tcp @10.53.0.2 +subnet=0 A a.example >dig.out.test$n 2>&1 || ret=1
478  grep "status: NOERROR" <dig.out.test$n >/dev/null || ret=1
479  grep "CLIENT-SUBNET: 0.0.0.0/0/0" <dig.out.test$n >/dev/null || ret=1
480  grep "10.0.0.1" <dig.out.test$n >/dev/null || ret=1
481  check_ttl_range dig.out.test$n "A" 300 || ret=1
482  if [ $ret -ne 0 ]; then echo_i "failed"; fi
483  status=$((status + ret))
484
485  n=$((n + 1))
486  echo_i "checking dig +subnet=::/0 ($n)"
487  ret=0
488  dig_with_opts +tcp @10.53.0.2 +subnet=::/0 A a.example >dig.out.test$n 2>&1 || ret=1
489  grep "status: NOERROR" <dig.out.test$n >/dev/null || ret=1
490  grep "CLIENT-SUBNET: ::/0/0" <dig.out.test$n >/dev/null || ret=1
491  grep "10.0.0.1" <dig.out.test$n >/dev/null || ret=1
492  check_ttl_range dig.out.test$n "A" 300 || ret=1
493  if [ $ret -ne 0 ]; then echo_i "failed"; fi
494  status=$((status + ret))
495
496  n=$((n + 1))
497  echo_i "checking dig +ednsopt=8:00000000 (family=0, source=0, scope=0) ($n)"
498  ret=0
499  dig_with_opts +tcp @10.53.0.2 +ednsopt=8:00000000 A a.example >dig.out.test$n 2>&1 || ret=1
500  grep "status: NOERROR" <dig.out.test$n >/dev/null || ret=1
501  grep "CLIENT-SUBNET: 0/0/0" <dig.out.test$n >/dev/null || ret=1
502  grep "10.0.0.1" <dig.out.test$n >/dev/null || ret=1
503  check_ttl_range dig.out.test$n "A" 300 || ret=1
504  if [ $ret -ne 0 ]; then echo_i "failed"; fi
505  status=$((status + ret))
506
507  n=$((n + 1))
508  echo_i "checking dig +ednsopt=8:00030000 (family=3, source=0, scope=0) ($n)"
509  ret=0
510  dig_with_opts +qr +tcp @10.53.0.2 +ednsopt=8:00030000 A a.example >dig.out.test$n 2>&1 || ret=1
511  grep "status: FORMERR" <dig.out.test$n >/dev/null || ret=1
512  grep "CLIENT-SUBNET: 00 03 00 00" <dig.out.test$n >/dev/null || ret=1
513  test "$(grep -c "CLIENT-SUBNET: 00 03 00 00" dig.out.test$n)" -eq 1 || ret=1
514  if [ $ret -ne 0 ]; then echo_i "failed"; fi
515  status=$((status + ret))
516
517  n=$((n + 1))
518  echo_i "checking dig +subnet with prefix lengths between byte boundaries ($n)"
519  ret=0
520  for p in 9 10 11 12 13 14 15; do
521    dig_with_opts +tcp @10.53.0.2 +subnet=10.53/$p A a.example >dig.out.test.$p.$n 2>&1 || ret=1
522    grep "FORMERR" <dig.out.test.$p.$n >/dev/null && ret=1
523    grep "CLIENT-SUBNET.*/$p/0" <dig.out.test.$p.$n >/dev/null || ret=1
524    check_ttl_range dig.out.test.$p.$n "A" 300 || ret=1
525  done
526  if [ $ret -ne 0 ]; then echo_i "failed"; fi
527  status=$((status + ret))
528
529  n=$((n + 1))
530  echo_i "checking dig +sp works as an abbreviated form of split ($n)"
531  ret=0
532  dig_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example >dig.out.test$n || ret=1
533  grep " 9ABC DEF6 7890 " <dig.out.test$n >/dev/null || ret=1
534  check_ttl_range dig.out.test$n "SSHFP" 300 || ret=1
535  if [ $ret -ne 0 ]; then echo_i "failed"; fi
536  status=$((status + ret))
537
538  n=$((n + 1))
539  echo_i "checking dig -c works ($n)"
540  ret=0
541  dig_with_opts @10.53.0.3 -c CHAOS -t txt version.bind >dig.out.test$n || ret=1
542  grep "version.bind.		0	CH	TXT" <dig.out.test$n >/dev/null || ret=1
543  if [ $ret -ne 0 ]; then echo_i "failed"; fi
544  status=$((status + ret))
545
546  n=$((n + 1))
547  echo_i "checking dig +ednsopt with option number ($n)"
548  ret=0
549  dig_with_opts @10.53.0.3 +ednsopt=3 a.example >dig.out.test$n 2>&1 || ret=1
550  grep 'NSID: .* ("ns3")' dig.out.test$n >/dev/null || ret=1
551  check_ttl_range dig.out.test$n "A" 300 || ret=1
552  if [ $ret -ne 0 ]; then echo_i "failed"; fi
553  status=$((status + ret))
554
555  n=$((n + 1))
556  echo_i "checking dig +ednsopt with option name ($n)"
557  ret=0
558  dig_with_opts @10.53.0.3 +ednsopt=nsid a.example >dig.out.test$n 2>&1 || ret=1
559  grep 'NSID: .* ("ns3")' dig.out.test$n >/dev/null || ret=1
560  check_ttl_range dig.out.test$n "A" 300 || ret=1
561  if [ $ret -ne 0 ]; then echo_i "failed"; fi
562  status=$((status + ret))
563
564  n=$((n + 1))
565  echo_i "checking ednsopt UL prints as expected (single lease) ($n)"
566  ret=0
567  dig_with_opts @10.53.0.3 +ednsopt=UL:00000e10 +qr a.example >dig.out.test$n 2>&1 || ret=1
568  pat='UL: 3600 (1 hour)'
569  grep "$pat" dig.out.test$n >/dev/null || ret=1
570  if [ $ret -ne 0 ]; then echo_i "failed"; fi
571  status=$((status + ret))
572  n=$((n + 1))
573
574  n=$((n + 1))
575  echo_i "checking ednsopt UL prints as expected (split lease) ($n)"
576  ret=0
577  dig_with_opts @10.53.0.3 +ednsopt=UL:00000e1000127500 +qr a.example >dig.out.test$n 2>&1 || ret=1
578  pat='UL: 3600/1209600 (1 hour/2 weeks)'
579  grep "$pat" dig.out.test$n >/dev/null || ret=1
580  if [ $ret -ne 0 ]; then echo_i "failed"; fi
581  status=$((status + ret))
582  n=$((n + 1))
583
584  echo_i "checking ednsopt LLQ prints as expected ($n)"
585  ret=0
586  dig_with_opts @10.53.0.3 +ednsopt=llq:0001000200001234567812345678fefefefe +qr a.example >dig.out.test$n 2>&1 || ret=1
587  pat='LLQ: Version: 1, Opcode: 2, Error: 0, Identifier: 1311768465173141112, Lifetime: 4278124286$'
588  grep "$pat" dig.out.test$n >/dev/null || ret=1
589  if [ $ret -ne 0 ]; then echo_i "failed"; fi
590  status=$((status + ret))
591
592  n=$((n + 1))
593  echo_i "checking that dig warns about .local queries ($n)"
594  ret=0
595  dig_with_opts @10.53.0.3 local soa >dig.out.test$n 2>&1 || ret=1
596  grep ";; WARNING: .local is reserved for Multicast DNS" dig.out.test$n >/dev/null || ret=1
597  if [ $ret -ne 0 ]; then echo_i "failed"; fi
598  status=$((status + ret))
599
600  n=$((n + 1))
601  echo_i "check that dig processes +ednsopt=key-tag and FORMERR is returned ($n)"
602  ret=0
603  dig_with_opts @10.53.0.3 +ednsopt=key-tag a.example +qr >dig.out.test$n 2>&1 || ret=1
604  grep "; KEY-TAG: *$" dig.out.test$n >/dev/null || ret=1
605  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
606  if [ $ret -ne 0 ]; then echo_i "failed"; fi
607  status=$((status + ret))
608
609  n=$((n + 1))
610  echo_i "check that dig processes +ednsopt=key-tag:<value-list> ($n)"
611  ret=0
612  dig_with_opts @10.53.0.3 +ednsopt=key-tag:00010002 a.example +qr >dig.out.test$n 2>&1 || ret=1
613  grep "; KEY-TAG: 1, 2$" dig.out.test$n >/dev/null || ret=1
614  grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1
615  check_ttl_range dig.out.test$n "A" 300 || ret=1
616  if [ $ret -ne 0 ]; then echo_i "failed"; fi
617  status=$((status + ret))
618
619  n=$((n + 1))
620  echo_i "check that dig processes +ednsopt=key-tag:<malformed-value-list> and FORMERR is returned ($n)"
621  ret=0
622  dig_with_opts @10.53.0.3 +ednsopt=key-tag:0001000201 a.example +qr >dig.out.test$n 2>&1 || ret=1
623  grep "; KEY-TAG: 00 01 00 02 01" dig.out.test$n >/dev/null || ret=1
624  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
625  if [ $ret -ne 0 ]; then echo_i "failed"; fi
626  status=$((status + ret))
627
628  n=$((n + 1))
629  echo_i "check that dig processes +ednsopt=client-tag:value ($n)"
630  ret=0
631  dig_with_opts @10.53.0.3 +ednsopt=client-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1
632  grep "; CLIENT-TAG: 1$" dig.out.test$n >/dev/null || ret=1
633  grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1
634  if [ $ret -ne 0 ]; then echo_i "failed"; fi
635  status=$((status + ret))
636
637  n=$((n + 1))
638  echo_i "check that FORMERR is returned for a too short client-tag ($n)"
639  ret=0
640  dig_with_opts @10.53.0.3 +ednsopt=client-tag:01 a.example +qr >dig.out.test$n 2>&1 || ret=1
641  grep "; CLIENT-TAG" dig.out.test$n >/dev/null || ret=1
642  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
643  if [ $ret -ne 0 ]; then echo_i "failed"; fi
644  status=$((status + ret))
645
646  n=$((n + 1))
647  echo_i "check that FORMERR is returned for a too long client-tag ($n)"
648  ret=0
649  dig_with_opts @10.53.0.3 +ednsopt=client-tag:000001 a.example +qr >dig.out.test$n 2>&1 || ret=1
650  grep "; CLIENT-TAG" dig.out.test$n >/dev/null || ret=1
651  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
652  if [ $ret -ne 0 ]; then echo_i "failed"; fi
653  status=$((status + ret))
654
655  n=$((n + 1))
656  echo_i "check that dig processes +ednsopt=server-tag:value ($n)"
657  ret=0
658  dig_with_opts @10.53.0.3 +ednsopt=server-tag:0001 a.example +qr >dig.out.test$n 2>&1 || ret=1
659  grep "; SERVER-TAG: 1$" dig.out.test$n >/dev/null || ret=1
660  grep "status: FORMERR" dig.out.test$n >/dev/null && ret=1
661  if [ $ret -ne 0 ]; then echo_i "failed"; fi
662  status=$((status + ret))
663
664  n=$((n + 1))
665  echo_i "check that FORMERR is returned for a too short server-tag ($n)"
666  ret=0
667  dig_with_opts @10.53.0.3 +ednsopt=server-tag:01 a.example +qr >dig.out.test$n 2>&1 || ret=1
668  grep "; SERVER-TAG" dig.out.test$n >/dev/null || ret=1
669  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
670  if [ $ret -ne 0 ]; then echo_i "failed"; fi
671  status=$((status + ret))
672
673  n=$((n + 1))
674  echo_i "check that FORMERR is returned for a too long server-tag ($n)"
675  ret=0
676  dig_with_opts @10.53.0.3 +ednsopt=server-tag:000001 a.example +qr >dig.out.test$n 2>&1 || ret=1
677  grep "; SERVER-TAG" dig.out.test$n >/dev/null || ret=1
678  grep "status: FORMERR" dig.out.test$n >/dev/null || ret=1
679  if [ $ret -ne 0 ]; then echo_i "failed"; fi
680  status=$((status + ret))
681
682  n=$((n + 1))
683  echo_i "check that Extended DNS Error 0 is printed correctly ($n)"
684  ret=0
685  # First defined EDE code, additional text "foo".
686  dig_with_opts @10.53.0.3 +ednsopt=ede:0000666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1
687  pat='^; EDE: 0 (Other): (foo)$'
688  grep "$pat" dig.out.test$n >/dev/null || ret=1
689  if [ $ret -ne 0 ]; then echo_i "failed"; fi
690  status=$((status + ret))
691
692  n=$((n + 1))
693  echo_i "check that Extended DNS Error 24 is printed correctly ($n)"
694  ret=0
695  # Last defined EDE code, no additional text.
696  dig_with_opts @10.53.0.3 +ednsopt=ede:0018 a.example +qr >dig.out.test$n 2>&1 || ret=1
697  pat='^; EDE: 24 (Invalid Data)$'
698  grep "$pat" dig.out.test$n >/dev/null || ret=1
699  if [ $ret -ne 0 ]; then echo_i "failed"; fi
700  status=$((status + ret))
701
702  n=$((n + 1))
703  echo_i "check that Extended DNS Error 25 is printed correctly ($n)"
704  ret=0
705  # First undefined EDE code, additional text "foo".
706  dig_with_opts @10.53.0.3 +ednsopt=ede:0019666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1
707  pat='^; EDE: 25: (foo)$'
708  grep "$pat" dig.out.test$n >/dev/null || ret=1
709  if [ $ret -ne 0 ]; then echo_i "failed"; fi
710  status=$((status + ret))
711
712  n=$((n + 1))
713  echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
714  ret=0
715  # EDE payload is too short
716  dig_with_opts @10.53.0.3 +ednsopt=ede a.example +qr >dig.out.test$n 2>&1 || ret=1
717  pat='^; EDE:$'
718  grep "$pat" dig.out.test$n >/dev/null || ret=1
719  if [ $ret -ne 0 ]; then echo_i "failed"; fi
720  status=$((status + ret))
721
722  n=$((n + 1))
723  echo_i "check that invalid Extended DNS Error (length 1) is printed ($n)"
724  ret=0
725  # EDE payload is too short
726  dig_with_opts @10.53.0.3 +ednsopt=ede:00 a.example +qr >dig.out.test$n 2>&1 || ret=1
727  pat='^; EDE: 00 (".")$'
728  grep "$pat" dig.out.test$n >/dev/null || ret=1
729  if [ $ret -ne 0 ]; then echo_i "failed"; fi
730  status=$((status + ret))
731
732  if [ $HAS_PYYAML -ne 0 ]; then
733    n=$((n + 1))
734    echo_i "check that +yaml Extended DNS Error 0 is printed correctly ($n)"
735    ret=0
736    # First defined EDE code, additional text "foo".
737    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0000666f6f a.example +qr >dig.out.test$n 2>&1 || ret=1
738    $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
739    read -r value <yamlget.out.test$n
740    [ "$value" = "0 (Other)" ] || ret=1
741    $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
742    read -r value <yamlget.out.test$n
743    [ "$value" = "foo" ] || ret=1
744    if [ $ret -ne 0 ]; then echo_i "failed"; fi
745    status=$((status + ret))
746
747    n=$((n + 1))
748    echo_i "check that +yaml Extended DNS Error 24 is printed correctly ($n)"
749    ret=0
750    # Last defined EDE code, no additional text.
751    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0018 a.example +qr >dig.out.test$n 2>&1 || ret=1
752    $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
753    read -r value <yamlget.out.test$n
754    [ "$value" = "24 (Invalid Data)" ] || ret=1
755    $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
756    if [ $ret -ne 0 ]; then echo_i "failed"; fi
757    status=$((status + ret))
758
759    n=$((n + 1))
760    echo_i "check that +yaml Extended DNS Error 25 is printed correctly ($n)"
761    ret=0
762    # First undefined EDE code, additional text "foo".
763    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:0019666f6f 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 INFO-CODE >yamlget.out.test$n 2>&1 || ret=1
765    read -r value <yamlget.out.test$n
766    [ "$value" = "25" ] || ret=1
767    $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
768    read -r value <yamlget.out.test$n
769    [ "$value" = "foo" ] || ret=1
770    if [ $ret -ne 0 ]; then echo_i "failed"; fi
771    status=$((status + ret))
772
773    n=$((n + 1))
774    echo_i "check that invalid Extended DNS Error (length 0) is printed ($n)"
775    ret=0
776    # EDE payload is too short
777    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede a.example +qr >dig.out.test$n 2>&1 || ret=1
778    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE >yamlget.out.test$n 2>&1 || ret=1
779    read -r value <yamlget.out.test$n
780    [ "$value" = "None" ] || ret=1
781    if [ $ret -ne 0 ]; then echo_i "failed"; fi
782    status=$((status + ret))
783
784    n=$((n + 1))
785    echo_i "check that invalid +yaml Extended DNS Error (length 1) is printed ($n)"
786    ret=0
787    # EDE payload is too short
788    dig_with_opts @10.53.0.3 +yaml +ednsopt=ede:00 a.example +qr >dig.out.test$n 2>&1 || ret=1
789    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data OPT_PSEUDOSECTION EDNS EDE >yamlget.out.test$n 2>&1 || ret=1
790    read -r value <yamlget.out.test$n
791    [ "$value" = '00 (".")' ] || ret=1
792    if [ $ret -ne 0 ]; then echo_i "failed"; fi
793    status=$((status + ret))
794  fi
795
796  n=$((n + 1))
797  echo_i "check that dig handles malformed option '+ednsopt=:' gracefully ($n)"
798  ret=0
799  dig_with_opts @10.53.0.3 +ednsopt=: a.example >dig.out.test$n 2>&1 && ret=1
800  grep "ednsopt no code point specified" dig.out.test$n >/dev/null || ret=1
801  if [ $ret -ne 0 ]; then echo_i "failed"; fi
802  status=$((status + ret))
803
804  n=$((n + 1))
805  echo_i "check that dig gracefully handles bad escape in domain name ($n)"
806  ret=0
807  digstatus=0
808  dig_with_opts @10.53.0.3 '\0.' >dig.out.test$n 2>&1 || digstatus=$?
809  echo digstatus=$digstatus >>dig.out.test$n
810  test $digstatus -eq 10 || ret=1
811  grep REQUIRE dig.out.test$n >/dev/null && ret=1
812  grep "is not a legal name (bad escape)" dig.out.test$n >/dev/null || ret=1
813  if [ $ret -ne 0 ]; then echo_i "failed"; fi
814  status=$((status + ret))
815
816  n=$((n + 1))
817  echo_i "check that dig -q -m works ($n)"
818  ret=0
819  dig_with_opts @10.53.0.3 -q -m >dig.out.test$n 2>&1
820  pat='^;-m\..*IN.*A$'
821  grep "$pat" dig.out.test$n >/dev/null || ret=1
822  grep "Dump of all outstanding memory allocations" dig.out.test$n >/dev/null && ret=1
823  if [ $ret -ne 0 ]; then echo_i "failed"; fi
824  status=$((status + ret))
825
826  n=$((n + 1))
827  echo_i "checking exit code for a retry upon TCP EOF (immediate -> immediate) ($n)"
828  ret=0
829  echo "no_response no_response" | sendcmd 10.53.0.5
830  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1
831  # Sanity check: ensure ans5 behaves as expected.
832  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
833  if [ $ret -ne 0 ]; then echo_i "failed"; fi
834  status=$((status + ret))
835
836  n=$((n + 1))
837  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> partial AXFR) ($n)"
838  ret=0
839  echo "partial_axfr partial_axfr" | sendcmd 10.53.0.5
840  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1
841  # Sanity check: ensure ans5 behaves as expected.
842  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
843  if [ $ret -ne 0 ]; then echo_i "failed"; fi
844  status=$((status + ret))
845
846  n=$((n + 1))
847  echo_i "checking exit code for a retry upon TCP EOF (immediate -> partial AXFR) ($n)"
848  ret=0
849  echo "no_response partial_axfr" | sendcmd 10.53.0.5
850  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1
851  # Sanity check: ensure ans5 behaves as expected.
852  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
853  if [ $ret -ne 0 ]; then echo_i "failed"; fi
854  status=$((status + ret))
855
856  n=$((n + 1))
857  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> immediate) ($n)"
858  ret=0
859  echo "partial_axfr no_response" | sendcmd 10.53.0.5
860  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 && ret=1
861  # Sanity check: ensure ans5 behaves as expected.
862  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 2 ] || ret=1
863  if [ $ret -ne 0 ]; then echo_i "failed"; fi
864  status=$((status + ret))
865
866  n=$((n + 1))
867  echo_i "checking exit code for a retry upon TCP EOF (immediate -> complete AXFR) ($n)"
868  ret=0
869  echo "no_response complete_axfr" | sendcmd 10.53.0.5
870  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 || ret=1
871  # Sanity check: ensure ans5 behaves as expected.
872  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
873  if [ $ret -ne 0 ]; then echo_i "failed"; fi
874  status=$((status + ret))
875
876  n=$((n + 1))
877  echo_i "checking exit code for a retry upon TCP EOF (partial AXFR -> complete AXFR) ($n)"
878  ret=0
879  echo "partial_axfr complete_axfr" | sendcmd 10.53.0.5
880  dig_with_opts @10.53.0.5 example AXFR +tries=2 >dig.out.test$n 2>&1 || ret=1
881  # Sanity check: ensure ans5 behaves as expected.
882  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
883  if [ $ret -ne 0 ]; then echo_i "failed"; fi
884  status=$((status + ret))
885
886  n=$((n + 1))
887  echo_i "checking +tries=1 won't retry twice upon TCP EOF ($n)"
888  ret=0
889  echo "no_response no_response" | sendcmd 10.53.0.5
890  dig_with_opts @10.53.0.5 example AXFR +tries=1 >dig.out.test$n 2>&1 && ret=1
891  # Sanity check: ensure ans5 behaves as expected.
892  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
893  if [ $ret -ne 0 ]; then echo_i "failed"; fi
894  status=$((status + ret))
895
896  n=$((n + 1))
897  echo_i "checking +retry=0 won't retry twice upon TCP EOF ($n)"
898  ret=0
899  dig_with_opts @10.53.0.5 example AXFR +retry=0 >dig.out.test$n 2>&1 && ret=1
900  # Sanity check: ensure ans5 behaves as expected.
901  [ $(grep "communications error.*end of file" dig.out.test$n | wc -l) -eq 1 ] || ret=1
902  if [ $ret -ne 0 ]; then echo_i "failed"; fi
903  status=$((status + ret))
904
905  n=$((n + 1))
906  echo_i "check that dig +expandaaaa works ($n)"
907  ret=0
908  dig_with_opts @10.53.0.3 +expandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1
909  grep "ns2.example.*fd92:7065:0b8e:ffff:0000:0000:0000:0002" dig.out.test$n >/dev/null || ret=1
910  if [ $ret -ne 0 ]; then echo_i "failed"; fi
911  status=$((status + ret))
912
913  n=$((n + 1))
914  echo_i "check that dig +noexpandaaaa works ($n)"
915  ret=0
916  dig_with_opts @10.53.0.3 +noexpandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1
917  grep "ns2.example.*fd92:7065:b8e:ffff::2" dig.out.test$n >/dev/null || ret=1
918  if [ $ret -ne 0 ]; then echo_i "failed"; fi
919  status=$((status + ret))
920
921  n=$((n + 1))
922  echo_i "check that dig default for +[no]expandaaa (+noexpandaaaa) works ($n)"
923  ret=0
924  dig_with_opts @10.53.0.3 AAAA ns2.example >dig.out.test$n 2>&1 || ret=1
925  grep "ns2.example.*fd92:7065:b8e:ffff::2" 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
931  echo_i "check that dig +short +expandaaaa works ($n)"
932  ret=0
933  dig_with_opts @10.53.0.3 +short +expandaaaa AAAA ns2.example >dig.out.test$n 2>&1 || ret=1
934  pat='^fd92:7065:0b8e:ffff:0000:0000:0000:0002$'
935  grep "$pat" dig.out.test$n >/dev/null || ret=1
936  if [ $ret -ne 0 ]; then echo_i "failed"; fi
937  status=$((status + ret))
938
939  if [ $HAS_PYYAML -ne 0 ]; then
940    n=$((n + 1))
941    echo_i "check dig +yaml output ($n)"
942    ret=0
943    dig_with_opts +qr +yaml @10.53.0.3 any ns2.example >dig.out.test$n 2>&1 || ret=1
944    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data status >yamlget.out.test$n 2>&1 || ret=1
945    read -r value <yamlget.out.test$n
946    [ "$value" = "NOERROR" ] || ret=1
947    $PYTHON yamlget.py dig.out.test$n 1 message response_message_data status >yamlget.out.test$n 2>&1 || ret=1
948    read -r value <yamlget.out.test$n
949    [ "$value" = "NOERROR" ] || ret=1
950    $PYTHON yamlget.py dig.out.test$n 1 message response_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
951    read -r value <yamlget.out.test$n
952    [ "$value" = "ns2.example. IN ANY" ] || ret=1
953    if [ $ret -ne 0 ]; then echo_i "failed"; fi
954    status=$((status + ret))
955
956    n=$((n + 1))
957    echo_i "check dig +yaml output of an IPv6 address ending in zeroes ($n)"
958    ret=0
959    dig_with_opts +qr +yaml @10.53.0.3 aaaa d.example >dig.out.test$n 2>&1 || ret=1
960    $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
961    read -r value <yamlget.out.test$n
962    [ "$value" = "d.example. 300 IN AAAA fd92:7065:b8e:ffff::0" ] || ret=1
963    if [ $ret -ne 0 ]; then echo_i "failed"; fi
964    status=$((status + ret))
965  fi
966
967  n=$((n + 1))
968  echo_i "check that dig +bufsize=0 just sets the buffer size to 0 ($n)"
969  ret=0
970  dig_with_opts @10.53.0.3 a.example +bufsize=0 +qr >dig.out.test$n 2>&1 || ret=1
971  grep "EDNS:" dig.out.test$n >/dev/null || ret=1
972  if [ $ret -ne 0 ]; then echo_i "failed"; fi
973  status=$((status + ret))
974
975  n=$((n + 1))
976  echo_i "check that dig +bufsize restores default bufsize ($n)"
977  ret=0
978  dig_with_opts @10.53.0.3 a.example +bufsize=0 +bufsize +qr >dig.out.test$n 2>&1 || ret=1
979  lines=$(grep "EDNS:.* udp:" dig.out.test$n | wc -l)
980  lines1232=$(grep "EDNS:.* udp: 1232" dig.out.test$n | wc -l)
981  test $lines -eq 2 || ret=1
982  test $lines1232 -eq 2 || ret=1
983  if [ $ret -ne 0 ]; then echo_i "failed"; fi
984  status=$((status + ret))
985
986  n=$((n + 1))
987  echo_i "check that dig without -u displays 'Query time' in millseconds ($n)"
988  ret=0
989  dig_with_opts @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
990  grep ';; Query time: [0-9][0-9]* msec' dig.out.test$n >/dev/null || ret=1
991  if [ $ret -ne 0 ]; then echo_i "failed"; fi
992  status=$((status + ret))
993
994  n=$((n + 1))
995  echo_i "check that dig -u displays 'Query time' in microseconds ($n)"
996  ret=0
997  dig_with_opts -u @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
998  grep ';; Query time: [0-9][0-9]* usec' dig.out.test$n >/dev/null || ret=1
999  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1000  status=$((status + ret))
1001
1002  n=$((n + 1))
1003  echo_i "check that dig +yaml without -u displays timestamps in milliseconds ($n)"
1004  ret=0
1005  dig_with_opts +yaml @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1006  grep 'query_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
1007  grep 'response_time: !!timestamp ....-..-..T..:..:..\....Z' dig.out.test$n >/dev/null || ret=1
1008  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1009  status=$((status + ret))
1010
1011  n=$((n + 1))
1012  echo_i "check that dig -u +yaml displays timestamps in microseconds ($n)"
1013  ret=0
1014  dig_with_opts -u +yaml @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1015  grep 'query_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
1016  grep 'response_time: !!timestamp ....-..-..T..:..:..\.......Z' dig.out.test$n >/dev/null || ret=1
1017  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1018  status=$((status + ret))
1019
1020  # See [GL #3020] for more information
1021  n=$((n + 1))
1022  echo_i "check that dig handles UDP timeout followed by a SERVFAIL correctly ($n)"
1023  # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes)
1024  echo "unstable" | sendcmd 10.53.0.8
1025  ret=0
1026  dig_with_opts +timeout=1 +nofail @10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1
1027  grep -F "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1028  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1029  status=$((status + ret))
1030
1031  n=$((n + 1))
1032  echo_i "check that dig handles TCP timeout followed by a SERVFAIL correctly ($n)"
1033  # Ask ans8 to be in "unstable" mode (switching between "silent" and "servfail" modes)
1034  echo "unstable" | sendcmd 10.53.0.8
1035  ret=0
1036  dig_with_opts +timeout=1 +nofail +tcp @10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1
1037  grep -F "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1038  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1039  status=$((status + ret))
1040
1041  n=$((n + 1))
1042  echo_i "check that dig tries the next server after a UDP socket network unreachable error ($n)"
1043  ret=0
1044  dig_with_opts @192.0.2.128 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1045  test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
1046  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1047  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1048  status=$((status + ret))
1049
1050  n=$((n + 1))
1051  echo_i "check that dig tries the next server after a TCP socket network unreachable error ($n)"
1052  ret=0
1053  dig_with_opts +tcp @192.0.2.128 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1054  test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
1055  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1056  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1057  status=$((status + ret))
1058
1059  n=$((n + 1))
1060  echo_i "check that dig tries the next server after a UDP socket read error ($n)"
1061  ret=0
1062  dig_with_opts @10.53.0.99 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1063  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1064  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1065  status=$((status + ret))
1066
1067  n=$((n + 1))
1068  echo_i "check that dig tries the next server after a TCP socket read error ($n)"
1069  # Ask ans8 to be in "close" mode, which closes the connection after accepting it
1070  echo "close" | sendcmd 10.53.0.8
1071  ret=0
1072  dig_with_opts +tcp @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1073  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1074  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1075  status=$((status + ret))
1076
1077  # Note that we combine TCP socket "connection error" and "timeout" cases in
1078  # one, because it is not trivial to simulate the timeout case in a system test
1079  # in Linux without a firewall, but the code which handles error cases during
1080  # the connection establishment time does not differentiate between timeout and
1081  # other types of errors (unlike during reading), so this one check should be
1082  # sufficient for both cases.
1083  n=$((n + 1))
1084  echo_i "check that dig tries the next server after a TCP socket connection error/timeout ($n)"
1085  ret=0
1086  dig_with_opts +tcp @10.53.0.99 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1087  test $(grep -F -e "connection refused" -e "timed out" -e "network unreachable" -e "host unreachable" dig.out.test$n | wc -l) -eq 3 || ret=1
1088  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1089  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1090  status=$((status + ret))
1091
1092  n=$((n + 1))
1093  echo_i "check that dig tries the next server after UDP socket read timeouts ($n)"
1094  # Ask ans8 to be in "silent" mode
1095  echo "silent" | sendcmd 10.53.0.8
1096  ret=0
1097  dig_with_opts +timeout=1 @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1098  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1099  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1100  status=$((status + ret))
1101
1102  n=$((n + 1))
1103  echo_i "check that dig tries the next server after TCP socket read timeouts ($n)"
1104  # Ask ans8 to be in "silent" mode
1105  echo "silent" | sendcmd 10.53.0.8
1106  ret=0
1107  dig_with_opts +timeout=1 +tcp @10.53.0.8 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1108  grep -F "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1109  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1110  status=$((status + ret))
1111
1112  # See [GL #3248] for more information
1113  n=$((n + 1))
1114  echo_i "check that dig correctly refuses to use a server with a IPv4 mapped IPv6 address after failing with a regular IP address ($n)"
1115  ret=0
1116  dig_with_opts @10.53.0.8 @::ffff:10.53.0.8 a.example >dig.out.test$n 2>&1 || ret=1
1117  grep -F ";; Skipping mapped address" dig.out.test$n >/dev/null || ret=1
1118  grep -F ";; No acceptable nameservers" dig.out.test$n >/dev/null || ret=1
1119  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1120  status=$((status + ret))
1121
1122  # See [GL #3244] for more information
1123  n=$((n + 1))
1124  echo_i "check that dig handles printing query information with +qr and +y when multiple queries are involved (including a failed query) ($n)"
1125  ret=0
1126  dig_with_opts +timeout=1 +qr +y @127.0.0.1 @10.53.0.3 a.example >dig.out.test$n 2>&1 || ret=1
1127  grep -F "IN A 10.0.0.1" dig.out.test$n >/dev/null || ret=1
1128  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1129  status=$((status + ret))
1130
1131  n=$((n + 1))
1132  echo_i "check that dig +noedns +ednsflags=<nonzero> re-enables EDNS ($n)"
1133  dig_with_opts @10.53.0.3 +qr +noedns +ednsflags=0x70 a.example >dig.out.test$n 2>&1 || ret=1
1134  grep "; EDNS: version: 0, flags:; MBZ: 0x0070, udp: 1232" dig.out.test$n >/dev/null || ret=1
1135  grep "; EDNS: version: 0, flags:; udp: 1232" dig.out.test$n >/dev/null || ret=1
1136  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1137  status=$((status + ret))
1138else
1139  echo_i "$DIG is needed, so skipping these dig tests"
1140fi
1141
1142if [ -x "$MDIG" ]; then
1143  n=$((n + 1))
1144  echo_i "checking mdig +tcp works with a source address and port ($n)"
1145  ret=0
1146  # When running more than once in quick succession with a source address#port,
1147  # we can get a "response failed with address not available" error because
1148  # the address#port is still busy, but we are not interested in that error,
1149  # as we are only looking for the unexpected error case, that's why we ignore
1150  # the return code from mdig, but we check for the unexpected error message
1151  # using grep. See GitLab #4969.
1152  mdig_with_opts -b "10.53.0.3#${EXTRAPORT8}" +tcp @10.53.0.3 example >dig.out.test$n 2>&1 || true
1153  grep -F "unexpected error" dig.out.test$n >/dev/null && ret=1
1154  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1155  status=$((status + ret))
1156
1157  n=$((n + 1))
1158  echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)"
1159  ret=0
1160  mdig_with_opts @10.53.0.3 +ednsopt=: a.example >dig.out.test$n 2>&1 && ret=1
1161  grep "ednsopt no code point specified" dig.out.test$n >/dev/null || ret=1
1162  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1163  status=$((status + ret))
1164
1165  n=$((n + 1))
1166  echo_i "checking mdig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
1167  ret=0
1168  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example >dig.out.test$n || ret=1
1169  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n && ret=1
1170  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1171  status=$((status + ret))
1172
1173  n=$((n + 1))
1174  echo_i "checking mdig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
1175  ret=0
1176  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example >dig.out.test$n || ret=1
1177  grep "; serial" <dig.out.test$n >/dev/null && ret=1
1178  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1179  status=$((status + ret))
1180
1181  if [ $HAS_PYYAML -ne 0 ]; then
1182    n=$((n + 1))
1183    echo_i "check mdig +yaml output ($n)"
1184    ret=0
1185    mdig_with_opts +yaml @10.53.0.3 -t any ns2.example >dig.out.test$n 2>&1 || ret=1
1186    $PYTHON yamlget.py dig.out.test$n 0 message response_message_data status >yamlget.out.test$n 2>&1 || ret=1
1187    read -r value <yamlget.out.test$n
1188    [ "$value" = "NOERROR" ] || ret=1
1189    $PYTHON yamlget.py dig.out.test$n 0 message response_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
1190    read -r value <yamlget.out.test$n
1191    [ "$value" = "ns2.example. IN ANY" ] || ret=1
1192    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1193    status=$((status + ret))
1194  fi
1195else
1196  echo_i "$MDIG is needed, so skipping these mdig tests"
1197fi
1198
1199if [ -x "$DELV" ]; then
1200  n=$((n + 1))
1201  echo_i "checking delv short form works ($n)"
1202  ret=0
1203  delv_with_opts @10.53.0.3 +short a a.example >delv.out.test$n || ret=1
1204  test "$(wc -l <delv.out.test$n)" -eq 1 || ret=1
1205  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1206  status=$((status + ret))
1207
1208  n=$((n + 1))
1209  echo_i "checking delv split width works ($n)"
1210  ret=0
1211  delv_with_opts @10.53.0.3 +split=4 -t sshfp foo.example >delv.out.test$n || ret=1
1212  grep " 9ABC DEF6 7890 " <delv.out.test$n >/dev/null || ret=1
1213  check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
1214  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1215  status=$((status + ret))
1216
1217  n=$((n + 1))
1218  echo_i "checking delv +unknownformat works ($n)"
1219  ret=0
1220  delv_with_opts @10.53.0.3 +unknownformat a a.example >delv.out.test$n || ret=1
1221  grep "CLASS1[ 	][ 	]*TYPE1[ 	][ 	]*\\\\# 4 0A000001" <delv.out.test$n >/dev/null || ret=1
1222  check_ttl_range delv.out.test$n "TYPE1" 300 || ret=1
1223  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1224  status=$((status + ret))
1225
1226  n=$((n + 1))
1227  echo_i "checking delv -4 -6 ($n)"
1228  ret=0
1229  delv_with_opts @10.53.0.3 -4 -6 A a.example >delv.out.test$n 2>&1 && ret=1
1230  grep "only one of -4 and -6 allowed" <delv.out.test$n >/dev/null || ret=1
1231  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1232  status=$((status + ret))
1233
1234  n=$((n + 1))
1235  echo_i "checking delv with IPv6 on IPv4 does not work ($n)"
1236  if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null; then
1237    ret=0
1238    # following should fail because @IPv4 overrides earlier @IPv6 above
1239    # and -6 forces IPv6 so this should fail, with a message
1240    # "Use of IPv4 disabled by -6"
1241    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
1242    # it should have no results but error output
1243    grep "testing" <delv.out.test$n >/dev/null && ret=1
1244    grep "Use of IPv4 disabled by -6" delv.out.test$n >/dev/null || ret=1
1245    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1246    status=$((status + ret))
1247  else
1248    echo_i "IPv6 unavailable; skipping"
1249  fi
1250
1251  n=$((n + 1))
1252  echo_i "checking delv with IPv4 on IPv6 does not work ($n)"
1253  if testsock6 fd92:7065:b8e:ffff::3 2>/dev/null; then
1254    ret=0
1255    # following should fail because @IPv6 overrides earlier @IPv4 above
1256    # and -4 forces IPv4 so this should fail, with a message
1257    # "Use of IPv6 disabled by -4"
1258    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
1259    # it should have no results but error output
1260    grep "testing" delv.out.test$n >/dev/null && ret=1
1261    grep "Use of IPv6 disabled by -4" delv.out.test$n >/dev/null || ret=1
1262    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1263    status=$((status + ret))
1264  else
1265    echo_i "IPv6 unavailable; skipping"
1266  fi
1267
1268  n=$((n + 1))
1269  echo_i "checking delv with reverse lookup works ($n)"
1270  ret=0
1271  delv_with_opts @10.53.0.3 -x 127.0.0.1 >delv.out.test$n 2>&1 || ret=1
1272  # doesn't matter if has answer
1273  grep -i "127\\.in-addr\\.arpa\\." <delv.out.test$n >/dev/null || ret=1
1274  check_ttl_range delv.out.test$n '\\-ANY' 10800 3 || ret=1
1275  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1276  status=$((status + ret))
1277
1278  n=$((n + 1))
1279  echo_i "checking delv over TCP works ($n)"
1280  ret=0
1281  delv_with_opts +tcp @10.53.0.3 a a.example >delv.out.test$n || ret=1
1282  grep "10\\.0\\.0\\.1$" <delv.out.test$n >/dev/null || ret=1
1283  check_ttl_range delv.out.test$n "A" 300 || ret=1
1284  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1285  status=$((status + ret))
1286
1287  n=$((n + 1))
1288  echo_i "checking delv +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
1289  ret=0
1290  delv_with_opts +tcp @10.53.0.3 +multi +norrcomments DNSKEY example >delv.out.test$n || ret=1
1291  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <delv.out.test$n >/dev/null && ret=1
1292  check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
1293  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1294  status=$((status + ret))
1295
1296  n=$((n + 1))
1297  echo_i "checking delv +multi +norrcomments works for SOA (when default is rrcomments)($n)"
1298  ret=0
1299  delv_with_opts +tcp @10.53.0.3 +multi +norrcomments SOA example >delv.out.test$n || ret=1
1300  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <delv.out.test$n >/dev/null && ret=1
1301  check_ttl_range delv.out.test$n "SOA" 300 || ret=1
1302  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1303  status=$((status + ret))
1304
1305  n=$((n + 1))
1306  echo_i "checking delv +rrcomments works for DNSKEY($n)"
1307  ret=0
1308  delv_with_opts +tcp @10.53.0.3 +rrcomments DNSKEY example >delv.out.test$n || ret=1
1309  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <delv.out.test$n >/dev/null || ret=1
1310  check_ttl_range delv.out.test$n "DNSKEY" 300 || ret=1
1311  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1312  status=$((status + ret))
1313
1314  n=$((n + 1))
1315  echo_i "checking delv +short +rrcomments works for DNSKEY ($n)"
1316  ret=0
1317  delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >delv.out.test$n || ret=1
1318  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <delv.out.test$n >/dev/null || ret=1
1319  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1320  status=$((status + ret))
1321
1322  n=$((n + 1))
1323  echo_i "checking delv +short +rrcomments works ($n)"
1324  ret=0
1325  delv_with_opts +tcp @10.53.0.3 +short +rrcomments DNSKEY example >delv.out.test$n || ret=1
1326  grep -q "$KEYDATA  ; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" <delv.out.test$n || ret=1
1327  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1328  status=$((status + ret))
1329
1330  n=$((n + 1))
1331  echo_i "checking delv +short +nosplit works ($n)"
1332  ret=0
1333  delv_with_opts +tcp @10.53.0.3 +short +nosplit DNSKEY example >delv.out.test$n || ret=1
1334  grep -q "$NOSPLIT" <delv.out.test$n || ret=1
1335  test "$(wc -l <delv.out.test$n)" -eq 1 || ret=1
1336  test "$(awk '{print NF}' <delv.out.test$n)" -eq 14 || ret=1
1337  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1338  status=$((status + ret))
1339
1340  n=$((n + 1))
1341  echo_i "checking delv +short +nosplit +norrcomments works ($n)"
1342  ret=0
1343  delv_with_opts +tcp @10.53.0.3 +short +nosplit +norrcomments DNSKEY example >delv.out.test$n || ret=1
1344  grep -q "$NOSPLIT\$" <delv.out.test$n || ret=1
1345  test "$(wc -l <delv.out.test$n)" -eq 1 || ret=1
1346  test "$(awk '{print NF}' <delv.out.test$n)" -eq 4 || ret=1
1347  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1348  status=$((status + ret))
1349
1350  n=$((n + 1))
1351  echo_i "checking delv +sp works as an abbriviated form of split ($n)"
1352  ret=0
1353  delv_with_opts @10.53.0.3 +sp=4 -t sshfp foo.example >delv.out.test$n || ret=1
1354  grep " 9ABC DEF6 7890 " <delv.out.test$n >/dev/null || ret=1
1355  check_ttl_range delv.out.test$n "SSHFP" 300 || ret=1
1356  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1357  status=$((status + ret))
1358
1359  n=$((n + 1))
1360  echo_i "checking delv +sh works as an abbriviated form of short ($n)"
1361  ret=0
1362  delv_with_opts @10.53.0.3 +sh a a.example >delv.out.test$n || ret=1
1363  test "$(wc -l <delv.out.test$n)" -eq 1 || ret=1
1364  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1365  status=$((status + ret))
1366
1367  n=$((n + 1))
1368  echo_i "checking delv -c IN works ($n)"
1369  ret=0
1370  delv_with_opts @10.53.0.3 -c IN -t a a.example >delv.out.test$n || ret=1
1371  grep "a.example." <delv.out.test$n >/dev/null || ret=1
1372  check_ttl_range delv.out.test$n "A" 300 || ret=1
1373  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1374  status=$((status + ret))
1375
1376  n=$((n + 1))
1377  echo_i "checking delv -c CH is ignored, and treated like IN ($n)"
1378  ret=0
1379  delv_with_opts @10.53.0.3 -c CH -t a a.example >delv.out.test$n || ret=1
1380  grep "a.example." <delv.out.test$n >/dev/null || ret=1
1381  check_ttl_range delv.out.test$n "A" 300 || ret=1
1382  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1383  status=$((status + ret))
1384
1385  n=$((n + 1))
1386  echo_i "checking delv H is ignored, and treated like IN ($n)"
1387  ret=0
1388  delv_with_opts @10.53.0.3 -c CH -t a a.example >delv.out.test$n || ret=1
1389  grep "a.example." <delv.out.test$n >/dev/null || ret=1
1390  check_ttl_range delv.out.test$n "A" 300 || ret=1
1391  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1392  status=$((status + ret))
1393
1394  n=$((n + 1))
1395  echo_i "check that delv -q -m works ($n)"
1396  ret=0
1397  delv_with_opts @10.53.0.3 -q -m >delv.out.test$n 2>&1 || ret=1
1398  grep '^; -m\..*[0-9]*.*IN.*ANY.*;' delv.out.test$n >/dev/null || ret=1
1399  grep "^add " delv.out.test$n >/dev/null && ret=1
1400  grep "^del " delv.out.test$n >/dev/null && ret=1
1401  check_ttl_range delv.out.test$n '\\-ANY' 300 3 || ret=1
1402  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1403  status=$((status + ret))
1404
1405  n=$((n + 1))
1406  echo_i "check that delv -t ANY works ($n)"
1407  ret=0
1408  delv_with_opts @10.53.0.3 -t ANY example >delv.out.test$n 2>&1 || ret=1
1409  grep "^example." <delv.out.test$n >/dev/null || ret=1
1410  check_ttl_range delv.out.test$n NS 300 || ret=1
1411  check_ttl_range delv.out.test$n SOA 300 || ret=1
1412  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1413  status=$((status + ret))
1414
1415  n=$((n + 1))
1416  echo_i "check that delv loads key-style trust anchors ($n)"
1417  ret=0
1418  delv_with_opts -a ns3/anchor.dnskey +root=example @10.53.0.3 -t DNSKEY example >delv.out.test$n 2>&1 || ret=1
1419  grep "fully validated" delv.out.test$n >/dev/null || ret=1
1420  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1421  status=$((status + ret))
1422
1423  n=$((n + 1))
1424  echo_i "check that delv loads DS-style trust anchors ($n)"
1425  ret=0
1426  delv_with_opts -a ns3/anchor.ds +root=example @10.53.0.3 -t DNSKEY example >delv.out.test$n 2>&1 || ret=1
1427  grep "fully validated" delv.out.test$n >/dev/null || ret=1
1428  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1429  status=$((status + ret))
1430
1431  if [ $HAS_PYYAML -ne 0 ]; then
1432    n=$((n + 1))
1433    echo_i "check delv +yaml output ($n)"
1434    ret=0
1435    delv_with_opts +yaml @10.53.0.3 any ns2.example >delv.out.test$n || ret=1
1436    $PYTHON yamlget.py delv.out.test$n status >yamlget.out.test$n 2>&1 || ret=1
1437    read -r value <yamlget.out.test$n
1438    [ "$value" = "success" ] || ret=1
1439    $PYTHON yamlget.py delv.out.test$n query_name >yamlget.out.test$n 2>&1 || ret=1
1440    read -r value <yamlget.out.test$n
1441    [ "$value" = "ns2.example" ] || ret=1
1442    $PYTHON yamlget.py delv.out.test$n records 0 answer_not_validated 0 >yamlget.out.test$n 2>&1 || ret=1
1443    read -r value <yamlget.out.test$n
1444    count=$(echo $value | wc -w)
1445    [ ${count:-0} -eq 5 ] || ret=1
1446    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1447    status=$((status + ret))
1448  fi
1449
1450  n=$((n + 1))
1451  echo_i "check that delv handles REFUSED when chasing DS records ($n)"
1452  delv_with_opts @10.53.0.2 +root xxx.example.tld A >delv.out.test$n 2>&1 || ret=1
1453  grep ";; resolution failed: broken trust chain" delv.out.test$n >/dev/null || ret=1
1454  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1455  status=$((status + ret))
1456
1457  n=$((n + 1))
1458  echo_i "check NS output from delv +ns ($n)"
1459  delv_with_opts -i +ns +nortrace +nostrace +nomtrace +novtrace +hint=../_common/root.hint ns example >delv.out.test$n || ret=1
1460  lines=$(awk '$1 == "example." && $4 == "NS" {print}' delv.out.test$n | wc -l)
1461  [ $lines -eq 2 ] || ret=1
1462  status=$((status + ret))
1463
1464  n=$((n + 1))
1465  echo_i "checking delv +ns (no validation) ($n)"
1466  ret=0
1467  delv_with_opts -i +ns +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1
1468  grep -q '; authoritative' delv.out.test$n || ret=1
1469  grep -q '_.example' delv.out.test$n && ret=1
1470  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1471  status=$((status + ret))
1472
1473  n=$((n + 1))
1474  echo_i "checking delv +ns +qmin (no validation) ($n)"
1475  ret=0
1476  delv_with_opts -i +ns +qmin +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1
1477  grep -q '; authoritative' delv.out.test$n || ret=1
1478  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1479  status=$((status + ret))
1480
1481  n=$((n + 1))
1482  echo_i "checking delv +ns (with validation) ($n)"
1483  ret=0
1484  delv_with_opts -a ns1/anchor.dnskey +root +ns +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1
1485  grep -q '; fully validated' delv.out.test$n || ret=1
1486  grep -q '_.example' delv.out.test$n && ret=1
1487  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1488  status=$((status + ret))
1489
1490  n=$((n + 1))
1491  echo_i "checking delv +ns +qmin (with validation) ($n)"
1492  ret=0
1493  delv_with_opts -a ns1/anchor.dnskey +root +ns +qmin +hint=../_common/root.hint a a.example >delv.out.test$n || ret=1
1494  grep -q '; fully validated' delv.out.test$n || ret=1
1495  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1496  status=$((status + ret))
1497
1498else
1499  echo_i "$DELV is needed, so skipping these delv tests"
1500fi
1501
1502if [ $HAS_PYYAML -ne 0 ]; then
1503  for qname in "yaml" "'.yaml" "[.yaml" "{.yaml" "&.yaml" "#.yaml"; do
1504    n=$((n + 1))
1505    echo_i "check yaml special '${yaml}.example' ($n)"
1506    ret=0
1507    dig_with_opts @10.53.0.3 +yaml "${qname}.example" TXT +qr >dig.out.test$n 2>&1 || ret=1
1508    $PYTHON yamlget.py dig.out.test$n 0 message query_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
1509    read -r value <yamlget.out.test$n
1510    [ "$value" = "${qname}.example. IN TXT" ] || ret=1
1511    $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
1512    read -r value <yamlget.out.test$n
1513    [ "$value" = "${qname}"'.example. 300 IN TXT "a: b"' ] || ret=1
1514    if [ $ret -ne 0 ]; then echo_i "failed"; fi
1515    status=$((status + ret))
1516  done
1517
1518  n=$((n + 1))
1519  echo_i "check yaml character values ($n)"
1520  ret=0
1521  dig_with_opts @10.53.0.3 +yaml "all.yaml.example" TXT +qr >dig.out.test$n 2>&1 || ret=1
1522  $PYTHON yamlget.py dig.out.test$n 1 message response_message_data ANSWER_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
1523  read -r value <yamlget.out.test$n
1524  expected='all.yaml.example. 300 IN TXT'
1525  expected="$expected "'"\000" "\001" "\002" "\003" "\004" "\005" "\006" "\007"'
1526  expected="$expected "'"\008" "\009" "\010" "\011" "\012" "\013" "\014" "\015"'
1527  expected="$expected "'"\016" "\017" "\018" "\019" "\020" "\021" "\022" "\023"'
1528  expected="$expected "'"\024" "\025" "\026" "\027" "\028" "\029" "\030" "\031"'
1529  expected="$expected "'" " "!" "\"" "#" "$" "%" "&" "'"'"'" "(" ")" "*" "+" ","'
1530  expected="$expected "'"-" "." "/" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" ":"'
1531  expected="$expected "'";" "<" "=" ">" "?" "@" "A" "B" "C" "D" "E" "F" "G" "H"'
1532  expected="$expected "'"I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V"'
1533  expected="$expected "'"W" "X" "Y" "Z" "[" "\\" "]" "^" "_" "`" "a" "b" "c" "d"'
1534  expected="$expected "'"e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r"'
1535  expected="$expected "'"s" "t" "u" "v" "w" "x" "y" "z" "{" "|" "}" "~" "\127"'
1536  expected="$expected "'"\128" "\129" "\130" "\131" "\132" "\133" "\134" "\135"'
1537  expected="$expected "'"\136" "\137" "\138" "\139" "\140" "\141" "\142" "\143"'
1538  expected="$expected "'"\144" "\145" "\146" "\147" "\148" "\149" "\150" "\151"'
1539  expected="$expected "'"\152" "\153" "\154" "\155" "\156" "\157" "\158" "\159"'
1540  expected="$expected "'"\160" "\161" "\162" "\163" "\164" "\165" "\166" "\167"'
1541  expected="$expected "'"\168" "\169" "\170" "\171" "\172" "\173" "\174" "\175"'
1542  expected="$expected "'"\176" "\177" "\178" "\179" "\180" "\181" "\182" "\183"'
1543  expected="$expected "'"\184" "\185" "\186" "\187" "\188" "\189" "\190" "\191"'
1544  expected="$expected "'"\192" "\193" "\194" "\195" "\196" "\197" "\198" "\199"'
1545  expected="$expected "'"\200" "\201" "\202" "\203" "\204" "\205" "\206" "\207"'
1546  expected="$expected "'"\208" "\209" "\210" "\211" "\212" "\213" "\214" "\215"'
1547  expected="$expected "'"\216" "\217" "\218" "\219" "\220" "\221" "\222" "\223"'
1548  expected="$expected "'"\224" "\225" "\226" "\227" "\228" "\229" "\230" "\231"'
1549  expected="$expected "'"\232" "\233" "\234" "\235" "\236" "\237" "\238" "\239"'
1550  expected="$expected "'"\240" "\241" "\242" "\243" "\244" "\245" "\246" "\247"'
1551  expected="$expected "'"\248" "\249" "\250" "\251" "\252" "\253" "\254" "\255"'
1552  [ "$value" = "$expected" ] || ret=1
1553  if [ $ret -ne 0 ]; then echo_i "failed"; fi
1554  status=$((status + ret))
1555fi
1556
1557echo_i "exit status: $status"
1558[ $status -eq 0 ] || exit 1
1559