xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/serve-stale/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. ../conf.sh
17
18RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s"
19DIG="$DIG +time=12 +tries=1"
20
21max_stale_ttl=$(sed -ne 's,^[[:space:]]*max-stale-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
22stale_answer_ttl=$(sed -ne 's,^[[:space:]]*stale-answer-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
23
24status=0
25n=0
26
27#
28# First test server with serve-stale options set.
29#
30echo_i "test server with serve-stale options set"
31
32n=$((n + 1))
33echo_i "prime cache longttl.example TXT ($n)"
34ret=0
35$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$n || ret=1
36grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
37grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
38if [ $ret != 0 ]; then echo_i "failed"; fi
39status=$((status + ret))
40
41n=$((n + 1))
42echo_i "prime cache data.example TXT ($n)"
43ret=0
44$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
45grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
46grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
47if [ $ret != 0 ]; then echo_i "failed"; fi
48status=$((status + ret))
49
50n=$((n + 1))
51echo_i "prime cache othertype.example CAA ($n)"
52ret=0
53$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$n || ret=1
54grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
55grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
56if [ $ret != 0 ]; then echo_i "failed"; fi
57status=$((status + ret))
58
59n=$((n + 1))
60echo_i "prime cache nodata.example TXT ($n)"
61ret=0
62$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$n || ret=1
63grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
64grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
65if [ $ret != 0 ]; then echo_i "failed"; fi
66status=$((status + ret))
67
68n=$((n + 1))
69echo_i "prime cache nxdomain.example TXT ($n)"
70ret=0
71$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$n || ret=1
72grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1
73grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
74if [ $ret != 0 ]; then echo_i "failed"; fi
75status=$((status + ret))
76
77n=$((n + 1))
78echo_i "verify prime cache statistics ($n)"
79ret=0
80rm -f ns1/named.stats
81$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1
82[ -f ns1/named.stats ] || ret=1
83cp ns1/named.stats ns1/named.stats.$n
84# Check first 10 lines of Cache DB statistics.  After prime queries, we expect
85# two active TXT, one active Others, one nxrrset TXT, and one NXDOMAIN.
86grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1
87grep "1 Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1
88grep "2 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
89grep "1 !TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
90grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb >/dev/null || ret=1
91if [ $ret != 0 ]; then echo_i "failed"; fi
92status=$((status + ret))
93
94n=$((n + 1))
95echo_i "disable responses from authoritative server ($n)"
96ret=0
97$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
98grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
99grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
100if [ $ret != 0 ]; then echo_i "failed"; fi
101status=$((status + ret))
102
103n=$((n + 1))
104echo_i "check 'rndc serve-stale status' ($n)"
105ret=0
106$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
107grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1
108if [ $ret != 0 ]; then echo_i "failed"; fi
109status=$((status + ret))
110
111sleep 2
112
113# Run rndc dumpdb, test whether the stale data has correct comment printed.
114# The max-stale-ttl is 3600 seconds, so the comment should say the data is
115# stale for somewhere between 3500-3599 seconds.
116echo_i "check rndc dump stale data.example ($n)"
117rndc_dumpdb ns1 || ret=1
118awk '/; stale/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \
119  | grep "; stale data\.example.*3[56]...*TXT.*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1
120# Also make sure the not expired data does not have a stale comment.
121awk '/; authanswer/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \
122  | grep "; authanswer longttl\.example.*[56]...*TXT.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1
123if [ $ret != 0 ]; then echo_i "failed"; fi
124status=$((status + ret))
125
126echo_i "sending queries for tests $((n + 1))-$((n + 5))..."
127$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
128$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$((n + 2)) &
129$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 3)) &
130$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 4)) &
131$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 5)) &
132
133wait
134
135n=$((n + 1))
136echo_i "check stale data.example TXT ($n)"
137ret=0
138grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
139grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
140grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
141grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
142if [ $ret != 0 ]; then echo_i "failed"; fi
143status=$((status + ret))
144
145n=$((n + 1))
146echo_i "check non-stale longttl.example TXT ($n)"
147ret=0
148grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
149grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
150grep "EDE" dig.out.test$n >/dev/null && ret=1
151grep "longttl\.example\..*59[0-9].*IN.*TXT.*A text record with a 600 second ttl" dig.out.test$n >/dev/null || ret=1
152if [ $ret != 0 ]; then echo_i "failed"; fi
153status=$((status + ret))
154
155n=$((n + 1))
156echo_i "check stale othertype.example CAA ($n)"
157ret=0
158grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
159grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
160grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
161grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
162if [ $ret != 0 ]; then echo_i "failed"; fi
163status=$((status + ret))
164
165n=$((n + 1))
166echo_i "check stale nodata.example TXT ($n)"
167ret=0
168grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
169grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
170grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
171grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
172if [ $ret != 0 ]; then echo_i "failed"; fi
173status=$((status + ret))
174
175n=$((n + 1))
176echo_i "check stale nxdomain.example TXT ($n)"
177ret=0
178grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
179grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
180if [ $ret != 0 ]; then echo_i "failed"; fi
181status=$((status + ret))
182
183n=$((n + 1))
184echo_i "verify stale cache statistics ($n)"
185ret=0
186rm -f ns1/named.stats
187$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1
188[ -f ns1/named.stats ] || ret=1
189cp ns1/named.stats ns1/named.stats.$n
190# Check first 10 lines of Cache DB statistics.  After serve-stale queries, we
191# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one
192# stale NXDOMAIN.
193grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1
194grep "1 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
195grep "1 #Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1
196grep "1 #TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
197grep "1 #!TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
198status=$((status + ret))
199if [ $ret != 0 ]; then echo_i "failed"; fi
200
201# Test stale-refresh-time when serve-stale is enabled via configuration.
202# Steps for testing stale-refresh-time option (default).
203# 1. Prime cache data.example txt
204# 2. Disable responses from authoritative server.
205# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
206# 4. Query data.example
207# 5. Check if response come from stale rrset (4 sec TTL)
208# 6. Enable responses from authoritative server.
209# 7. Query data.example
210# 8. Check if response come from stale rrset, since the query
211#    is still within stale-refresh-time window.
212n=$((n + 1))
213echo_i "check 'rndc serve-stale status' ($n)"
214ret=0
215$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
216grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1
217if [ $ret != 0 ]; then echo_i "failed"; fi
218status=$((status + ret))
219
220# Step 1-3 done above.
221
222# Step 4.
223n=$((n + 1))
224echo_i "sending query for test ($n)"
225$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
226
227# Step 5.
228echo_i "check stale data.example TXT (stale-refresh-time) ($n)"
229ret=0
230grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
231grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1
232grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
233grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
234if [ $ret != 0 ]; then echo_i "failed"; fi
235status=$((status + ret))
236
237# Step 6.
238n=$((n + 1))
239echo_i "enable responses from authoritative server ($n)"
240ret=0
241$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
242grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
243grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
244if [ $ret != 0 ]; then echo_i "failed"; fi
245status=$((status + ret))
246
247# Step 7.
248echo_i "sending query for test $((n + 1))"
249$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true
250
251# Step 8.
252n=$((n + 1))
253echo_i "check stale data.example TXT comes from cache (stale-refresh-time) ($n)"
254ret=0
255grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
256grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1
257grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
258grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
259if [ $ret != 0 ]; then echo_i "failed"; fi
260status=$((status + ret))
261
262#
263# Test interaction with local zone
264#
265
266n=$((n + 1))
267echo_i "check that serve-stale does not recurse for local authoritative zone ($n)"
268ret=0
269
270num=0
271threshold=10
272while [ $num -lt $threshold ]; do
273
274  echo_i "dig test.serve.stale TXT ($n)"
275  $DIG -p ${PORT} @10.53.0.3 test.serve.stale TXT >dig.out.test$n.$num || ret=1
276  grep "status: SERVFAIL" dig.out.test$n.$num >/dev/null || ret=1
277  if [ $ret != 0 ]; then num=$threshold; fi
278
279  sleep 1
280  num=$((num + 1))
281done
282if [ $ret != 0 ]; then echo_i "failed"; fi
283status=$((status + ret))
284
285#
286# Test disabling serve-stale via rndc.
287#
288
289n=$((n + 1))
290echo_i "updating ns1/named.conf ($n)"
291ret=0
292copy_setports ns1/named2.conf.in ns1/named.conf
293if [ $ret != 0 ]; then echo_i "failed"; fi
294status=$((status + ret))
295
296n=$((n + 1))
297echo_i "running 'rndc reload' ($n)"
298ret=0
299rndc_reload ns1 10.53.0.1
300if [ $ret != 0 ]; then echo_i "failed"; fi
301status=$((status + ret))
302
303n=$((n + 1))
304echo_i "check 'rndc serve-stale status' ($n)"
305ret=0
306$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
307grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
308if [ $ret != 0 ]; then echo_i "failed"; fi
309status=$((status + ret))
310
311n=$((n + 1))
312echo_i "disable responses from authoritative server ($n)"
313ret=0
314$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
315grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
316grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
317if [ $ret != 0 ]; then echo_i "failed"; fi
318status=$((status + ret))
319
320n=$((n + 1))
321echo_i "running 'rndc serve-stale off' ($n)"
322ret=0
323$RNDCCMD 10.53.0.1 serve-stale off || ret=1
324if [ $ret != 0 ]; then echo_i "failed"; fi
325status=$((status + ret))
326
327n=$((n + 1))
328echo_i "check 'rndc serve-stale status' ($n)"
329ret=0
330$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
331grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
332if [ $ret != 0 ]; then echo_i "failed"; fi
333status=$((status + ret))
334
335echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
336$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
337$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) &
338$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) &
339$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) &
340
341wait
342
343n=$((n + 1))
344echo_i "check stale data.example TXT (serve-stale off) ($n)"
345ret=0
346grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
347grep "EDE" dig.out.test$n >/dev/null && ret=1
348if [ $ret != 0 ]; then echo_i "failed"; fi
349status=$((status + ret))
350
351n=$((n + 1))
352echo_i "check stale othertype.example CAA (serve-stale off) ($n)"
353ret=0
354grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
355grep "EDE" dig.out.test$n >/dev/null && ret=1
356if [ $ret != 0 ]; then echo_i "failed"; fi
357status=$((status + ret))
358
359n=$((n + 1))
360echo_i "check stale nodata.example TXT (serve-stale off) ($n)"
361ret=0
362grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
363grep "EDE" dig.out.test$n >/dev/null && ret=1
364if [ $ret != 0 ]; then echo_i "failed"; fi
365status=$((status + ret))
366
367n=$((n + 1))
368echo_i "check stale nxdomain.example TXT (serve-stale off) ($n)"
369ret=0
370grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
371grep "EDE" dig.out.test$n >/dev/null && ret=1
372if [ $ret != 0 ]; then echo_i "failed"; fi
373status=$((status + ret))
374
375#
376# Test enabling serve-stale via rndc.
377#
378n=$((n + 1))
379echo_i "running 'rndc serve-stale on' ($n)"
380ret=0
381$RNDCCMD 10.53.0.1 serve-stale on || ret=1
382if [ $ret != 0 ]; then echo_i "failed"; fi
383status=$((status + ret))
384
385n=$((n + 1))
386echo_i "check 'rndc serve-stale status' ($n)"
387ret=0
388$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
389grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
390if [ $ret != 0 ]; then echo_i "failed"; fi
391status=$((status + ret))
392
393echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
394$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
395$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) &
396$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) &
397$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) &
398
399wait
400
401n=$((n + 1))
402echo_i "check stale data.example TXT (serve-stale on) ($n)"
403ret=0
404grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
405grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
406grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
407grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
408if [ $ret != 0 ]; then echo_i "failed"; fi
409status=$((status + ret))
410
411n=$((n + 1))
412echo_i "check stale othertype.example CAA (serve-stale on) ($n)"
413ret=0
414grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
415grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
416grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
417grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
418if [ $ret != 0 ]; then echo_i "failed"; fi
419status=$((status + ret))
420
421n=$((n + 1))
422echo_i "check stale nodata.example TXT (serve-stale on) ($n)"
423ret=0
424grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
425grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
426grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
427grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
428if [ $ret != 0 ]; then echo_i "failed"; fi
429status=$((status + ret))
430
431n=$((n + 1))
432echo_i "check stale nxdomain.example TXT (serve-stale on) ($n)"
433ret=0
434grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
435grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
436if [ $ret != 0 ]; then echo_i "failed"; fi
437status=$((status + ret))
438
439n=$((n + 1))
440echo_i "running 'rndc serve-stale off' ($n)"
441ret=0
442$RNDCCMD 10.53.0.1 serve-stale off || ret=1
443if [ $ret != 0 ]; then echo_i "failed"; fi
444status=$((status + ret))
445
446n=$((n + 1))
447echo_i "running 'rndc serve-stale reset' ($n)"
448ret=0
449$RNDCCMD 10.53.0.1 serve-stale reset || ret=1
450if [ $ret != 0 ]; then echo_i "failed"; fi
451status=$((status + ret))
452
453n=$((n + 1))
454echo_i "check 'rndc serve-stale status' ($n)"
455ret=0
456$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
457grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
458if [ $ret != 0 ]; then echo_i "failed"; fi
459status=$((status + ret))
460
461echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
462$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
463$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) &
464$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) &
465$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) &
466
467wait
468
469n=$((n + 1))
470echo_i "check stale data.example TXT (serve-stale reset) ($n)"
471ret=0
472grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
473grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
474grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
475grep "data\.example\..*4.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
476if [ $ret != 0 ]; then echo_i "failed"; fi
477status=$((status + ret))
478
479n=$((n + 1))
480echo_i "check stale othertype.example CAA (serve-stale reset) ($n)"
481ret=0
482grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
483grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
484grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
485grep "othertype.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
486if [ $ret != 0 ]; then echo_i "failed"; fi
487status=$((status + ret))
488
489n=$((n + 1))
490echo_i "check stale nodata.example TXT (serve-stale reset) ($n)"
491ret=0
492grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
493grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
494grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
495grep "example\..*4.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
496if [ $ret != 0 ]; then echo_i "failed"; fi
497status=$((status + ret))
498
499n=$((n + 1))
500echo_i "check stale nxdomain.example TXT (serve-stale reset) ($n)"
501ret=0
502grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
503grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
504if [ $ret != 0 ]; then echo_i "failed"; fi
505status=$((status + ret))
506
507n=$((n + 1))
508echo_i "running 'rndc serve-stale off' ($n)"
509ret=0
510$RNDCCMD 10.53.0.1 serve-stale off || ret=1
511if [ $ret != 0 ]; then echo_i "failed"; fi
512status=$((status + ret))
513
514n=$((n + 1))
515echo_i "check 'rndc serve-stale status' ($n)"
516ret=0
517$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
518grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
519if [ $ret != 0 ]; then echo_i "failed"; fi
520status=$((status + ret))
521
522#
523# Update named.conf.
524# Test server with low max-stale-ttl.
525#
526echo_i "test server with serve-stale options set, low max-stale-ttl"
527
528n=$((n + 1))
529echo_i "updating ns1/named.conf ($n)"
530ret=0
531copy_setports ns1/named3.conf.in ns1/named.conf
532if [ $ret != 0 ]; then echo_i "failed"; fi
533status=$((status + ret))
534
535n=$((n + 1))
536echo_i "running 'rndc reload' ($n)"
537ret=0
538rndc_reload ns1 10.53.0.1
539if [ $ret != 0 ]; then echo_i "failed"; fi
540status=$((status + ret))
541
542n=$((n + 1))
543echo_i "check 'rndc serve-stale status' ($n)"
544ret=0
545$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
546grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1
547if [ $ret != 0 ]; then echo_i "failed"; fi
548status=$((status + ret))
549
550n=$((n + 1))
551echo_i "flush cache, re-enable serve-stale and query again ($n)"
552ret=0
553$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1
554$RNDCCMD 10.53.0.1 serve-stale on >rndc.out.test$n.2 2>&1 || ret=1
555$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
556grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
557grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
558if [ $ret != 0 ]; then echo_i "failed"; fi
559status=$((status + ret))
560
561n=$((n + 1))
562echo_i "check 'rndc serve-stale status' ($n)"
563ret=0
564$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
565grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1
566if [ $ret != 0 ]; then echo_i "failed"; fi
567status=$((status + ret))
568
569n=$((n + 1))
570echo_i "enable responses from authoritative server ($n)"
571ret=0
572$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
573grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
574grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
575if [ $ret != 0 ]; then echo_i "failed"; fi
576status=$((status + ret))
577
578n=$((n + 1))
579echo_i "prime cache longttl.example TXT (low max-stale-ttl) ($n)"
580ret=0
581$DIG -p ${PORT} @10.53.0.1 longttl.example TXT >dig.out.test$n || ret=1
582grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
583grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
584if [ $ret != 0 ]; then echo_i "failed"; fi
585status=$((status + ret))
586
587n=$((n + 1))
588echo_i "prime cache data.example TXT (low max-stale-ttl) ($n)"
589ret=0
590$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
591grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
592grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
593if [ $ret != 0 ]; then echo_i "failed"; fi
594status=$((status + ret))
595
596n=$((n + 1))
597echo_i "prime cache othertype.example CAA (low max-stale-ttl) ($n)"
598ret=0
599$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$n || ret=1
600grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
601grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
602if [ $ret != 0 ]; then echo_i "failed"; fi
603status=$((status + ret))
604
605n=$((n + 1))
606echo_i "prime cache nodata.example TXT (low max-stale-ttl) ($n)"
607ret=0
608$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$n || ret=1
609grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
610grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
611if [ $ret != 0 ]; then echo_i "failed"; fi
612status=$((status + ret))
613
614n=$((n + 1))
615echo_i "prime cache nxdomain.example TXT (low max-stale-ttl) ($n)"
616ret=0
617$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$n || ret=1
618grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1
619grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
620if [ $ret != 0 ]; then echo_i "failed"; fi
621status=$((status + ret))
622
623# Keep track of time so we can access these RRset later, when we expect them
624# to become ancient.
625t1=$($PERL -e 'print time()')
626
627n=$((n + 1))
628echo_i "verify prime cache statistics (low max-stale-ttl) ($n)"
629ret=0
630rm -f ns1/named.stats
631$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1
632[ -f ns1/named.stats ] || ret=1
633cp ns1/named.stats ns1/named.stats.$n
634# Check first 10 lines of Cache DB statistics.  After prime queries, we expect
635# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
636grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1
637grep "2 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
638grep "1 Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1
639grep "1 !TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
640grep "1 NXDOMAIN" ns1/named.stats.$n.cachedb >/dev/null || ret=1
641status=$((status + ret))
642if [ $ret != 0 ]; then echo_i "failed"; fi
643
644n=$((n + 1))
645echo_i "disable responses from authoritative server ($n)"
646ret=0
647$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
648grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
649grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
650if [ $ret != 0 ]; then echo_i "failed"; fi
651status=$((status + ret))
652
653sleep 2
654
655echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
656$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
657$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) &
658$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) &
659$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) &
660
661wait
662
663n=$((n + 1))
664echo_i "check stale data.example TXT (low max-stale-ttl) ($n)"
665ret=0
666grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
667grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
668grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
669grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
670if [ $ret != 0 ]; then echo_i "failed"; fi
671status=$((status + ret))
672
673n=$((n + 1))
674echo_i "check stale othertype.example CAA (low max-stale-ttl) ($n)"
675ret=0
676grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
677grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
678grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
679grep "othertype\.example\..*3.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
680if [ $ret != 0 ]; then echo_i "failed"; fi
681status=$((status + ret))
682
683n=$((n + 1))
684echo_i "check stale nodata.example TXT (low max-stale-ttl) ($n)"
685ret=0
686grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
687grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
688grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
689grep "example\..*3.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
690if [ $ret != 0 ]; then echo_i "failed"; fi
691status=$((status + ret))
692
693n=$((n + 1))
694echo_i "check stale nxdomain.example TXT (low max-stale-ttl) ($n)"
695ret=0
696grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
697grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
698if [ $ret != 0 ]; then echo_i "failed"; fi
699status=$((status + ret))
700
701n=$((n + 1))
702echo_i "verify stale cache statistics (low max-stale-ttl) ($n)"
703ret=0
704rm -f ns1/named.stats
705$RNDCCMD 10.53.0.1 stats >/dev/null 2>&1
706[ -f ns1/named.stats ] || ret=1
707cp ns1/named.stats ns1/named.stats.$n
708# Check first 10 lines of Cache DB statistics.  After serve-stale queries, we
709# expect one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one
710# stale NXDOMAIN.
711grep -A 10 "++ Cache DB RRsets ++" ns1/named.stats.$n >ns1/named.stats.$n.cachedb || ret=1
712grep "1 TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
713grep "1 #TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
714grep "1 #Others" ns1/named.stats.$n.cachedb >/dev/null || ret=1
715grep "1 #!TXT" ns1/named.stats.$n.cachedb >/dev/null || ret=1
716
717status=$((status + ret))
718if [ $ret != 0 ]; then echo_i "failed"; fi
719
720# Retrieve max-stale-ttl value.
721interval_to_ancient=$(grep 'max-stale-ttl' ns1/named3.conf.in | awk '{ print $2 }' | tr -d ';')
722# We add 2 seconds to it since this is the ttl value of the records being
723# tested.
724interval_to_ancient=$((interval_to_ancient + 2))
725t2=$($PERL -e 'print time()')
726elapsed=$((t2 - t1))
727
728# If elapsed time so far is less than max-stale-ttl + 2 seconds, then we sleep
729# enough to ensure that we'll ask for ancient RRsets in the next queries.
730if [ $elapsed -lt $interval_to_ancient ]; then
731  sleep $((interval_to_ancient - elapsed))
732fi
733
734echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
735$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) &
736$DIG -p ${PORT} @10.53.0.1 othertype.example CAA >dig.out.test$((n + 2)) &
737$DIG -p ${PORT} @10.53.0.1 nodata.example TXT >dig.out.test$((n + 3)) &
738$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT >dig.out.test$((n + 4)) &
739
740wait
741
742n=$((n + 1))
743echo_i "check ancient data.example TXT (low max-stale-ttl) ($n)"
744ret=0
745grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
746grep "EDE" dig.out.test$n >/dev/null && ret=1
747grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
748if [ $ret != 0 ]; then echo_i "failed"; fi
749status=$((status + ret))
750
751n=$((n + 1))
752echo_i "check ancient othertype.example CAA (low max-stale-ttl) ($n)"
753ret=0
754grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
755grep "EDE" dig.out.test$n >/dev/null && ret=1
756grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
757if [ $ret != 0 ]; then echo_i "failed"; fi
758status=$((status + ret))
759
760n=$((n + 1))
761echo_i "check ancient nodata.example TXT (low max-stale-ttl) ($n)"
762ret=0
763grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
764grep "EDE" dig.out.test$n >/dev/null && ret=1
765grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
766if [ $ret != 0 ]; then echo_i "failed"; fi
767status=$((status + ret))
768
769n=$((n + 1))
770echo_i "check ancient nxdomain.example TXT (low max-stale-ttl) ($n)"
771ret=0
772grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
773grep "EDE" dig.out.test$n >/dev/null && ret=1
774grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
775if [ $ret != 0 ]; then echo_i "failed"; fi
776status=$((status + ret))
777
778# Test stale-refresh-time when serve-stale is enabled via rndc.
779# Steps for testing stale-refresh-time option (default).
780# 1. Prime cache data.example txt
781# 2. Disable responses from authoritative server.
782# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
783# 4. Query data.example
784# 5. Check if response come from stale rrset (3 sec TTL)
785# 6. Enable responses from authoritative server.
786# 7. Query data.example
787# 8. Check if response come from stale rrset, since the query
788#    is within stale-refresh-time window.
789n=$((n + 1))
790echo_i "flush cache, enable responses from authoritative server ($n)"
791ret=0
792$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1
793$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
794grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
795grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
796if [ $ret != 0 ]; then echo_i "failed"; fi
797status=$((status + ret))
798
799n=$((n + 1))
800echo_i "check 'rndc serve-stale status' ($n)"
801ret=0
802$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
803grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n >/dev/null || ret=1
804if [ $ret != 0 ]; then echo_i "failed"; fi
805status=$((status + ret))
806
807# Step 1.
808n=$((n + 1))
809echo_i "prime cache data.example TXT (stale-refresh-time rndc) ($n)"
810ret=0
811$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
812grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
813grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
814grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
815if [ $ret != 0 ]; then echo_i "failed"; fi
816status=$((status + ret))
817
818# Step 2.
819n=$((n + 1))
820echo_i "disable responses from authoritative server ($n)"
821ret=0
822$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
823grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
824grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
825if [ $ret != 0 ]; then echo_i "failed"; fi
826status=$((status + ret))
827
828# Step 3.
829sleep 2
830
831# Step 4.
832n=$((n + 1))
833echo_i "sending query for test ($n)"
834$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
835
836# Step 5.
837echo_i "check stale data.example TXT (stale-refresh-time rndc) ($n)"
838ret=0
839grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
840grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
841grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
842grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
843if [ $ret != 0 ]; then echo_i "failed"; fi
844status=$((status + ret))
845
846# Step 6.
847n=$((n + 1))
848echo_i "enable responses from authoritative server ($n)"
849ret=0
850$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
851grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
852grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
853if [ $ret != 0 ]; then echo_i "failed"; fi
854status=$((status + ret))
855
856# Step 7.
857echo_i "sending query for test $((n + 1))"
858$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true
859
860# Step 8.
861n=$((n + 1))
862echo_i "check stale data.example TXT comes from cache (stale-refresh-time rndc) ($n)"
863ret=0
864grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
865grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1
866grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
867grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
868if [ $ret != 0 ]; then echo_i "failed"; fi
869status=$((status + ret))
870
871# Steps for testing stale-refresh-time option (disabled).
872# 1. Prime cache data.example txt
873# 2. Disable responses from authoritative server.
874# 3. Sleep for TTL duration so rrset TTL expires (2 sec)
875# 4. Query data.example
876# 5. Check if response come from stale rrset (3 sec TTL)
877# 6. Enable responses from authoritative server.
878# 7. Query data.example
879# 8. Check if response come from stale rrset, since the query
880#    is within stale-refresh-time window.
881n=$((n + 1))
882echo_i "updating ns1/named.conf ($n)"
883ret=0
884copy_setports ns1/named4.conf.in ns1/named.conf
885if [ $ret != 0 ]; then echo_i "failed"; fi
886status=$((status + ret))
887
888n=$((n + 1))
889echo_i "running 'rndc reload' ($n)"
890ret=0
891rndc_reload ns1 10.53.0.1
892if [ $ret != 0 ]; then echo_i "failed"; fi
893status=$((status + ret))
894
895n=$((n + 1))
896echo_i "check 'rndc serve-stale status' ($n)"
897ret=0
898$RNDCCMD 10.53.0.1 serve-stale status >rndc.out.test$n 2>&1 || ret=1
899grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=0)' rndc.out.test$n >/dev/null || ret=1
900if [ $ret != 0 ]; then echo_i "failed"; fi
901status=$((status + ret))
902
903n=$((n + 1))
904echo_i "flush cache, enable responses from authoritative server ($n)"
905ret=0
906$RNDCCMD 10.53.0.1 flushtree example >rndc.out.test$n.1 2>&1 || ret=1
907$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
908grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
909grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
910if [ $ret != 0 ]; then echo_i "failed"; fi
911status=$((status + ret))
912
913# Step 1.
914n=$((n + 1))
915echo_i "prime cache data.example TXT (stale-refresh-time disabled) ($n)"
916ret=0
917$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
918grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
919grep "EDE" dig.out.test$n >/dev/null && ret=1
920grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
921grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
922if [ $ret != 0 ]; then echo_i "failed"; fi
923status=$((status + ret))
924
925# Step 2.
926n=$((n + 1))
927echo_i "disable responses from authoritative server ($n)"
928ret=0
929$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
930grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
931grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
932if [ $ret != 0 ]; then echo_i "failed"; fi
933status=$((status + ret))
934
935# Step 3.
936sleep 2
937
938# Step 4.
939n=$((n + 1))
940echo_i "sending query for test ($n)"
941$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$n || ret=1
942
943# Step 5.
944echo_i "check stale data.example TXT (stale-refresh-time disabled) ($n)"
945ret=0
946grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
947grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
948grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
949grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
950if [ $ret != 0 ]; then echo_i "failed"; fi
951status=$((status + ret))
952
953# Step 6.
954n=$((n + 1))
955echo_i "enable responses from authoritative server ($n)"
956ret=0
957$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
958grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
959grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
960if [ $ret != 0 ]; then echo_i "failed"; fi
961status=$((status + ret))
962
963# Step 7.
964echo_i "sending query for test $((n + 1))"
965$DIG -p ${PORT} @10.53.0.1 data.example TXT >dig.out.test$((n + 1)) || true
966
967# Step 8.
968n=$((n + 1))
969echo_i "check data.example TXT comes from authoritative (stale-refresh-time disabled) ($n)"
970ret=0
971grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
972grep "EDE" dig.out.test$n >/dev/null && ret=1
973grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
974grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
975if [ $ret != 0 ]; then echo_i "failed"; fi
976status=$((status + ret))
977
978#
979# Now test server with no serve-stale options set.
980#
981echo_i "test server with no serve-stale options set"
982
983n=$((n + 1))
984echo_i "updating ns3/named.conf ($n)"
985ret=0
986copy_setports ns3/named1.conf.in ns3/named.conf
987if [ $ret != 0 ]; then echo_i "failed"; fi
988status=$((status + ret))
989
990echo_i "restart ns3"
991stop_server --use-rndc --port ${CONTROLPORT} ns3
992start_server --noclean --restart --port ${PORT} ns3
993
994n=$((n + 1))
995echo_i "enable responses from authoritative server ($n)"
996ret=0
997$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
998grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
999grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1000if [ $ret != 0 ]; then echo_i "failed"; fi
1001status=$((status + ret))
1002
1003n=$((n + 1))
1004echo_i "prime cache longttl.example TXT (max-stale-ttl default) ($n)"
1005ret=0
1006$DIG -p ${PORT} @10.53.0.3 longttl.example TXT >dig.out.test$n || ret=1
1007grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1008grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1009if [ $ret != 0 ]; then echo_i "failed"; fi
1010status=$((status + ret))
1011
1012n=$((n + 1))
1013echo_i "prime cache data.example TXT (max-stale-ttl default) ($n)"
1014ret=0
1015$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
1016grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1017grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1018grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1019if [ $ret != 0 ]; then echo_i "failed"; fi
1020status=$((status + ret))
1021
1022n=$((n + 1))
1023echo_i "prime cache othertype.example CAA (max-stale-ttl default) ($n)"
1024ret=0
1025$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$n || ret=1
1026grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1027grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1028grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
1029if [ $ret != 0 ]; then echo_i "failed"; fi
1030status=$((status + ret))
1031
1032n=$((n + 1))
1033echo_i "prime cache nodata.example TXT (max-stale-ttl default) ($n)"
1034ret=0
1035$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1
1036grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1037grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1038grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1039if [ $ret != 0 ]; then echo_i "failed"; fi
1040status=$((status + ret))
1041
1042n=$((n + 1))
1043echo_i "prime cache nxdomain.example TXT (max-stale-ttl default) ($n)"
1044ret=0
1045$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$n || ret=1
1046grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1
1047grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1048grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1049if [ $ret != 0 ]; then echo_i "failed"; fi
1050status=$((status + ret))
1051
1052n=$((n + 1))
1053echo_i "verify prime cache statistics (max-stale-ttl default) ($n)"
1054ret=0
1055rm -f ns3/named.stats
1056$RNDCCMD 10.53.0.3 stats >/dev/null 2>&1
1057[ -f ns3/named.stats ] || ret=1
1058cp ns3/named.stats ns3/named.stats.$n
1059# Check first 10 lines of Cache DB statistics.  After prime queries, we expect
1060# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
1061grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n >ns3/named.stats.$n.cachedb || ret=1
1062grep "2 TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1063grep "1 Others" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1064grep "1 !TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1065grep "1 NXDOMAIN" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1066status=$((status + ret))
1067if [ $ret != 0 ]; then echo_i "failed"; fi
1068
1069n=$((n + 1))
1070echo_i "disable responses from authoritative server ($n)"
1071ret=0
1072$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
1073grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1074grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
1075if [ $ret != 0 ]; then echo_i "failed"; fi
1076status=$((status + ret))
1077
1078n=$((n + 1))
1079echo_i "check 'rndc serve-stale status' ($n)"
1080ret=0
1081$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1
1082grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1
1083if [ $ret != 0 ]; then echo_i "failed"; fi
1084status=$((status + ret))
1085
1086sleep 2
1087
1088echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
1089$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) &
1090$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) &
1091$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) &
1092$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) &
1093
1094wait
1095
1096n=$((n + 1))
1097echo_i "check fail of data.example TXT (max-stale-ttl default) ($n)"
1098ret=0
1099grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1100grep "EDE" dig.out.test$n >/dev/null && ret=1
1101grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1102if [ $ret != 0 ]; then echo_i "failed"; fi
1103status=$((status + ret))
1104
1105n=$((n + 1))
1106echo_i "check fail of othertype.example CAA (max-stale-ttl default) ($n)"
1107ret=0
1108grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1109grep "EDE" dig.out.test$n >/dev/null && ret=1
1110grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1111if [ $ret != 0 ]; then echo_i "failed"; fi
1112status=$((status + ret))
1113
1114n=$((n + 1))
1115echo_i "check fail of nodata.example TXT (max-stale-ttl default) ($n)"
1116ret=0
1117grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1118grep "EDE" dig.out.test$n >/dev/null && ret=1
1119grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1120if [ $ret != 0 ]; then echo_i "failed"; fi
1121status=$((status + ret))
1122
1123n=$((n + 1))
1124echo_i "check fail of nxdomain.example TXT (max-stale-ttl default) ($n)"
1125ret=0
1126grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1127grep "EDE" dig.out.test$n >/dev/null && ret=1
1128grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1129if [ $ret != 0 ]; then echo_i "failed"; fi
1130status=$((status + ret))
1131
1132n=$((n + 1))
1133echo_i "verify stale cache statistics (max-stale-ttl default) ($n)"
1134ret=0
1135rm -f ns3/named.stats
1136$RNDCCMD 10.53.0.3 stats >/dev/null 2>&1
1137[ -f ns3/named.stats ] || ret=1
1138cp ns3/named.stats ns3/named.stats.$n
1139# Check first 10 lines of Cache DB statistics. After last queries, we expect
1140# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale
1141# NXDOMAIN.
1142grep -A 10 "++ Cache DB RRsets ++" ns3/named.stats.$n >ns3/named.stats.$n.cachedb || ret=1
1143grep "1 TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1144grep "1 #TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1145grep "1 #Others" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1146grep "1 #!TXT" ns3/named.stats.$n.cachedb >/dev/null || ret=1
1147
1148status=$((status + ret))
1149if [ $ret != 0 ]; then echo_i "failed"; fi
1150
1151n=$((n + 1))
1152echo_i "check 'rndc serve-stale on' ($n)"
1153ret=0
1154$RNDCCMD 10.53.0.3 serve-stale on >rndc.out.test$n 2>&1 || ret=1
1155if [ $ret != 0 ]; then echo_i "failed"; fi
1156status=$((status + ret))
1157
1158n=$((n + 1))
1159echo_i "check 'rndc serve-stale status' ($n)"
1160ret=0
1161$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1
1162grep "_default: stale cache enabled; stale answers enabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1
1163if [ $ret != 0 ]; then echo_i "failed"; fi
1164status=$((status + ret))
1165
1166sleep 2
1167
1168# Check that if we don't have stale data for a domain name, we will
1169# not answer anything until the resolver query timeout.
1170n=$((n + 1))
1171echo_i "check notincache.example TXT times out (max-stale-ttl default) ($n)"
1172ret=0
1173$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 notfound.example TXT >dig.out.test$n 2>&1 && ret=1
1174grep "timed out" dig.out.test$n >/dev/null || ret=1
1175grep ";; no servers could be reached" dig.out.test$n >/dev/null || ret=1
1176if [ $ret != 0 ]; then echo_i "failed"; fi
1177status=$((status + ret))
1178
1179echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
1180$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) &
1181$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) &
1182$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) &
1183$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) &
1184$DIG -p ${PORT} @10.53.0.3 notfound.example TXT >dig.out.test$((n + 5)) &
1185
1186wait
1187
1188n=$((n + 1))
1189echo_i "check data.example TXT (max-stale-ttl default) ($n)"
1190ret=0
1191grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1192grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
1193grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1194grep "data\.example\..*30.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1195if [ $ret != 0 ]; then echo_i "failed"; fi
1196status=$((status + ret))
1197
1198n=$((n + 1))
1199echo_i "check othertype.example CAA (max-stale-ttl default) ($n)"
1200ret=0
1201grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1202grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
1203grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1204grep "example\..*30.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
1205if [ $ret != 0 ]; then echo_i "failed"; fi
1206status=$((status + ret))
1207
1208n=$((n + 1))
1209echo_i "check nodata.example TXT (max-stale-ttl default) ($n)"
1210ret=0
1211grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1212grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
1213grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1214grep "example\..*30.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1215if [ $ret != 0 ]; then echo_i "failed"; fi
1216status=$((status + ret))
1217
1218n=$((n + 1))
1219echo_i "check nxdomain.example TXT (max-stale-ttl default) ($n)"
1220ret=0
1221grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1222grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1223if [ $ret != 0 ]; then echo_i "failed"; fi
1224status=$((status + ret))
1225
1226# The notfound.example check is different than nxdomain.example because
1227# we didn't send a prime query to add notfound.example to the cache.
1228n=$((n + 1))
1229echo_i "check notfound.example TXT (max-stale-ttl default) ($n)"
1230ret=0
1231grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1232grep "EDE" dig.out.test$n >/dev/null && ret=1
1233grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1234if [ $ret != 0 ]; then echo_i "failed"; fi
1235status=$((status + ret))
1236
1237#
1238# Now test server with serve-stale answers disabled.
1239#
1240echo_i "test server with serve-stale disabled"
1241
1242n=$((n + 1))
1243echo_i "enable responses from authoritative server ($n)"
1244ret=0
1245$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
1246grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1247grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1248if [ $ret != 0 ]; then echo_i "failed"; fi
1249status=$((status + ret))
1250
1251n=$((n + 1))
1252echo_i "prime cache longttl.example TTL (serve-stale answers disabled) ($n)"
1253ret=0
1254$DIG -p ${PORT} @10.53.0.4 longttl.example TXT >dig.out.test$n || ret=1
1255grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1256grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1257if [ $ret != 0 ]; then echo_i "failed"; fi
1258status=$((status + ret))
1259
1260n=$((n + 1))
1261echo_i "prime cache data.example TTL (serve-stale answers disabled) ($n)"
1262ret=0
1263$DIG -p ${PORT} @10.53.0.4 data.example TXT >dig.out.test$n || ret=1
1264grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1265grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1266grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1267if [ $ret != 0 ]; then echo_i "failed"; fi
1268status=$((status + ret))
1269
1270n=$((n + 1))
1271echo_i "prime cache othertype.example CAA (serve-stale answers disabled) ($n)"
1272ret=0
1273$DIG -p ${PORT} @10.53.0.4 othertype.example CAA >dig.out.test$n || ret=1
1274grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1275grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1276grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
1277if [ $ret != 0 ]; then echo_i "failed"; fi
1278status=$((status + ret))
1279
1280n=$((n + 1))
1281echo_i "prime cache nodata.example TXT (serve-stale answers disabled) ($n)"
1282ret=0
1283$DIG -p ${PORT} @10.53.0.4 nodata.example TXT >dig.out.test$n || ret=1
1284grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1285grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1286grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1287if [ $ret != 0 ]; then echo_i "failed"; fi
1288status=$((status + ret))
1289
1290n=$((n + 1))
1291echo_i "prime cache nxdomain.example TXT (serve-stale answers disabled) ($n)"
1292ret=0
1293$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT >dig.out.test$n || ret=1
1294grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1
1295grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1296grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1297if [ $ret != 0 ]; then echo_i "failed"; fi
1298status=$((status + ret))
1299
1300n=$((n + 1))
1301echo_i "verify prime cache statistics (serve-stale answers disabled) ($n)"
1302ret=0
1303rm -f ns4/named.stats
1304$RNDCCMD 10.53.0.4 stats >/dev/null 2>&1
1305[ -f ns4/named.stats ] || ret=1
1306cp ns4/named.stats ns4/named.stats.$n
1307# Check first 10 lines of Cache DB statistics.  After prime queries, we expect
1308# two active TXT RRsets, one active Others, one nxrrset TXT, and one NXDOMAIN.
1309grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1
1310grep "2 TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1311grep "1 Others" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1312grep "1 !TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1313grep "1 NXDOMAIN" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1314status=$((status + ret))
1315if [ $ret != 0 ]; then echo_i "failed"; fi
1316
1317n=$((n + 1))
1318echo_i "disable responses from authoritative server ($n)"
1319ret=0
1320$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
1321grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1322grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
1323if [ $ret != 0 ]; then echo_i "failed"; fi
1324status=$((status + ret))
1325
1326n=$((n + 1))
1327echo_i "check 'rndc serve-stale status' ($n)"
1328ret=0
1329$RNDCCMD 10.53.0.4 serve-stale status >rndc.out.test$n 2>&1 || ret=1
1330grep "_default: stale cache enabled; stale answers disabled (stale-answer-ttl=$stale_answer_ttl max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n >/dev/null || ret=1
1331if [ $ret != 0 ]; then echo_i "failed"; fi
1332status=$((status + ret))
1333
1334sleep 2
1335
1336echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
1337$DIG -p ${PORT} @10.53.0.4 data.example TXT >dig.out.test$((n + 1)) &
1338$DIG -p ${PORT} @10.53.0.4 othertype.example CAA >dig.out.test$((n + 2)) &
1339$DIG -p ${PORT} @10.53.0.4 nodata.example TXT >dig.out.test$((n + 3)) &
1340$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT >dig.out.test$((n + 4)) &
1341
1342wait
1343
1344n=$((n + 1))
1345echo_i "check fail of data.example TXT (serve-stale answers disabled) ($n)"
1346ret=0
1347grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1348grep "EDE" dig.out.test$n >/dev/null && ret=1
1349grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1350if [ $ret != 0 ]; then echo_i "failed"; fi
1351status=$((status + ret))
1352
1353n=$((n + 1))
1354echo_i "check fail of othertype.example TXT (serve-stale answers disabled) ($n)"
1355ret=0
1356grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1357grep "EDE" dig.out.test$n >/dev/null && ret=1
1358grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1359if [ $ret != 0 ]; then echo_i "failed"; fi
1360status=$((status + ret))
1361
1362n=$((n + 1))
1363echo_i "check fail of nodata.example TXT (serve-stale answers disabled) ($n)"
1364ret=0
1365grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1366grep "EDE" dig.out.test$n >/dev/null && ret=1
1367grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1368if [ $ret != 0 ]; then echo_i "failed"; fi
1369status=$((status + ret))
1370
1371n=$((n + 1))
1372echo_i "check fail of nxdomain.example TXT (serve-stale answers disabled) ($n)"
1373ret=0
1374grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1375grep "EDE" dig.out.test$n >/dev/null && ret=1
1376grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1377if [ $ret != 0 ]; then echo_i "failed"; fi
1378status=$((status + ret))
1379
1380n=$((n + 1))
1381echo_i "verify stale cache statistics (serve-stale answers disabled) ($n)"
1382ret=0
1383rm -f ns4/named.stats
1384$RNDCCMD 10.53.0.4 stats >/dev/null 2>&1
1385[ -f ns4/named.stats ] || ret=1
1386cp ns4/named.stats ns4/named.stats.$n
1387# Check first 10 lines of Cache DB statistics. After last queries, we expect
1388# one active TXT RRset, one stale TXT, one stale nxrrset TXT, and one stale
1389# NXDOMAIN.
1390grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1
1391grep "1 TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1392grep "1 #TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1393grep "1 #Others" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1394grep "1 #!TXT" ns4/named.stats.$n.cachedb >/dev/null || ret=1
1395status=$((status + ret))
1396if [ $ret != 0 ]; then echo_i "failed"; fi
1397
1398# Dump the cache.
1399n=$((n + 1))
1400echo_i "dump the cache (serve-stale answers disabled) ($n)"
1401ret=0
1402rndc_dumpdb ns4 -cache || ret=1
1403if [ $ret != 0 ]; then echo_i "failed"; fi
1404status=$((status + ret))
1405
1406echo_i "stop ns4"
1407stop_server --use-rndc --port ${CONTROLPORT} ns4
1408
1409# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older. Since
1410# max-stale-ttl defaults to a week, we need to adjust the date by one week and
1411# five minutes.
1412LASTWEEK=$(TZ=UTC perl -e 'my $now = time();
1413        my $oneWeekAgo = $now - 604800;
1414        my $fiveMinutesAgo = $oneWeekAgo - 300;
1415        my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5];
1416        printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);')
1417
1418echo_i "mock the cache date to $LASTWEEK (serve-stale answers disabled) ($n)"
1419ret=0
1420sed -E "s/DATE [0-9]{14}/DATE $LASTWEEK/g" ns4/named_dump.db.test$n >ns4/named_dump.db.out || ret=1
1421cp ns4/named_dump.db.out ns4/named_dump.db
1422if [ $ret != 0 ]; then echo_i "failed"; fi
1423status=$((status + ret))
1424
1425echo_i "start ns4"
1426start_server --noclean --restart --port ${PORT} ns4
1427
1428n=$((n + 1))
1429echo_i "verify ancient cache statistics (serve-stale answers disabled) ($n)"
1430ret=0
1431rm -f ns4/named.stats
1432$RNDCCMD 10.53.0.4 stats #> /dev/null 2>&1
1433[ -f ns4/named.stats ] || ret=1
1434cp ns4/named.stats ns4/named.stats.$n
1435# Check first 10 lines of Cache DB statistics. After last queries, we expect
1436# everything to be removed or scheduled to be removed.
1437grep -A 10 "++ Cache DB RRsets ++" ns4/named.stats.$n >ns4/named.stats.$n.cachedb || ret=1
1438grep "#TXT" ns4/named.stats.$n.cachedb >/dev/null && ret=1
1439grep "#Others" ns4/named.stats.$n.cachedb >/dev/null && ret=1
1440grep "#!TXT" ns4/named.stats.$n.cachedb >/dev/null && ret=1
1441grep "#NXDOMAIN" ns4/named.stats.$n.cachedb >/dev/null && ret=1
1442status=$((status + ret))
1443if [ $ret != 0 ]; then echo_i "failed"; fi
1444
1445#
1446# Test the server with stale-cache disabled.
1447#
1448echo_i "test server with serve-stale cache disabled"
1449
1450n=$((n + 1))
1451echo_i "enable responses from authoritative server ($n)"
1452ret=0
1453$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
1454grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1455grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1456if [ $ret != 0 ]; then echo_i "failed"; fi
1457status=$((status + ret))
1458
1459n=$((n + 1))
1460echo_i "prime cache longttl.example TXT (serve-stale cache disabled) ($n)"
1461ret=0
1462$DIG -p ${PORT} @10.53.0.5 longttl.example TXT >dig.out.test$n || ret=1
1463grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1464grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1465if [ $ret != 0 ]; then echo_i "failed"; fi
1466status=$((status + ret))
1467
1468n=$((n + 1))
1469echo_i "prime cache data.example TXT (serve-stale cache disabled) ($n)"
1470ret=0
1471$DIG -p ${PORT} @10.53.0.5 data.example TXT >dig.out.test$n || ret=1
1472grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1473grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1474grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1475if [ $ret != 0 ]; then echo_i "failed"; fi
1476status=$((status + ret))
1477
1478n=$((n + 1))
1479echo_i "prime cache othertype.example CAA (serve-stale cache disabled) ($n)"
1480ret=0
1481$DIG -p ${PORT} @10.53.0.5 othertype.example CAA >dig.out.test$n || ret=1
1482grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1483grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1484grep "othertype\.example\..*2.*IN.*CAA.*0.*issue" dig.out.test$n >/dev/null || ret=1
1485if [ $ret != 0 ]; then echo_i "failed"; fi
1486status=$((status + ret))
1487
1488n=$((n + 1))
1489echo_i "prime cache nodata.example TXT (serve-stale cache disabled) ($n)"
1490ret=0
1491$DIG -p ${PORT} @10.53.0.5 nodata.example TXT >dig.out.test$n || ret=1
1492grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1493grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1494grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1495if [ $ret != 0 ]; then echo_i "failed"; fi
1496status=$((status + ret))
1497
1498n=$((n + 1))
1499echo_i "prime cache nxdomain.example TXT (serve-stale cache disabled) ($n)"
1500ret=0
1501$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT >dig.out.test$n || ret=1
1502grep "status: NXDOMAIN" dig.out.test$n >/dev/null || ret=1
1503grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1504grep "example\..*2.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1505if [ $ret != 0 ]; then echo_i "failed"; fi
1506status=$((status + ret))
1507
1508n=$((n + 1))
1509echo_i "verify prime cache statistics (serve-stale cache disabled) ($n)"
1510ret=0
1511rm -f ns5/named.stats
1512$RNDCCMD 10.53.0.5 stats >/dev/null 2>&1
1513[ -f ns5/named.stats ] || ret=1
1514cp ns5/named.stats ns5/named.stats.$n
1515# Check first 10 lines of Cache DB statistics.  After serve-stale queries,
1516# we expect two active TXT RRsets, one active Others, one nxrrset TXT, and
1517# one NXDOMAIN.
1518grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1
1519grep "2 TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1520grep "1 Others" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1521grep "1 !TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1522status=$((status + ret))
1523if [ $ret != 0 ]; then echo_i "failed"; fi
1524
1525n=$((n + 1))
1526echo_i "disable responses from authoritative server ($n)"
1527ret=0
1528$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
1529grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1530grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
1531if [ $ret != 0 ]; then echo_i "failed"; fi
1532status=$((status + ret))
1533
1534n=$((n + 1))
1535echo_i "check 'rndc serve-stale status' ($n)"
1536ret=0
1537$RNDCCMD 10.53.0.5 serve-stale status >rndc.out.test$n 2>&1 || ret=1
1538grep "_default: stale cache disabled; stale answers unavailable" rndc.out.test$n >/dev/null || ret=1
1539if [ $ret != 0 ]; then echo_i "failed"; fi
1540status=$((status + ret))
1541
1542sleep 2
1543
1544echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
1545$DIG -p ${PORT} @10.53.0.5 data.example TXT >dig.out.test$((n + 1)) &
1546$DIG -p ${PORT} @10.53.0.5 othertype.example CAA >dig.out.test$((n + 2)) &
1547$DIG -p ${PORT} @10.53.0.5 nodata.example TXT >dig.out.test$((n + 3)) &
1548$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT >dig.out.test$((n + 4)) &
1549
1550wait
1551
1552n=$((n + 1))
1553echo_i "check fail of data.example TXT (serve-stale cache disabled) ($n)"
1554ret=0
1555grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1556grep "EDE" dig.out.test$n >/dev/null && ret=1
1557grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1558if [ $ret != 0 ]; then echo_i "failed"; fi
1559status=$((status + ret))
1560
1561n=$((n + 1))
1562echo_i "check fail of othertype.example CAA (serve-stale cache disabled) ($n)"
1563ret=0
1564grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1565grep "EDE" dig.out.test$n >/dev/null && ret=1
1566grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1567if [ $ret != 0 ]; then echo_i "failed"; fi
1568status=$((status + ret))
1569
1570n=$((n + 1))
1571echo_i "check fail of nodata.example TXT (serve-stale cache disabled) ($n)"
1572ret=0
1573grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1574grep "EDE" dig.out.test$n >/dev/null && ret=1
1575grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1576if [ $ret != 0 ]; then echo_i "failed"; fi
1577status=$((status + ret))
1578
1579n=$((n + 1))
1580echo_i "check fail of nxdomain.example TXT (serve-stale cache disabled) ($n)"
1581ret=0
1582grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
1583grep "EDE" dig.out.test$n >/dev/null && ret=1
1584grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1585if [ $ret != 0 ]; then echo_i "failed"; fi
1586status=$((status + ret))
1587
1588n=$((n + 1))
1589echo_i "verify stale cache statistics (serve-stale cache disabled) ($n)"
1590ret=0
1591rm -f ns5/named.stats
1592$RNDCCMD 10.53.0.5 stats >/dev/null 2>&1
1593[ -f ns5/named.stats ] || ret=1
1594cp ns5/named.stats ns5/named.stats.$n
1595# Check first 10 lines of Cache DB statistics.  After serve-stale queries,
1596# we expect one active TXT (longttl) and the rest to be expired from cache,
1597# but since we keep everything for 5 minutes (RBTDB_VIRTUAL) in the cache
1598# after expiry, they still show up in the stats.
1599grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1
1600grep -F "1 Others" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1601grep -F "2 TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1602grep -F "1 !TXT" ns5/named.stats.$n.cachedb >/dev/null || ret=1
1603status=$((status + ret))
1604if [ $ret != 0 ]; then echo_i "failed"; fi
1605
1606# Dump the cache.
1607n=$((n + 1))
1608echo_i "dump the cache (serve-stale cache disabled) ($n)"
1609ret=0
1610rndc_dumpdb ns5 || ret=1
1611if [ $ret != 0 ]; then echo_i "failed"; fi
1612status=$((status + ret))
1613# Check that expired records are not dumped.
1614ret=0
1615grep "; expired since .* (awaiting cleanup)" ns5/named_dump.db.test$n && ret=1
1616if [ $ret != 0 ]; then echo_i "failed"; fi
1617status=$((status + ret))
1618
1619# Dump the cache including expired entries.
1620n=$((n + 1))
1621echo_i "dump the cache including expired entries (serve-stale cache disabled) ($n)"
1622ret=0
1623rndc_dumpdb ns5 -expired || ret=1
1624if [ $ret != 0 ]; then echo_i "failed"; fi
1625status=$((status + ret))
1626
1627# Check that expired records are dumped.
1628echo_i "check rndc dump expired data.example ($n)"
1629ret=0
1630awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
1631  | grep "; expired since .* (awaiting cleanup) data\.example\..*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1
1632awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
1633  | grep "; expired since .* (awaiting cleanup) nodata\.example\." >/dev/null 2>&1 || ret=1
1634awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
1635  | grep "; expired since .* (awaiting cleanup) nxdomain\.example\." >/dev/null 2>&1 || ret=1
1636awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
1637  | grep "; expired since .* (awaiting cleanup) othertype\.example\." >/dev/null 2>&1 || ret=1
1638# Also make sure the not expired data does not have an expired comment.
1639awk '/; authanswer/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
1640  | grep "; authanswer longttl\.example.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1
1641if [ $ret != 0 ]; then echo_i "failed"; fi
1642status=$((status + ret))
1643
1644echo_i "stop ns5"
1645stop_server --use-rndc --port ${CONTROLPORT} ns5
1646
1647# Load the cache as if it was five minutes (RBTDB_VIRTUAL) older.
1648cp ns5/named_dump.db.test$n ns5/named_dump.db
1649FIVEMINUTESAGO=$(TZ=UTC perl -e 'my $now = time();
1650        my $fiveMinutesAgo = 300;
1651        my ($s, $m, $h, $d, $mo, $y) = (localtime($fiveMinutesAgo))[0, 1, 2, 3, 4, 5];
1652        printf("%04d%02d%02d%02d%02d%02d", $y+1900, $mo+1, $d, $h, $m, $s);')
1653
1654n=$((n + 1))
1655echo_i "mock the cache date to $FIVEMINUTESAGO (serve-stale cache disabled) ($n)"
1656ret=0
1657sed -E "s/DATE [0-9]{14}/DATE $FIVEMINUTESAGO/g" ns5/named_dump.db >ns5/named_dump.db.out || ret=1
1658cp ns5/named_dump.db.out ns5/named_dump.db
1659if [ $ret != 0 ]; then echo_i "failed"; fi
1660status=$((status + ret))
1661
1662echo_i "start ns5"
1663start_server --noclean --restart --port ${PORT} ns5
1664
1665n=$((n + 1))
1666echo_i "verify ancient cache statistics (serve-stale cache disabled) ($n)"
1667ret=0
1668rm -f ns5/named.stats
1669$RNDCCMD 10.53.0.5 stats #> /dev/null 2>&1
1670[ -f ns5/named.stats ] || ret=1
1671cp ns5/named.stats ns5/named.stats.$n
1672# Check first 10 lines of Cache DB statistics. After last queries, we expect
1673# everything to be removed or scheduled to be removed.
1674grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n >ns5/named.stats.$n.cachedb || ret=1
1675grep -F "#TXT" ns5/named.stats.$n.cachedb >/dev/null && ret=1
1676grep -F "#Others" ns5/named.stats.$n.cachedb >/dev/null && ret=1
1677grep -F "#!TXT" ns5/named.stats.$n.cachedb >/dev/null && ret=1
1678status=$((status + ret))
1679if [ $ret != 0 ]; then echo_i "failed"; fi
1680
1681#############################################
1682# Test for stale-answer-client-timeout off. #
1683#############################################
1684echo_i "test stale-answer-client-timeout (off)"
1685
1686n=$((n + 1))
1687echo_i "updating ns3/named.conf ($n)"
1688ret=0
1689copy_setports ns3/named3.conf.in ns3/named.conf
1690if [ $ret != 0 ]; then echo_i "failed"; fi
1691status=$((status + ret))
1692
1693n=$((n + 1))
1694echo_i "running 'rndc reload' ($n)"
1695ret=0
1696rndc_reload ns3 10.53.0.3
1697if [ $ret != 0 ]; then echo_i "failed"; fi
1698status=$((status + ret))
1699
1700# Send a query, auth server is disabled, we will enable it after a while in
1701# order to receive an answer before resolver-query-timeout expires. Since
1702# stale-answer-client-timeout is disabled we must receive an answer from
1703# authoritative server.
1704echo_i "sending query for test $((n + 2))"
1705$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 2)) &
1706sleep 3
1707
1708n=$((n + 1))
1709echo_i "enable responses from authoritative server ($n)"
1710ret=0
1711$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
1712grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1713grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1714if [ $ret != 0 ]; then echo_i "failed"; fi
1715status=$((status + ret))
1716
1717# Wait until dig is done.
1718wait
1719
1720n=$((n + 1))
1721echo_i "check data.example TXT comes from authoritative server (stale-answer-client-timeout off) ($n)"
1722grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1723grep "EDE" dig.out.test$n >/dev/null && ret=1
1724grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1725grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1726if [ $ret != 0 ]; then echo_i "failed"; fi
1727status=$((status + ret))
1728
1729check_server_responds() {
1730  $DIG -p ${PORT} @10.53.0.3 version.bind txt ch >dig.out.test$n || return 1
1731  grep "status: NOERROR" dig.out.test$n >/dev/null || return 1
1732}
1733
1734##############################################################
1735# Test for stale-answer-client-timeout off and CNAME record. #
1736##############################################################
1737echo_i "test stale-answer-client-timeout (0) and CNAME record"
1738
1739n=$((n + 1))
1740echo_i "prime cache shortttl.cname.example (stale-answer-client-timeout off) ($n)"
1741ret=0
1742$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A >dig.out.test$n || ret=1
1743grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1744grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
1745grep "shortttl\.cname\.example\..*1.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n >/dev/null || ret=1
1746grep "longttl\.target\.example\..*600.*IN.*A.*10\.53\.0\.2" dig.out.test$n >/dev/null || ret=1
1747if [ $ret != 0 ]; then echo_i "failed"; fi
1748status=$((status + ret))
1749
1750# Allow RRset to become stale.
1751sleep 1
1752
1753n=$((n + 1))
1754echo_i "disable responses from authoritative server ($n)"
1755ret=0
1756$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
1757grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1758grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
1759if [ $ret != 0 ]; then echo_i "failed"; fi
1760status=$((status + ret))
1761
1762n=$((n + 1))
1763ret=0
1764echo_i "check stale shortttl.cname.example comes from cache (stale-answer-client-timeout off) ($n)"
1765nextpart ns3/named.run >/dev/null
1766$DIG -p ${PORT} @10.53.0.3 shortttl.cname.example A >dig.out.test$n || ret=1
1767wait_for_log 5 "shortttl.cname.example A resolver failure, stale answer used" ns3/named.run || ret=1
1768grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1769grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n >/dev/null || ret=1
1770grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
1771grep "shortttl\.cname\.example\..*3.*IN.*CNAME.*longttl\.target\.example\." dig.out.test$n >/dev/null || ret=1
1772# We can't reliably test the TTL of the longttl.target.example A record.
1773grep "longttl\.target\.example\..*IN.*A.*10\.53\.0\.2" dig.out.test$n >/dev/null || ret=1
1774if [ $ret != 0 ]; then echo_i "failed"; fi
1775status=$((status + ret))
1776
1777n=$((n + 1))
1778echo_i "enable responses from authoritative server ($n)"
1779ret=0
1780$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
1781grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1782grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1783if [ $ret != 0 ]; then echo_i "failed"; fi
1784status=$((status + ret))
1785
1786n=$((n + 1))
1787echo_i "check server is alive or restart ($n)"
1788ret=0
1789$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1
1790if [ $ret != 0 ]; then
1791  echo_i "failed"
1792  echo_i "restart ns3"
1793  start_server --noclean --restart --port ${PORT} serve-stale ns3
1794fi
1795status=$((status + ret))
1796
1797n=$((n + 1))
1798echo_i "check server is alive or restart ($n)"
1799ret=0
1800$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1
1801if [ $ret != 0 ]; then
1802  echo_i "failed"
1803  echo_i "restart ns3"
1804  start_server --noclean --restart --port ${PORT} serve-stale ns3
1805fi
1806status=$((status + ret))
1807
1808#############################################
1809# Test for stale-answer-client-timeout 0.   #
1810#############################################
1811echo_i "test stale-answer-client-timeout (0)"
1812
1813n=$((n + 1))
1814echo_i "updating ns3/named.conf ($n)"
1815ret=0
1816copy_setports ns3/named4.conf.in ns3/named.conf
1817if [ $ret != 0 ]; then echo_i "failed"; fi
1818status=$((status + ret))
1819
1820echo_i "restart ns3"
1821stop_server --use-rndc --port ${CONTROLPORT} ns3
1822start_server --noclean --restart --port ${PORT} ns3
1823
1824n=$((n + 1))
1825echo_i "prime cache data.example TXT (stale-answer-client-timeout 0)"
1826ret=0
1827$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
1828grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1829grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1830if [ $ret != 0 ]; then echo_i "failed"; fi
1831status=$((status + ret))
1832
1833n=$((n + 1))
1834echo_i "prime cache nodata.example TXT (stale-answer-client-timeout 0)"
1835ret=0
1836$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1
1837grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1838grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1839if [ $ret != 0 ]; then echo_i "failed"; fi
1840status=$((status + ret))
1841
1842n=$((n + 1))
1843echo_i "disable responses from authoritative server ($n)"
1844ret=0
1845$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
1846grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1847grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
1848if [ $ret != 0 ]; then echo_i "failed"; fi
1849status=$((status + ret))
1850
1851# Allow RRset to become stale.
1852sleep 2
1853
1854n=$((n + 1))
1855ret=0
1856echo_i "check stale nodata.example TXT comes from cache (stale-answer-client-timeout 0) ($n)"
1857nextpart ns3/named.run >/dev/null
1858$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || ret=1
1859wait_for_log 5 "nodata.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
1860grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1861grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
1862grep "ANSWER: 0," dig.out.test$n >/dev/null || ret=1
1863grep "example\..*3.*IN.*SOA" dig.out.test$n >/dev/null || ret=1
1864if [ $ret != 0 ]; then echo_i "failed"; fi
1865status=$((status + ret))
1866
1867n=$((n + 1))
1868ret=0
1869echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0) ($n)"
1870nextpart ns3/named.run >/dev/null
1871$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
1872wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
1873grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1874grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
1875grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1876grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
1877if [ $ret != 0 ]; then echo_i "failed"; fi
1878status=$((status + ret))
1879
1880n=$((n + 1))
1881echo_i "enable responses from authoritative server ($n)"
1882ret=0
1883$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
1884grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1885grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1886if [ $ret != 0 ]; then echo_i "failed"; fi
1887status=$((status + ret))
1888
1889wait_for_rrset_refresh() {
1890  $DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || return 1
1891  grep "status: NOERROR" dig.out.test$n >/dev/null || return 1
1892  grep "EDE" dig.out.test$n >/dev/null && return 1
1893  grep "ANSWER: 1," dig.out.test$n >/dev/null || return 1
1894  grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || return 1
1895}
1896
1897# This test ensures that after we get stale data due to
1898# stale-answer-client-timeout 0, enabling the authoritative server will allow
1899# the RRset to be updated.
1900n=$((n + 1))
1901ret=0
1902echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0) ($n)"
1903retry_quiet 10 wait_for_rrset_refresh || ret=1
1904if [ $ret != 0 ]; then echo_i "failed"; fi
1905status=$((status + ret))
1906
1907wait_for_nodata_refresh() {
1908  $DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$n || return 1
1909  grep "status: NOERROR" dig.out.test$n >/dev/null || return 1
1910  grep "ANSWER: 0," dig.out.test$n >/dev/null || return 1
1911  grep "example\..*[12].*IN.*SOA" dig.out.test$n >/dev/null || return 1
1912  return 0
1913}
1914
1915n=$((n + 1))
1916ret=0
1917echo_i "check stale nodata.example TXT was refreshed (stale-answer-client-timeout 0) ($n)"
1918retry_quiet 10 wait_for_nodata_refresh || ret=1
1919if [ $ret != 0 ]; then echo_i "failed"; fi
1920status=$((status + ret))
1921
1922####################################################################
1923# Test for stale-answer-client-timeout 0 and recursive-clients 10. #
1924# CVE-2023-2911, GL #4089                                          #
1925# ##################################################################
1926echo_i "test stale-answer-client-timeout (0) and recursive-clients 10"
1927
1928n=$((n + 1))
1929echo_i "prime cache data.slow TXT (stale-answer-client-timeout 0) ($n)"
1930ret=0
1931$DIG -p ${PORT} @10.53.0.3 data.slow TXT >dig.out.test$n || ret=1
1932grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1933grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1934if [ $ret != 0 ]; then echo_i "failed"; fi
1935status=$((status + ret))
1936
1937# Run the following check twice. Sometimes a priming query interrupts the first
1938# attempt to exceed the quota.
1939attempt=0
1940while [ $ret -eq 0 ] && [ $attempt -lt 2 ]; do
1941  n=$((n + 1))
1942  echo_i "slow down response from authoritative server ($n)"
1943  ret=0
1944  $DIG -p ${PORT} @10.53.0.2 slowdown TXT >dig.out.test$n || ret=1
1945  grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
1946  grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
1947  if [ $ret != 0 ]; then echo_i "failed"; fi
1948  status=$((status + ret))
1949
1950  # Let the data.slow TTL expire
1951  sleep 2
1952
1953  n=$((n + 1))
1954  echo_i "check that named survives reaching recursive-clients quota (stale-answer-client-timeout 0) ($n)"
1955  ret=0
1956  num=0
1957  # Attempt to exceed the configured value of 'recursive-clients 10;' by running
1958  # 20 parallel queries for the stale domain which has slow auth.
1959  while [ $num -lt 20 ]; do
1960    $DIG +tries=1 +timeout=10 -p ${PORT} @10.53.0.3 data.slow TXT >/dev/null 2>&1 &
1961    num=$((num + 1))
1962  done
1963  # Let the dig processes finish.
1964  wait
1965  retry_quiet 5 check_server_responds || ret=1
1966  if [ $ret != 0 ]; then echo_i "failed"; fi
1967  status=$((status + ret))
1968
1969  attempt=$((attempt + 1))
1970done
1971
1972# Restart ns3 to avoid the exceeded recursive-clients limit from previous check
1973# to interfere with subsequent checks.
1974echo_i "restart ns3"
1975stop_server --use-rndc --port ${CONTROLPORT} ns3
1976start_server --noclean --restart --port ${PORT} ns3
1977
1978############################################################
1979# Test for stale-answer-client-timeout 0 and CNAME record. #
1980############################################################
1981echo_i "test stale-answer-client-timeout (0) and CNAME record"
1982
1983n=$((n + 1))
1984echo_i "prime cache cname1.stale.test A (stale-answer-client-timeout 0) ($n)"
1985ret=0
1986$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A >dig.out.test$n || ret=1
1987grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
1988grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
1989grep "cname1\.stale\.test\..*1.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n >/dev/null || ret=1
1990grep "a1\.stale\.test\..*1.*IN.*A.*192\.0\.2\.1" dig.out.test$n >/dev/null || ret=1
1991if [ $ret != 0 ]; then echo_i "failed"; fi
1992status=$((status + ret))
1993
1994# Allow RRset to become stale.
1995sleep 1
1996
1997n=$((n + 1))
1998ret=0
1999echo_i "check stale cname1.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)"
2000nextpart ns3/named.run >/dev/null
2001$DIG -p ${PORT} @10.53.0.3 cname1.stale.test A >dig.out.test$n || ret=1
2002wait_for_log 5 "cname1.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
2003grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2004grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
2005grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
2006grep "cname1\.stale\.test\..*3.*IN.*CNAME.*a1\.stale\.test\." dig.out.test$n >/dev/null || ret=1
2007grep "a1\.stale\.test\..*3.*IN.*A.*192\.0\.2\.1" dig.out.test$n >/dev/null || ret=1
2008if [ $ret != 0 ]; then echo_i "failed"; fi
2009status=$((status + ret))
2010
2011n=$((n + 1))
2012echo_i "check server is alive or restart ($n)"
2013ret=0
2014$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1
2015if [ $ret != 0 ]; then
2016  echo_i "failed"
2017  echo_i "restart ns3"
2018  start_server --noclean --restart --port ${PORT} ns3
2019fi
2020status=$((status + ret))
2021
2022n=$((n + 1))
2023echo_i "prime cache cname2.stale.test A (stale-answer-client-timeout 0) ($n)"
2024ret=0
2025$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1
2026grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2027grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
2028grep "cname2\.stale\.test\..*1.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1
2029grep "a2\.stale\.test\..*300.*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1
2030if [ $ret != 0 ]; then echo_i "failed"; fi
2031status=$((status + ret))
2032
2033# Allow CNAME record in the RRSET to become stale.
2034sleep 1
2035
2036n=$((n + 1))
2037ret=0
2038echo_i "check stale cname2.stale.test A comes from cache (stale-answer-client-timeout 0) ($n)"
2039nextpart ns3/named.run >/dev/null
2040$DIG -p ${PORT} @10.53.0.3 cname2.stale.test A >dig.out.test$n || ret=1
2041wait_for_log 5 "cname2.stale.test A stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
2042grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2043grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
2044grep "ANSWER: 2," dig.out.test$n >/dev/null || ret=1
2045grep "cname2\.stale\.test\..*3.*IN.*CNAME.*a2\.stale\.test\." dig.out.test$n >/dev/null || ret=1
2046# We can't reliably test the TTL of the a2.stale.test A record.
2047grep "a2\.stale\.test\..*IN.*A.*192\.0\.2\.2" dig.out.test$n >/dev/null || ret=1
2048if [ $ret != 0 ]; then echo_i "failed"; fi
2049status=$((status + ret))
2050
2051n=$((n + 1))
2052echo_i "check server is alive or restart ($n)"
2053ret=0
2054$RNDCCMD 10.53.0.3 status >rndc.out.test$n 2>&1 || ret=1
2055if [ $ret != 0 ]; then
2056  echo_i "failed"
2057  echo_i "restart ns3"
2058  start_server --noclean --restart --port ${PORT} ns3
2059fi
2060status=$((status + ret))
2061
2062####################################################################
2063# Test for stale-answer-client-timeout 0 and stale-refresh-time 4. #
2064####################################################################
2065echo_i "test stale-answer-client-timeout (0) and stale-refresh-time (4)"
2066
2067n=$((n + 1))
2068echo_i "updating ns3/named.conf ($n)"
2069ret=0
2070copy_setports ns3/named5.conf.in ns3/named.conf
2071if [ $ret != 0 ]; then echo_i "failed"; fi
2072status=$((status + ret))
2073
2074n=$((n + 1))
2075echo_i "running 'rndc reload' ($n)"
2076ret=0
2077rndc_reload ns3 10.53.0.3
2078if [ $ret != 0 ]; then echo_i "failed"; fi
2079status=$((status + ret))
2080
2081n=$((n + 1))
2082echo_i "flush cache, enable responses from authoritative server ($n)"
2083ret=0
2084$RNDCCMD 10.53.0.3 flushtree example >rndc.out.test$n.1 2>&1 || ret=1
2085$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
2086grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2087grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
2088if [ $ret != 0 ]; then echo_i "failed"; fi
2089status=$((status + ret))
2090
2091n=$((n + 1))
2092echo_i "prime cache data.example TXT (stale-answer-client-timeout 0, stale-refresh-time 4) ($n)"
2093ret=0
2094$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2095grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2096grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2097grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2098if [ $ret != 0 ]; then echo_i "failed"; fi
2099status=$((status + ret))
2100
2101# Allow RRset to become stale.
2102sleep 2
2103
2104n=$((n + 1))
2105echo_i "disable responses from authoritative server ($n)"
2106ret=0
2107$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
2108grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2109grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
2110if [ $ret != 0 ]; then echo_i "failed"; fi
2111status=$((status + ret))
2112
2113n=$((n + 1))
2114ret=0
2115echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2116nextpart ns3/named.run >/dev/null
2117$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2118wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
2119grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2120grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
2121grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2122grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2123if [ $ret != 0 ]; then echo_i "failed"; fi
2124status=$((status + ret))
2125
2126n=$((n + 1))
2127echo_i "enable responses from authoritative server ($n)"
2128ret=0
2129$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
2130grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2131grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
2132if [ $ret != 0 ]; then echo_i "failed"; fi
2133status=$((status + ret))
2134
2135# This test ensures that after we get stale data due to
2136# stale-answer-client-timeout 0, enabling the authoritative server will allow
2137# the RRset to be updated.
2138n=$((n + 1))
2139ret=0
2140echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2141retry_quiet 10 wait_for_rrset_refresh || ret=1
2142if [ $ret != 0 ]; then echo_i "failed"; fi
2143status=$((status + ret))
2144
2145# Allow RRset to become stale.
2146sleep 2
2147
2148n=$((n + 1))
2149echo_i "disable responses from authoritative server ($n)"
2150ret=0
2151$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
2152grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2153grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
2154if [ $ret != 0 ]; then echo_i "failed"; fi
2155status=$((status + ret))
2156
2157n=$((n + 1))
2158ret=0
2159echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2160nextpart ns3/named.run >/dev/null
2161$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2162wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
2163grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2164grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
2165grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2166grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2167if [ $ret != 0 ]; then echo_i "failed"; fi
2168status=$((status + ret))
2169
2170# Allow stale-refresh-time to be activated.
2171n=$((n + 1))
2172ret=0
2173echo_i "wait until resolver query times out, activating stale-refresh-time"
2174wait_for_log 15 "data.example/TXT stale refresh failed: timed out" ns3/named.run || ret=1
2175if [ $ret != 0 ]; then echo_i "failed"; fi
2176status=$((status + ret))
2177
2178n=$((n + 1))
2179ret=0
2180echo_i "check stale data.example TXT comes from cache within stale-refresh-time (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2181nextpart ns3/named.run >/dev/null
2182$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2183wait_for_log 5 "data.example TXT query within stale refresh time" ns3/named.run || ret=1
2184grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2185grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1
2186grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2187grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2188if [ $ret != 0 ]; then echo_i "failed"; fi
2189status=$((status + ret))
2190
2191n=$((n + 1))
2192echo_i "enable responses from authoritative server ($n)"
2193ret=0
2194$DIG -p ${PORT} @10.53.0.2 txt enable >dig.out.test$n || ret=1
2195grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2196grep "TXT.\"1\"" dig.out.test$n >/dev/null || ret=1
2197if [ $ret != 0 ]; then echo_i "failed"; fi
2198status=$((status + ret))
2199
2200# We give BIND some time to ensure that after we enable authoritative server,
2201# this RRset is still not refreshed because it was hit during
2202# stale-refresh-time window.
2203sleep 1
2204
2205n=$((n + 1))
2206ret=0
2207echo_i "check stale data.example TXT was not refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2208nextpart ns3/named.run >/dev/null
2209$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2210wait_for_log 5 "data.example TXT query within stale refresh time" ns3/named.run || ret=1
2211grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2212grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n >/dev/null || ret=1
2213grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2214grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2215if [ $ret != 0 ]; then echo_i "failed"; fi
2216status=$((status + ret))
2217
2218# After the refresh-time-window, the RRset will be refreshed.
2219sleep 4
2220
2221n=$((n + 1))
2222ret=0
2223echo_i "check stale data.example TXT comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2224$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2225wait_for_log 5 "data.example TXT stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1
2226grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2227grep "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" dig.out.test$n >/dev/null || ret=1
2228grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2229grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2230if [ $ret != 0 ]; then echo_i "failed"; fi
2231status=$((status + ret))
2232
2233n=$((n + 1))
2234ret=0
2235echo_i "check stale data.example TXT was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)"
2236$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2237grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2238grep "EDE" dig.out.test$n >/dev/null && ret=1
2239grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2240grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2241if [ $ret != 0 ]; then echo_i "failed"; fi
2242status=$((status + ret))
2243
2244####################################################################
2245# Test serve-stale's interaction with fetch limits (cache only) #
2246#################################################################
2247echo_i "test serve-stale's interaction with fetch-limits (cache only)"
2248
2249# We update the named configuration to enable fetch-limits. The fetch-limits
2250# are set to 1, which is ridiciously low, but that is because for this test we
2251# want to reach the fetch-limits.
2252n=$((n + 1))
2253echo_i "updating ns3/named.conf ($n)"
2254ret=0
2255copy_setports ns3/named6.conf.in ns3/named.conf
2256if [ $ret != 0 ]; then echo_i "failed"; fi
2257status=$((status + ret))
2258
2259n=$((n + 1))
2260echo_i "running 'rndc reload' ($n)"
2261ret=0
2262rndc_reload ns3 10.53.0.3
2263if [ $ret != 0 ]; then echo_i "failed"; fi
2264status=$((status + ret))
2265
2266# Disable responses from authoritative server. If we can't resolve the example
2267# zone, fetch limits will be reached.
2268n=$((n + 1))
2269echo_i "disable responses from authoritative server ($n)"
2270ret=0
2271$DIG -p ${PORT} @10.53.0.2 txt disable >dig.out.test$n || ret=1
2272grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2273grep "TXT.\"0\"" dig.out.test$n >/dev/null || ret=1
2274if [ $ret != 0 ]; then echo_i "failed"; fi
2275status=$((status + ret))
2276
2277# Allow RRset to become stale.
2278sleep 2
2279
2280# Turn on serve-stale.
2281n=$((n + 1))
2282echo_i "running 'rndc serve-stale on' ($n)"
2283ret=0
2284$RNDCCMD 10.53.0.3 serve-stale on || ret=1
2285if [ $ret != 0 ]; then echo_i "failed"; fi
2286status=$((status + ret))
2287
2288n=$((n + 1))
2289echo_i "check 'rndc serve-stale status' ($n)"
2290ret=0
2291$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1
2292grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1
2293if [ $ret != 0 ]; then echo_i "failed"; fi
2294status=$((status + ret))
2295
2296# Hit the fetch-limits. We burst the name server with a small batch of queries.
2297# Only 2 queries are required to hit the fetch-limits. The first query will
2298# start to resolve, the second one hit the fetch-limits.
2299burst() {
2300  num=${1}
2301  rm -f burst.input.$$
2302  while [ $num -gt 0 ]; do
2303    num=$((num - 1))
2304    echo "fetch${num}.example A" >>burst.input.$$
2305  done
2306  $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 -b ${EXTRAPORT8} burst.input.$$
2307  rm -f burst.input.$$
2308}
2309
2310wait_for_fetchlimits() {
2311  burst 2
2312  # We expect a query for nx.example to fail because fetch-limits for
2313  # the domain 'example.' (and everything below) has been reached.
2314  $DIG -p ${PORT} +tries=1 +timeout=1 @10.53.0.3 nx.example >dig.out.test$n || return 1
2315  grep "status: SERVFAIL" dig.out.test$n >/dev/null || return 1
2316}
2317
2318n=$((n + 1))
2319echo_i "hit fetch limits ($n)"
2320ret=0
2321retry_quiet 10 wait_for_fetchlimits || ret=1
2322if [ $ret != 0 ]; then echo_i "failed"; fi
2323status=$((status + ret))
2324
2325# Expect stale data now (because fetch-limits for the domain 'example.' (and
2326# everything below) has been reached. But we have a stale RRset for
2327# 'data.example/TXT' that can be used.
2328n=$((n + 1))
2329ret=0
2330echo_i "check stale data.example TXT comes from cache (fetch-limits) ($n)"
2331nextpart ns3/named.run >/dev/null
2332$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2333wait_for_log 5 "data.example TXT resolver failure, stale answer used" ns3/named.run || ret=1
2334grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2335grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n >/dev/null || ret=1
2336grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2337grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2338if [ $ret != 0 ]; then echo_i "failed"; fi
2339status=$((status + ret))
2340
2341# The previous query should not have started the stale-refresh-time window.
2342n=$((n + 1))
2343ret=0
2344echo_i "check stale data.example TXT comes from cache again (fetch-limits) ($n)"
2345nextpart ns3/named.run >/dev/null
2346$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$n || ret=1
2347wait_for_log 5 "data.example TXT resolver failure, stale answer used" ns3/named.run || ret=1
2348grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
2349grep "EDE: 3 (Stale Answer): (resolver failure" dig.out.test$n >/dev/null || ret=1
2350grep "ANSWER: 1," dig.out.test$n >/dev/null || ret=1
2351grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n >/dev/null || ret=1
2352if [ $ret != 0 ]; then echo_i "failed"; fi
2353status=$((status + ret))
2354
2355########################################################################
2356# Test serve-stale's interaction with fetch limits (dual-mode) #
2357########################################################################
2358echo_i "test serve-stale's interaction with fetch limits (dual-mode)"
2359
2360# Update named configuration so that ns3 becomes a recursive resolver which is
2361# also a secondary server for the root zone.
2362n=$((n + 1))
2363echo_i "updating ns3/named.conf ($n)"
2364ret=0
2365copy_setports ns3/named7.conf.in ns3/named.conf
2366if [ $ret != 0 ]; then echo_i "failed"; fi
2367status=$((status + ret))
2368
2369n=$((n + 1))
2370echo_i "running 'rndc reload' ($n)"
2371ret=0
2372rndc_reload ns3 10.53.0.3
2373if [ $ret != 0 ]; then echo_i "failed"; fi
2374status=$((status + ret))
2375
2376n=$((n + 1))
2377echo_i "check 'rndc serve-stale status' ($n)"
2378ret=0
2379$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1
2380grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1
2381if [ $ret != 0 ]; then echo_i "failed"; fi
2382status=$((status + ret))
2383
2384# Flush the cache to ensure the example/NS RRset cached during previous tests
2385# does not override the authoritative delegation found in the root zone.
2386n=$((n + 1))
2387echo_i "flush cache ($n)"
2388ret=0
2389$RNDCCMD 10.53.0.3 flush >rndc.out.test$n 2>&1 || ret=1
2390if [ $ret != 0 ]; then echo_i "failed"; fi
2391status=$((status + ret))
2392
2393# Test that after flush, serve-stale configuration is not reset.
2394n=$((n + 1))
2395echo_i "check serve-stale configuration is not reset after flush ($n)"
2396ret=0
2397$RNDCCMD 10.53.0.3 serve-stale status >rndc.out.test$n 2>&1 || ret=1
2398grep '_default: stale cache enabled; stale answers enabled (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n >/dev/null || ret=1
2399if [ $ret != 0 ]; then echo_i "failed"; fi
2400status=$((status + ret))
2401
2402# Query name server with low fetch limits. The authoritative server (ans2) is
2403# not responding. Sending queries for multiple names in the 'example' zone
2404# in parallel causes the fetch limit for that zone (set to 1) to be
2405# reached. This should not trigger a crash.
2406echo_i "sending queries for tests $((n + 1))-$((n + 4))..."
2407$DIG -p ${PORT} @10.53.0.3 data.example TXT >dig.out.test$((n + 1)) &
2408$DIG -p ${PORT} @10.53.0.3 othertype.example CAA >dig.out.test$((n + 2)) &
2409$DIG -p ${PORT} @10.53.0.3 nodata.example TXT >dig.out.test$((n + 3)) &
2410$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT >dig.out.test$((n + 4)) &
2411
2412wait
2413
2414# Expect SERVFAIL for the entries not in cache.
2415n=$((n + 1))
2416echo_i "check stale data.example TXT (fetch-limits dual-mode) ($n)"
2417ret=0
2418grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
2419if [ $ret != 0 ]; then echo_i "failed"; fi
2420status=$((status + ret))
2421
2422n=$((n + 1))
2423echo_i "check stale othertype.example CAA (fetch-limits dual-mode) ($n)"
2424ret=0
2425grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
2426if [ $ret != 0 ]; then echo_i "failed"; fi
2427status=$((status + ret))
2428
2429n=$((n + 1))
2430echo_i "check stale nodata.example TXT (fetch-limits dual-mode) ($n)"
2431ret=0
2432grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
2433if [ $ret != 0 ]; then echo_i "failed"; fi
2434status=$((status + ret))
2435
2436n=$((n + 1))
2437echo_i "check stale nxdomain.example TXT (fetch-limits dual-mode) ($n)"
2438ret=0
2439grep "status: SERVFAIL" dig.out.test$n >/dev/null || ret=1
2440if [ $ret != 0 ]; then echo_i "failed"; fi
2441status=$((status + ret))
2442
2443n=$((n + 1))
2444echo_i "check DNS64 processing of a stale negative answer ($n)"
2445ret=0
2446# configure ns3 with dns64
2447copy_setports ns3/named8.conf.in ns3/named.conf
2448rndc_reload ns3 10.53.0.3
2449# flush cache, enable ans2 responses, make sure serve-stale is on
2450$RNDCCMD 10.53.0.3 flush >rndc.out.test$n.1 2>&1 || ret=1
2451$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1
2452$RNDCCMD 10.53.0.3 serve-stale on >rndc.out.test$n.2 2>&1 || ret=1
2453# prime the cache with an AAAA NXRRSET response
2454$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA >dig.out.1.test$n || ret=1
2455grep "status: NOERROR" dig.out.1.test$n >/dev/null || ret=1
2456grep "2001:aaaa" dig.out.1.test$n >/dev/null || ret=1
2457# disable responses from the auth server
2458$DIG -p ${PORT} @10.53.0.2 txt disable >/dev/null || ret=1
2459# wait two seconds for the previous answer to become stale
2460sleep 2
2461# resend the query and wait in the background; we should get a stale answer
2462$DIG -p ${PORT} @10.53.0.3 a-only.example AAAA >dig.out.2.test$n &
2463# re-enable queries after a pause, so the server gets a real answer too
2464sleep 2
2465$DIG -p ${PORT} @10.53.0.2 txt enable >/dev/null || ret=1
2466wait
2467grep "status: NOERROR" dig.out.2.test$n >/dev/null || ret=1
2468grep "2001:aaaa" dig.out.2.test$n >/dev/null || ret=1
2469if [ $ret != 0 ]; then echo_i "failed"; fi
2470status=$((status + ret))
2471
2472echo_i "exit status: $status"
2473[ $status -eq 0 ] || exit 1
2474