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# touch dnsrps-off to not test with DNSRPS
17# touch dnsrps-only to not test with classic RPZ
18
19. ../conf.sh
20
21status=0
22
23t=0
24
25DEBUG=
26ARGS=
27
28USAGE="$0: [-xS]"
29while getopts "xS:" c; do
30  case $c in
31    x)
32      set -x
33      DEBUG=-x
34      ARGS="$ARGS -x"
35      ;;
36    S)
37      SAVE_RESULTS=-S
38      ARGS="$ARGS -S"
39      ;;
40    *)
41      echo "$USAGE" 1>&2
42      exit 1
43      ;;
44  esac
45done
46shift $((OPTIND - 1))
47if test "$#" -ne 0; then
48  echo "$USAGE" 1>&2
49  exit 1
50fi
51# really quit on control-C
52trap 'exit 1' 1 2 15
53
54DNSRPSCMD=../rpz/dnsrps
55RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s"
56
57# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists)
58run_server() {
59  TESTNAME=$1
60
61  echo_i "stopping resolver"
62  stop_server --use-rndc --port ${CONTROLPORT} ns2
63
64  sleep 1
65
66  echo_i "starting resolver using named.$TESTNAME.conf"
67  cp -f ns2/named.$TESTNAME.conf ns2/named.conf
68  start_server --noclean --restart --port ${PORT} ns2
69  sleep 3
70}
71
72run_query() {
73  TESTNAME=$1
74  LINE=$2
75
76  NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
77  $DIG $DIGOPTS $NAME a @10.53.0.2 -p ${PORT} -b 127.0.0.1 >dig.out.${t}
78  grep "status: SERVFAIL" dig.out.${t} >/dev/null 2>&1 && return 1
79  return 0
80}
81
82# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
83# $2 = line number in query file to test (the name to query is taken from this line)
84expect_norecurse() {
85  TESTNAME=$1
86  LINE=$2
87
88  NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
89  t=$((t + 1))
90  echo_i "testing $NAME doesn't recurse (${t})"
91  add_test_marker 10.53.0.2
92  run_query $TESTNAME $LINE || {
93    echo_i "test ${t} failed"
94    status=1
95  }
96}
97
98# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists)
99# $2 = line number in query file to test (the name to query is taken from this line)
100expect_recurse() {
101  TESTNAME=$1
102  LINE=$2
103
104  NAME=$(sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1)
105  t=$((t + 1))
106  echo_i "testing $NAME recurses (${t})"
107  add_test_marker 10.53.0.2
108  run_query $TESTNAME $LINE && {
109    echo_i "test ${t} failed"
110    status=1
111  }
112  return 0
113}
114
115add_test_marker() {
116  for ns in $@; do
117    $RNDCCMD $ns null ---- test ${t} ----
118  done
119}
120
121native=0
122dnsrps=0
123for mode in native dnsrps; do
124  status=0
125  case $mode in
126    native)
127      if [ -e dnsrps-only ]; then
128        echo_i "'dnsrps-only' found: skipping native RPZ sub-test"
129        continue
130      else
131        echo_i "running native RPZ sub-test"
132      fi
133      ;;
134    dnsrps)
135      if [ -e dnsrps-off ]; then
136        echo_i "'dnsrps-off' found: skipping DNSRPS sub-test"
137        continue
138      fi
139      echo_i "attempting to configure servers with DNSRPS..."
140      stop_server --use-rndc --port ${CONTROLPORT}
141      $SHELL ./setup.sh -N -D $DEBUG
142      sed -n 's/^## //p' dnsrps.conf | cat_i
143      if grep '^#fail' dnsrps.conf >/dev/null; then
144        echo_i "exit status: 1"
145        exit 1
146      fi
147      if grep '^#skip' dnsrps.conf >/dev/null; then
148        echo_i "DNSRPS sub-test skipped"
149        continue
150      else
151        echo_i "running DNSRPS sub-test"
152        start_server --noclean --restart --port ${PORT}
153        sleep 3
154      fi
155      ;;
156  esac
157
158  # show whether and why DNSRPS is enabled or disabled
159  sed -n 's/^## //p' dnsrps.conf | cat_i
160
161  t=$((t + 1))
162  echo_i "testing that l1.l0 exists without RPZ (${t})"
163  add_test_marker 10.53.0.2
164  $DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p ${PORT} >dig.out.${t}
165  grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || {
166    echo_i "test ${t} failed"
167    status=1
168  }
169
170  t=$((t + 1))
171  echo_i "testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})"
172  add_test_marker 10.53.0.2
173  $DIG $DIGOPTS l2.l1.l0 ns @10.53.0.2 -p ${PORT} >dig.out.${t}
174  grep "status: SERVFAIL" dig.out.${t} >/dev/null 2>&1 || {
175    echo_i "test ${t} failed"
176    status=1
177  }
178
179  # Group 1
180  run_server 1a
181  expect_norecurse 1a 1
182  run_server 1b
183  expect_norecurse 1b 1
184  expect_recurse 1b 2
185  run_server 1c
186  expect_norecurse 1c 1
187
188  # Group 2
189  run_server 2a
190  for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
191    21 22 23 24 25 26 27 28 29 30 31 32; do
192    expect_norecurse 2a $n
193  done
194  expect_recurse 2a 33
195
196  # Group 3
197  run_server 3a
198  expect_recurse 3a 1
199  run_server 3b
200  expect_recurse 3b 1
201  run_server 3c
202  expect_recurse 3c 1
203  run_server 3d
204  expect_norecurse 3d 1
205  expect_recurse 3d 2
206  run_server 3e
207  expect_norecurse 3e 1
208  expect_recurse 3e 2
209  run_server 3f
210  expect_norecurse 3f 1
211  expect_recurse 3f 2
212
213  # Group 4
214  testlist="aa ap bf"
215  values="1 16 32"
216  # Uncomment the following to test every skip value instead of
217  # only a sample of values
218  #
219  #testlist="aa ab ac ad ae af ag ah ai aj ak al am an ao ap \
220  #          aq ar as at au av aw ax ay az ba bb bc bd be bf"
221  #values="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
222  #        21 22 23 24 25 26 27 28 29 30 31 32"
223  set -- $values
224  for n in $testlist; do
225    run_server 4$n
226    ni=$1
227    t=$((t + 1))
228    echo_i "testing that ${ni} of 33 queries skip recursion (${t})"
229    add_test_marker 10.53.0.2
230    c=0
231    for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \
232      17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33; do
233      run_query 4$n $i || c=$((c + 1))
234    done
235    skipped=$((33 - c))
236    if [ $skipped != $ni ]; then
237      echo_i "test $t failed (actual=$skipped, expected=$ni)"
238      status=1
239    fi
240    shift
241  done
242
243  # Group 5
244  run_server 5a
245  expect_norecurse 5a 1
246  expect_norecurse 5a 2
247  expect_recurse 5a 3
248  expect_recurse 5a 4
249  expect_recurse 5a 5
250  expect_recurse 5a 6
251
252  # Group 6
253  echo_i "check recursive behavior consistency during policy update races"
254  run_server 6a
255  sleep 1
256  t=$((t + 1))
257  echo_i "running dig to cache CNAME record (${t})"
258  add_test_marker 10.53.0.1 10.53.0.2
259  $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME >dig.out.${t}
260  sleep 1
261  echo_i "suspending authority server"
262  PID=$(cat ns1/named.pid)
263  kill -STOP $PID
264  echo_i "adding an NSDNAME policy"
265  cp ns2/db.6a.00.policy.local ns2/saved.policy.local
266  cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
267  $RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
268  test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
269  sleep 1
270  t=$((t + 1))
271  echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
272  add_test_marker 10.53.0.2
273  $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 >dig.out.${t} &
274  sleep 1
275  echo_i "removing the NSDNAME policy"
276  cp ns2/db.6c.00.policy.local ns2/db.6a.00.policy.local
277  $RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
278  test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
279  sleep 1
280  echo_i "resuming authority server"
281  PID=$(cat ns1/named.pid)
282  kill -CONT $PID
283  add_test_marker 10.53.0.1
284  for n in 1 2 3 4 5 6 7 8 9; do
285    sleep 1
286    [ -s dig.out.${t} ] || continue
287    grep "status: .*," dig.out.${t} >/dev/null 2>&1 && break
288  done
289  grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || {
290    echo_i "test ${t} failed"
291    status=1
292  }
293
294  echo_i "check recursive behavior consistency during policy removal races"
295  cp ns2/saved.policy.local ns2/db.6a.00.policy.local
296  run_server 6a
297  sleep 1
298  t=$((t + 1))
299  echo_i "running dig to cache CNAME record (${t})"
300  add_test_marker 10.53.0.1 10.53.0.2
301  $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME >dig.out.${t}
302  sleep 1
303  echo_i "suspending authority server"
304  PID=$(cat ns1/named.pid)
305  kill -STOP $PID
306  echo_i "adding an NSDNAME policy"
307  cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local
308  $RNDC -c ../_common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i
309  test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
310  sleep 1
311  t=$((t + 1))
312  echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})"
313  add_test_marker 10.53.0.2
314  $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 >dig.out.${t} &
315  sleep 1
316  echo_i "removing the policy zone"
317  cp ns2/named.default.conf ns2/named.conf
318  rndc_reconfig ns2 10.53.0.2
319  test -f dnsrpzd.pid && kill -USR1 $(cat dnsrpzd.pid) || true
320  sleep 1
321  echo_i "resuming authority server"
322  PID=$(cat ns1/named.pid)
323  kill -CONT $PID
324  add_test_marker 10.53.0.1
325  for n in 1 2 3 4 5 6 7 8 9; do
326    sleep 1
327    [ -s dig.out.${t} ] || continue
328    grep "status: .*," dig.out.${t} >/dev/null 2>&1 && break
329  done
330  grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || {
331    echo_i "test ${t} failed"
332    status=1
333  }
334
335  # Check maximum number of RPZ zones (64)
336  t=$((t + 1))
337  echo_i "testing maximum number of RPZ zones (${t})"
338  add_test_marker 10.53.0.2
339  run_server max
340  i=1
341  while test $i -le 64; do
342    $DIG $DIGOPTS name$i a @10.53.0.2 -p ${PORT} -b 10.53.0.1 >dig.out.${t}.${i}
343    grep "^name$i.[ 	]*[0-9]*[ 	]*IN[ 	]*A[ 	]*10.53.0.$i" dig.out.${t}.${i} >/dev/null 2>&1 || {
344      echo_i "test $t failed: didn't get expected answer from policy zone $i"
345      status=1
346    }
347    i=$((i + 1))
348  done
349
350  # Check CLIENT-IP behavior
351  t=$((t + 1))
352  echo_i "testing CLIENT-IP behavior (${t})"
353  add_test_marker 10.53.0.2
354  run_server clientip
355  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t}
356  grep "status: NOERROR" dig.out.${t} >/dev/null 2>&1 || {
357    echo_i "test $t failed: query failed"
358    status=1
359  }
360  grep "^l2.l1.l0.[ 	]*[0-9]*[ 	]*IN[ 	]*A[ 	]*10.53.0.2" dig.out.${t} >/dev/null 2>&1 || {
361    echo_i "test $t failed: didn't get expected answer"
362    status=1
363  }
364
365  # Check CLIENT-IP behavior #2
366  t=$((t + 1))
367  echo_i "testing CLIENT-IP behavior #2 (${t})"
368  add_test_marker 10.53.0.2
369  run_server clientip2
370  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.1 >dig.out.${t}.1
371  grep "status: SERVFAIL" dig.out.${t}.1 >/dev/null 2>&1 || {
372    echo_i "test $t failed: query failed"
373    status=1
374  }
375  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >dig.out.${t}.2
376  grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null 2>&1 || {
377    echo_i "test $t failed: query failed"
378    status=1
379  }
380  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >dig.out.${t}.3
381  grep "status: NOERROR" dig.out.${t}.3 >/dev/null 2>&1 || {
382    echo_i "test $t failed: query failed"
383    status=1
384  }
385  grep "^l2.l1.l0.[ 	]*[0-9]*[ 	]*IN[ 	]*A[ 	]*10.53.0.1" dig.out.${t}.3 >/dev/null 2>&1 || {
386    echo_i "test $t failed: didn't get expected answer"
387    status=1
388  }
389  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t}.4
390  grep "status: SERVFAIL" dig.out.${t}.4 >/dev/null 2>&1 || {
391    echo_i "test $t failed: query failed"
392    status=1
393  }
394
395  # Check RPZ log clause
396  t=$((t + 1))
397  echo_i "testing RPZ log clause (${t})"
398  add_test_marker 10.53.0.2
399  run_server log
400  cur=$(awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run)
401  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 >dig.out.${t}
402  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >>dig.out.${t}
403  $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >>dig.out.${t}
404  sed -n "$cur,"'$p' <ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.4.0.53.10.rpz-client-ip.log1" >/dev/null && {
405    echo_ic "failed: unexpected rewrite message for policy zone log1 was logged"
406    status=1
407  }
408  sed -n "$cur,"'$p' <ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.3.0.53.10.rpz-client-ip.log2" >/dev/null || {
409    echo_ic "failed: expected rewrite message for policy zone log2 was not logged"
410    status=1
411  }
412  sed -n "$cur,"'$p' <ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.2.0.53.10.rpz-client-ip.log3" >/dev/null || {
413    echo_ic "failed: expected rewrite message for policy zone log3 was not logged"
414    status=1
415  }
416
417  # Check wildcard behavior
418
419  t=$((t + 1))
420  echo_i "testing wildcard behavior with 1 RPZ zone (${t})"
421  add_test_marker 10.53.0.2
422  run_server wildcard1
423  $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1
424  grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || {
425    echo_i "test ${t} failed"
426    status=1
427  }
428  $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2
429  grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null || {
430    echo_i "test ${t} failed"
431    status=1
432  }
433
434  t=$((t + 1))
435  echo_i "testing wildcard behavior with 2 RPZ zones (${t})"
436  add_test_marker 10.53.0.2
437  run_server wildcard2
438  $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1
439  grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || {
440    echo_i "test ${t} failed"
441    status=1
442  }
443  $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2
444  grep "status: NXDOMAIN" dig.out.${t}.2 >/dev/null || {
445    echo_i "test ${t} failed"
446    status=1
447  }
448
449  t=$((t + 1))
450  echo_i "testing wildcard behavior with 1 RPZ zone and no non-wildcard triggers (${t})"
451  add_test_marker 10.53.0.2
452  run_server wildcard3
453  $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.1
454  grep "status: NXDOMAIN" dig.out.${t}.1 >/dev/null || {
455    echo_i "test ${t} failed"
456    status=1
457  }
458  $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} >dig.out.${t}.2
459  grep "status: NOERROR" dig.out.${t}.2 >/dev/null || {
460    echo_i "test ${t} failed"
461    status=1
462  }
463
464  t=$((t + 1))
465  echo_i "testing wildcard passthru before explicit drop (${t})"
466  add_test_marker 10.53.0.2
467  run_server wildcard4
468  $DIG $DIGOPTS example.com a @10.53.0.2 -p ${PORT} >dig.out.${t}.1
469  grep "status: NOERROR" dig.out.${t}.1 >/dev/null || {
470    echo_i "test ${t} failed"
471    status=1
472  }
473  $DIG $DIGOPTS www.example.com a @10.53.0.2 -p ${PORT} >dig.out.${t}.2
474  grep "status: NOERROR" dig.out.${t}.2 >/dev/null || {
475    echo_i "test ${t} failed"
476    status=1
477  }
478
479  if [ "$mode" = "native" ]; then
480    # Check for invalid prefix length error
481    t=$((t + 1))
482    echo_i "testing for invalid prefix length error (${t})"
483    add_test_marker 10.53.0.2
484    run_server invalidprefixlength
485    grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run >/dev/null || {
486      echo_ic "failed: expected that invalid prefix length error would be logged"
487      status=1
488    }
489  fi
490
491  t=$((t + 1))
492  echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)"
493  add_test_marker 10.53.0.2 10.53.0.3
494  echo_i "timing 'nsip-wait-recurse yes' (default)"
495  ret=0
496  t1=$($PERL -e 'print time()."\n";')
497  $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.yes.$t
498  t2=$($PERL -e 'print time()."\n";')
499  p1=$((t2 - t1))
500  echo_i "elapsed time $p1 seconds"
501
502  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
503  copy_setports ns3/named2.conf.in ns3/named.conf
504  nextpart ns3/named.run >/dev/null
505  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null
506  wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
507
508  echo_i "timing 'nsip-wait-recurse no'"
509  t3=$($PERL -e 'print time()."\n";')
510  $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.no.$t
511  t4=$($PERL -e 'print time()."\n";')
512  p2=$((t4 - t3))
513  echo_i "elapsed time $p2 seconds"
514
515  if test $p1 -le $p2; then ret=1; fi
516  if test $ret != 0; then echo_i "failed"; fi
517  status=$((status + ret))
518
519  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
520  # restore original named.conf
521  copy_setports ns3/named1.conf.in ns3/named.conf
522  nextpart ns3/named.run >/dev/null
523  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null
524  wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
525
526  t=$((t + 1))
527  echo_i "checking 'nsdname-wait-recurse no' is faster than 'nsdname-wait-recurse yes' ($t)"
528  add_test_marker 10.53.0.2 10.53.0.3
529  echo_i "timing 'nsdname-wait-recurse yes' (default)"
530  ret=0
531  t1=$($PERL -e 'print time()."\n";')
532  $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.yes.$t
533  t2=$($PERL -e 'print time()."\n";')
534  p1=$((t2 - t1))
535  echo_i "elapsed time $p1 seconds"
536
537  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush
538  copy_setports ns3/named3.conf.in ns3/named.conf
539  nextpart ns3/named.run >/dev/null
540  $RNDC -c ../_common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload >/dev/null
541  wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1
542
543  echo_i "timing 'nsdname-wait-recurse no'"
544  t3=$($PERL -e 'print time()."\n";')
545  $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a >dig.out.no.$t
546  t4=$($PERL -e 'print time()."\n";')
547  p2=$((t4 - t3))
548  echo_i "elapsed time $p2 seconds"
549
550  if test $p1 -le $p2; then ret=1; fi
551  if test $ret != 0; then echo_i "failed"; fi
552  status=$((status + ret))
553
554  [ $status -ne 0 ] && pf=fail || pf=pass
555  case $mode in
556    native)
557      native=$status
558      echo_i "status (native RPZ sub-test): $status ($pf)"
559      ;;
560    dnsrps)
561      dnsrps=$status
562      echo_i "status (DNSRPS sub-test): $status ($pf)"
563      ;;
564    *) echo_i "invalid test mode" ;;
565  esac
566done
567status=$((native + dnsrps))
568
569[ $status -eq 0 ] || exit 1
570