From 11b74fc176f29820cbfff22e06ae9d8920b0a21c Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 28 Jan 2021 12:30:08 +0100 Subject: [PATCH] Add test for serve-stale /w fetch-limits Add a test case when fetch-limits are reached and we have stale data in cache. This test starts with a positive answer for 'data.example/TXT' in cache. 1. Reload named.conf to set fetch limits. 2. Disable responses from the authoritative server. 3. Now send a batch of queries to the resolver, until hitting the fetch limits. We can detect this by looking at the response RCODE, at some point we will see SERVFAIL responses. 4. At that point we will turn on serve-stale. 5. Clients should see stale answers now. 6. An incoming query should not set the stale-refresh-time window, so a following query should still get a stale answer because of a resolver failure (and not because it was in the stale-refresh-time window). --- bin/tests/system/serve-stale/ans2/ans.pl | 2 +- .../system/serve-stale/ns3/named6.conf.in | 50 ++++++++++ bin/tests/system/serve-stale/tests.sh | 99 +++++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 bin/tests/system/serve-stale/ns3/named6.conf.in diff --git a/bin/tests/system/serve-stale/ans2/ans.pl b/bin/tests/system/serve-stale/ans2/ans.pl index 8be8392f28..4bb9f896ff 100644 --- a/bin/tests/system/serve-stale/ans2/ans.pl +++ b/bin/tests/system/serve-stale/ans2/ans.pl @@ -145,7 +145,7 @@ sub reply_handler { $rcode = "NXDOMAIN"; } - # mark the answer as authoritative (by setting the 'aa' flag + # mark the answer as authoritative (by setting the 'aa' flag) return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); } diff --git a/bin/tests/system/serve-stale/ns3/named6.conf.in b/bin/tests/system/serve-stale/ns3/named6.conf.in new file mode 100644 index 0000000000..1aea7c85c2 --- /dev/null +++ b/bin/tests/system/serve-stale/ns3/named6.conf.in @@ -0,0 +1,50 @@ +/* + * 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 no; + stale-cache-enable yes; + stale-answer-ttl 3; + stale-answer-client-timeout disabled; + stale-refresh-time 4; + resolver-query-timeout 10; + fetches-per-zone 1 fail; + fetches-per-server 1 fail; + max-stale-ttl 3600; +}; + +zone "." { + type hint; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh index 92263d86df..47a117308e 100755 --- a/bin/tests/system/serve-stale/tests.sh +++ b/bin/tests/system/serve-stale/tests.sh @@ -2010,5 +2010,104 @@ grep "data\.example\..*[12].*IN.*TXT.*A text record with a 2 second ttl" dig.out if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) +#################################################################### +# Test if fetch-limits quota is reached, stale data is served. # +#################################################################### +echo_i "test stale data with fetch-limits" + +n=$((n+1)) +echo_i "updating ns3/named.conf ($n)" +ret=0 +copy_setports ns3/named6.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)) + +# Disable responses from authoritative server. +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)) + +# Hit the fetch-limits. +burst() { + num=${1} + rm -f burst.input.$$ + while [ $num -gt 0 ]; do + num=`expr $num - 1` + echo "${num}.data.example A" >> burst.input.$$ + done + $PERL ../ditch.pl -p ${PORT} -s 10.53.0.3 burst.input.$$ + rm -f burst.input.$$ +} + +wait_for_fetchlimits() { + burst 20 + $DIG -p ${PORT} @10.53.0.3 data.example A > dig.out.test$n + grep "status: SERVFAIL" dig.out.test$n > /dev/null || return 1 +} + +n=$((n+1)) +echo_i "hit fetch limits ($n)" +ret=0 +retry_quiet 10 wait_for_fetchlimits || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Allow RRset to become stale. +sleep 2 + +# Turn on serve-stale. +n=$((n+1)) +echo_i "running 'rndc serve-stale on' ($n)" +ret=0 +$RNDCCMD 10.53.0.3 serve-stale on || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +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 (rndc) (stale-answer-ttl=3 max-stale-ttl=3600 stale-refresh-time=4)' rndc.out.test$n > /dev/null || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + +# Expect stale data now. +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache (fetch-limits) ($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 resolver failure, stale answer used" 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)) + +# The previous query should not have started the stale-refresh-time window. +n=$((n+1)) +ret=0 +echo_i "check stale data.example comes from cache again (fetch-limits) ($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 resolver failure, stale answer used" 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)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1