From bea63000db96bce883ee75b1616f4e0930e77afc Mon Sep 17 00:00:00 2001 From: Diego Fronza Date: Wed, 23 Dec 2020 10:47:02 -0300 Subject: [PATCH] Add system tests for stale-answer-client-timeout This commit add 4 tests for the new option: 1. Test default configuration of stale-answer-client-timeout, a value of 1.8 seconds, with stale-refresh-time disabled. 2. Test disabling of stale-answer-client-timeout. 3. Test stale-answer-client-timeout with a value of zero, in this case we take advantage of a log entry which shows that a stale answer was promptly used before an attempt to refresh the RRset is made. We also check, by activating a disabled authoritative server, that the RRset was successfully refreshed after that. 4. Test stale-answer-client-timeout 0 with stale-refresh-time 4, in this test we want to ensure a couple things: - If we have a stale RRSet entry in cache, a request must be promptly answered with this data, while BIND must also attempt to refresh the RRSet in background. - If the attempt to refresh the RRSet times out, the RRSet must have its stale-refresh-time window activated. - If a new request for the same RRSet arrives, it must be promptly answered with stale data due to stale-refresh-time being active for this RRSet, in this case no attempt to refresh the RRSet is made. - Enable authoritative server, ensure that the RRSet was not refreshed, to honor stale-refresh-time. - Wait for stale-refresh-window time pass, send another request for the same RRSet, this time we expect the answer to be the stale entry in cache being hit due to stale-answer-client-timeout 0. - Send another request, this time we expect the answer to be an active RRSet, since it must have been refreshed during the previous request. (cherry picked from commit 35fd039d038419d0301737f3a9afdd2310a81234) --- bin/tests/system/serve-stale/clean.sh | 2 +- .../system/serve-stale/ns3/named2.conf.in | 48 ++ .../system/serve-stale/ns3/named3.conf.in | 48 ++ .../system/serve-stale/ns3/named4.conf.in | 48 ++ .../system/serve-stale/ns3/named5.conf.in | 48 ++ bin/tests/system/serve-stale/ns3/root.db | 11 + bin/tests/system/serve-stale/tests.sh | 466 +++++++++++++++++- 7 files changed, 667 insertions(+), 4 deletions(-) create mode 100644 bin/tests/system/serve-stale/ns3/named2.conf.in create mode 100644 bin/tests/system/serve-stale/ns3/named3.conf.in create mode 100644 bin/tests/system/serve-stale/ns3/named4.conf.in create mode 100644 bin/tests/system/serve-stale/ns3/named5.conf.in create mode 100644 bin/tests/system/serve-stale/ns3/root.db diff --git a/bin/tests/system/serve-stale/clean.sh b/bin/tests/system/serve-stale/clean.sh index 2784ba25a0..a089574d37 100644 --- a/bin/tests/system/serve-stale/clean.sh +++ b/bin/tests/system/serve-stale/clean.sh @@ -15,4 +15,4 @@ rm -f */named.run */named.memstats rm -f ns*/managed-keys.bind* rm -f ns*/named_dump* rm -f ns*/named.stats* -rm -f ns1/named.run.prev +rm -f ns*/named.run.prev diff --git a/bin/tests/system/serve-stale/ns3/named2.conf.in b/bin/tests/system/serve-stale/ns3/named2.conf.in new file mode 100644 index 0000000000..e91f67b044 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named2.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Test default stale-answer-client-timeout value + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-refresh-time 0; + max-stale-ttl 3600; + resolver-query-timeout 10; +}; + +zone "." { + type secondary; + primaries { 10.53.0.1; }; + file "root.bk"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named3.conf.in b/bin/tests/system/serve-stale/ns3/named3.conf.in new file mode 100644 index 0000000000..0520e514c1 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named3.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Test disable of stale-answer-client-timeout. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout off; + stale-refresh-time 0; + max-stale-ttl 3600; + resolver-query-timeout 10; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named4.conf.in b/bin/tests/system/serve-stale/ns3/named4.conf.in new file mode 100644 index 0000000000..5fd5ef82f4 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named4.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Test stale-answer-client-timeout 0. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout 0; + stale-refresh-time 0; + resolver-query-timeout 10; + max-stale-ttl 3600; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/named5.conf.in b/bin/tests/system/serve-stale/ns3/named5.conf.in new file mode 100644 index 0000000000..92b2cdf108 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named5.conf.in @@ -0,0 +1,48 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +/* + * Test stale-answer-client-timeout 0. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.3; + notify-source 10.53.0.3; + transfer-source 10.53.0.3; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.3; }; + listen-on-v6 { none; }; + dnssec-validation no; + recursion yes; + stale-answer-enable yes; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout 0; + stale-refresh-time 4; + resolver-query-timeout 10; + max-stale-ttl 3600; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/ns3/root.db b/bin/tests/system/serve-stale/ns3/root.db new file mode 100644 index 0000000000..8f779b0878 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/root.db @@ -0,0 +1,11 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, You can obtain one at http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +. 300 NS ns.nil. +ns.nil. 300 A 10.53.0.1 diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh index ebef10928a..4fce8828e7 100755 --- a/bin/tests/system/serve-stale/tests.sh +++ b/bin/tests/system/serve-stale/tests.sh @@ -20,7 +20,6 @@ stale_answer_ttl=$(sed -ne 's,^[[:space:]]*stale-answer-ttl \([[:digit:]]*\).*,\ status=0 n=0 - # # First test server with serve-stale options set. # @@ -189,7 +188,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi # 2. Disable responses from authoritative server. # 3. Sleep for TTL duration so rrset TTL expires (2 sec) # 4. Query data.example -# 5. Check if response come from stale rrset (3 sec TTL) +# 5. Check if response come from stale rrset (4 sec TTL) # 6. Enable responses from authoritative server. # 7. Query data.example # 8. Check if response come from stale rrset, since the query @@ -886,7 +885,7 @@ $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) # Step 8. n=$((n+1)) -echo_i "check stale data.example comes from authoritative (stale-refresh-time disabled) ($n)" +echo_i "check data.example comes from authoritative (stale-refresh-time disabled) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 @@ -1554,5 +1553,466 @@ grep -F "#NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null && ret=1 status=$((status+ret)) if [ $ret != 0 ]; then echo_i "failed"; fi +######################################################## +# Test for stale-answer-client-timeout (default 1.8s). # +######################################################## +echo_i "test stale-answer-client-timeout (default 1.8)" + +n=$((n+1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named2.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +echo_i "restart ns3" +$PERL ../stop.pl --use-rndc --port ${CONTROLPORT} serve-stale ns3 +start_server --noclean --restart --port ${PORT} serve-stale ns3 + +n=$((n+1)) +echo_i "check 'rndc serve-stale status' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale status > rndc.out.test$n 2>&1 || ret=1 +grep '_default: on (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=0)' rndc.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "prime cache data.example (stale-answer-client-timeout)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "prime cache nodata.example (stale-answer-client-timeout)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow RRset to become stale. +sleep 2 + +# We configured a long value of 30 seconds for resolver-query-timeout. +# That should give us enough time to receive an stale answer from cache +# after stale-answer-client-timeout timer of 1.8 sec triggers. +n=$((n+1)) +echo_i "check stale data.example comes from cache (default stale-answer-client-timeout) ($n)" +nextpart ns3/named.run > /dev/null +t1=`$PERL -e 'print time()'` +$DIG -p ${PORT} +tries=1 +timeout=10 @10.53.0.3 data.example TXT > dig.out.test$n +t2=`$PERL -e 'print time()'` +wait_for_log 5 "data.example client timeout, stale answer used" ns3/named.run || ret=1 +ret=0 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +# Default stale-answer-client-timeout is 1.8s, we allow some extra time +# just in case other tests are taking too much cpu. +[ $((t2 - t1)) -le 10 ] || { echo_i "query took $((t2 - t1))s to resolve."; ret=1; } +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +echo_i "sending queries for tests $((n+1))-$((n+2))..." +$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 nodata.example TXT > dig.out.test$((n+1)) & +$DIG -p ${PORT} +tries=1 +timeout=30 @10.53.0.3 nodata.example TXT > dig.out.test$((n+2)) +wait + +# Since nodata.example is cached as NXRRSET and marked as +# stale at this point, BIND must not return this RRset when +# stale-answer-client-timeout triggers, instead, it must attempt +# to refresh the RRset. +# Since the authoritative server is disabled and we are using +# resolver-query-timeout value of 10 seconds, we expect this +# query with a timeout of 3 seconds to time out. +n=$((n+1)) +echo_i "check query for nodata.example times out (default stale-answer-client-timeout) ($n)" +grep "connection timed out" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# For this query we expect BIND to return stale NXRRSET data +# for nodata.example after resolver-query-timeout expires. +n=$((n+1)) +echo_i "check stale nodata.example comes from cache after resolver-query-timeout expires (default stale-answer-client-timeout) ($n)" +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +############################################# +# Test for stale-answer-client-timeout off. # +############################################# +echo_i "test stale-answer-client-timeout (off)" + +n=$((n+1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named3.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Send a query, auth server is disabled, we will enable it after +# a while in order to receive an answer before resolver-query-timeout +# expires. Since stale-answer-client-timeout is disabled we must receive +# an answer from authoritative server. +echo_i "sending query for test $((n+2))" +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$((n+2)) & +sleep 3 + +n=$((n+1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Wait until dig is done. +wait + +n=$((n+1)) +echo_i "check data.example comes from authoritative server (stale-answer-client-timeout off) ($n)" +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +############################################# +# Test for stale-answer-client-timeout 0. # +############################################# +echo_i "test stale-answer-client-timeout (0)" + +n=$((n+1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named4.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +echo_i "restart ns3" +$PERL ../stop.pl --use-rndc --port ${CONTROLPORT} serve-stale ns3 +start_server --noclean --restart --port ${PORT} serve-stale ns3 + +n=$((n+1)) +echo_i "prime cache data.example (stale-answer-client-timeout 0)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "prime cache nodata.example (stale-answer-client-timeout 0)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache (stale-answer-client-timeout 0) ($n)" +nextpart ns3/named.run > /dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +wait_for_rrset_refresh() { + nextpart ns3/named.run | grep 'data.example.*2.*TXT.*"A text record with a 2 second ttl"' > /dev/null && return 0 + return 1 +} + +# This test ensures that after we get stale data due to +# stale-answer-client-timeout 0, enabling the authoritative server +# will allow the RRset to be updated. +n=$((n+1)) +ret=0 +echo_i "check stale data.example was refreshed (stale-answer-client-timeout 0) ($n)" +retry_quiet 10 wait_for_rrset_refresh || ret=1 +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +echo_i "sending queries for tests $((n+1))-$((n+2))..." +$DIG -p ${PORT} +tries=1 +timeout=3 @10.53.0.3 nodata.example TXT > dig.out.test$((n+1)) & +$DIG -p ${PORT} +tries=1 +timeout=30 @10.53.0.3 nodata.example TXT > dig.out.test$((n+2)) +wait + +# Since nodata.example is cached as NXRRSET and marked as +# stale at this point, BIND must not prompty return this RRset +# due to stale-answer-client-timeout == 0, instead, it must +# attempt to refresh the RRset. +# Since the authoritative server is disabled and we are using +# resolver-query-timeout value of 10 seconds, we expect this +# query with a timeout of 3 seconds to time out. +n=$((n+1)) +echo_i "check query for nodata.example times out (stale-answer-client-timeout 0) ($n)" +grep "connection timed out" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# For this query we expect BIND to return stale NXRRSET data +# for nodata.example after resolver-query-timeout expires. +n=$((n+1)) +echo_i "check stale nodata.example comes from cache after resolver-query-timeout expires (stale-answer-client-timeout 0) ($n)" +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +#################################################################### +# Test for stale-answer-client-timeout 0 and stale-refresh-time 4. # +#################################################################### +echo_i "test stale-answer-client-timeout (0) and stale-refresh-time (4)" + +n=$((n+1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named5.conf.in ns3/named.conf +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "running 'rndc reload' ($n)" +ret=0 +rndc_reload ns3 10.53.0.3 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "flush cache, enable responses from authoritative server ($n)" +ret=0 +$RNDCCMD 10.53.0.3 flushtree example > rndc.out.test$n.1 2>&1 || ret=1 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "prime cache data.example (stale-answer-client-timeout 0, stale-refresh-time 4) ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n+1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run > /dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# This test ensures that after we get stale data due to +# stale-answer-client-timeout 0, enabling the authoritative server +# will allow the RRset to be updated. +n=$((n+1)) +ret=0 +echo_i "check stale data.example was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +retry_quiet 10 wait_for_rrset_refresh || ret=1 +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow RRset to become stale. +sleep 2 + +n=$((n+1)) +echo_i "disable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt disable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"0\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run > /dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow stale-refresh-time to be activated. +n=$((n+1)) +ret=0 +echo_i "wait until resolver query times out, activating stale-refresh-time" +wait_for_log 15 "data.example resolver failure, stale answer used" ns3/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache within stale-refresh-time (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run > /dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example query within stale refresh time" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +echo_i "enable responses from authoritative server ($n)" +ret=0 +$DIG -p ${PORT} @10.53.0.2 txt enable > dig.out.test$n +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "TXT.\"1\"" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# We give BIND some time to ensure that after we enable authoritative server, +# this RRset is still not refreshed because it was hit during +# stale-refresh-time window. +sleep 1 + +n=$((n+1)) +ret=0 +echo_i "check stale data.example was not refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +nextpart ns3/named.run > /dev/null +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example query within stale refresh time" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# After the refresh-time-window, the RRset will be refreshed. +sleep 4 + +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +wait_for_log 5 "data.example stale answer used, an attempt to refresh the RRset" ns3/named.run || ret=1 +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*3.*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +n=$((n+1)) +ret=0 +echo_i "check stale data.example was refreshed (stale-answer-client-timeout 0 stale-refresh-time 4) ($n)" +$DIG -p ${PORT} @10.53.0.3 data.example TXT > dig.out.test$n +grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 +grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1