diff --git a/bin/tests/system/serve-stale/ns1/named2.conf.in b/bin/tests/system/serve-stale/ns1/named2.conf.in index 985cddb6f9..c1579031fb 100644 --- a/bin/tests/system/serve-stale/ns1/named2.conf.in +++ b/bin/tests/system/serve-stale/ns1/named2.conf.in @@ -29,10 +29,11 @@ options { listen-on { 10.53.0.1; }; listen-on-v6 { none; }; recursion yes; - max-stale-ttl 20; - stale-answer-ttl 3; + max-stale-ttl 3600; + stale-answer-ttl 4; stale-answer-enable yes; stale-cache-enable yes; + stale-refresh-time 0; servfail-ttl 0; }; diff --git a/bin/tests/system/serve-stale/ns1/named3.conf.in b/bin/tests/system/serve-stale/ns1/named3.conf.in index 263baa095c..985cddb6f9 100644 --- a/bin/tests/system/serve-stale/ns1/named3.conf.in +++ b/bin/tests/system/serve-stale/ns1/named3.conf.in @@ -33,7 +33,6 @@ options { stale-answer-ttl 3; stale-answer-enable yes; stale-cache-enable yes; - stale-refresh-time 0; servfail-ttl 0; }; diff --git a/bin/tests/system/serve-stale/ns1/named4.conf.in b/bin/tests/system/serve-stale/ns1/named4.conf.in new file mode 100644 index 0000000000..263baa095c --- /dev/null +++ b/bin/tests/system/serve-stale/ns1/named4.conf.in @@ -0,0 +1,43 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.1; + notify-source 10.53.0.1; + transfer-source 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { none; }; + recursion yes; + max-stale-ttl 20; + stale-answer-ttl 3; + stale-answer-enable yes; + stale-cache-enable yes; + stale-refresh-time 0; + servfail-ttl 0; +}; + +zone "." { + type primary; + file "root.db"; +}; diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh index 4acd22c600..e50e431017 100755 --- a/bin/tests/system/serve-stale/tests.sh +++ b/bin/tests/system/serve-stale/tests.sh @@ -121,7 +121,7 @@ awk '/; answer/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n | if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) -echo_i "sending queries for tests $((n+1))-$((n+4))..." +echo_i "sending queries for tests $((n+1))-$((n+5))..." $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) & $DIG -p ${PORT} @10.53.0.1 longttl.example TXT > dig.out.test$((n+2)) & $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+3)) & @@ -135,6 +135,7 @@ echo_i "check stale data.example ($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 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*4.*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)) @@ -144,6 +145,7 @@ echo_i "check non-stale longttl.example ($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 +grep "EDE" dig.out.test$n > /dev/null && ret=1 grep "longttl\.example\..*59[0-9].*IN.*TXT.*A text record with a 600 second ttl" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -153,6 +155,7 @@ echo_i "check stale othertype.example ($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 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -162,6 +165,7 @@ echo_i "check stale nodata.example ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -171,6 +175,7 @@ echo_i "check stale nxdomain.example ($n)" ret=0 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 +grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -204,7 +209,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi # 6. Enable responses from authoritative server. # 7. Query data.example # 8. Check if response come from stale rrset, since the query -# is within stale-refresh-time window. +# is still within stale-refresh-time window. n=$((n+1)) echo_i "check 'rndc serve-stale status' ($n)" ret=0 @@ -224,6 +229,7 @@ $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n echo_i "check stale data.example (stale-refresh-time) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*4.*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 @@ -248,6 +254,7 @@ n=$((n+1)) echo_i "check stale data.example comes from cache (stale-refresh-time) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*4.*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 @@ -256,6 +263,29 @@ status=$((status+ret)) # # Test disabling serve-stale via rndc. # + +n=$((n+1)) +echo_i "updating ns1/named.conf ($n)" +ret=0 +copy_setports ns1/named2.conf.in ns1/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 ns1 10.53.0.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.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1 +grep '_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 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status+ret)) + n=$((n+1)) echo_i "disable responses from authoritative server ($n)" ret=0 @@ -276,7 +306,7 @@ n=$((n+1)) echo_i "check 'rndc serve-stale status' ($n)" ret=0 $RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1 -grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1 +grep '_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 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -292,6 +322,7 @@ n=$((n+1)) echo_i "check stale data.example (serve-stale off) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" dig.out.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -299,6 +330,7 @@ n=$((n+1)) echo_i "check stale othertype.example (serve-stale off) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" dig.out.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -306,6 +338,7 @@ n=$((n+1)) echo_i "check stale nodata.example (serve-stale off) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" dig.out.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -313,6 +346,7 @@ n=$((n+1)) echo_i "check stale nxdomain.example (serve-stale off) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" dig.out.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -330,7 +364,7 @@ n=$((n+1)) echo_i "check 'rndc serve-stale status' ($n)" ret=0 $RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1 -grep '_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 +grep '_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 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -346,6 +380,7 @@ n=$((n+1)) echo_i "check stale data.example (serve-stale on) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*4.*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 @@ -355,6 +390,7 @@ n=$((n+1)) echo_i "check stale othertype.example (serve-stale on) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "othertype\.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -364,6 +400,7 @@ n=$((n+1)) echo_i "check stale nodata.example (serve-stale on) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -373,6 +410,7 @@ n=$((n+1)) echo_i "check stale nxdomain.example (serve-stale on) ($n)" ret=0 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -396,7 +434,7 @@ n=$((n+1)) echo_i "check 'rndc serve-stale status' ($n)" ret=0 $RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1 -grep '_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 +grep '_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 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -412,6 +450,7 @@ n=$((n+1)) echo_i "check stale data.example (serve-stale reset) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*4.*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 @@ -421,6 +460,7 @@ n=$((n+1)) echo_i "check stale othertype.example (serve-stale reset) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "othertype.example\..*4.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -430,6 +470,7 @@ n=$((n+1)) echo_i "check stale nodata.example (serve-stale reset) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -439,6 +480,7 @@ n=$((n+1)) echo_i "check stale nxdomain.example (serve-stale reset) ($n)" ret=0 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -455,7 +497,7 @@ n=$((n+1)) echo_i "check 'rndc serve-stale status' ($n)" ret=0 $RNDCCMD 10.53.0.1 serve-stale status > rndc.out.test$n 2>&1 || ret=1 -grep '_default: stale cache enabled; stale answers disabled (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1 +grep '_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 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -468,7 +510,7 @@ echo_i "test server with serve-stale options set, low max-stale-ttl" n=$((n+1)) echo_i "updating ns1/named.conf ($n)" ret=0 -copy_setports ns1/named2.conf.in ns1/named.conf +copy_setports ns1/named3.conf.in ns1/named.conf if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -604,6 +646,7 @@ n=$((n+1)) echo_i "check stale data.example (low max-stale-ttl) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" 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 @@ -613,6 +656,7 @@ n=$((n+1)) echo_i "check stale othertype.example (low max-stale-ttl) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "othertype\.example\..*3.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -622,6 +666,7 @@ n=$((n+1)) echo_i "check stale nodata.example (low max-stale-ttl) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" 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 @@ -631,6 +676,7 @@ n=$((n+1)) echo_i "check stale nxdomain.example (low max-stale-ttl) ($n)" ret=0 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" 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 @@ -657,7 +703,7 @@ status=$((status+ret)) if [ $ret != 0 ]; then echo_i "failed"; fi # Retrieve max-stale-ttl value. -interval_to_ancient=`grep 'max-stale-ttl' ns1/named2.conf.in | awk '{ print $2 }' | tr -d ';'` +interval_to_ancient=`grep 'max-stale-ttl' ns1/named3.conf.in | awk '{ print $2 }' | tr -d ';'` # We add 2 seconds to it since this is the ttl value of the records being # tested. interval_to_ancient=$((interval_to_ancient + 2)) @@ -682,6 +728,7 @@ n=$((n+1)) echo_i "check ancient data.example (low max-stale-ttl) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -690,6 +737,7 @@ n=$((n+1)) echo_i "check ancient othertype.example (low max-stale-ttl) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -698,6 +746,7 @@ n=$((n+1)) echo_i "check ancient nodata.example (low max-stale-ttl) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -706,6 +755,7 @@ n=$((n+1)) echo_i "check ancient nxdomain.example (low max-stale-ttl) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -772,6 +822,7 @@ $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n echo_i "check stale data.example (stale-refresh-time rndc) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" 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 @@ -796,6 +847,7 @@ n=$((n+1)) echo_i "check stale data.example comes from cache (stale-refresh-time rndc) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (query within stale refresh time window)" 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 @@ -814,7 +866,7 @@ status=$((status+ret)) n=$((n+1)) echo_i "updating ns1/named.conf ($n)" ret=0 -copy_setports ns1/named3.conf.in ns1/named.conf +copy_setports ns1/named4.conf.in ns1/named.conf if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status+ret)) @@ -849,6 +901,7 @@ echo_i "prime cache data.example (stale-refresh-time disabled) ($n)" ret=0 $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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 @@ -876,6 +929,7 @@ $DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n echo_i "check stale data.example (stale-refresh-time disabled) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" 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 @@ -900,6 +954,7 @@ n=$((n+1)) 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 "EDE" 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 @@ -1016,6 +1071,7 @@ n=$((n+1)) echo_i "check fail of data.example (max-stale-ttl default) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1024,6 +1080,7 @@ n=$((n+1)) echo_i "check fail of othertype.example (max-stale-ttl default) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1032,6 +1089,7 @@ n=$((n+1)) echo_i "check fail of nodata.example (max-stale-ttl default) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1040,6 +1098,7 @@ n=$((n+1)) echo_i "check fail of nxdomain.example (max-stale-ttl default) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1104,6 +1163,7 @@ n=$((n+1)) echo_i "check data.example (max-stale-ttl default) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "data\.example\..*30.*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 @@ -1113,6 +1173,7 @@ n=$((n+1)) echo_i "check othertype.example (max-stale-ttl default) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1 grep "example\..*30.*IN.*CAA.*0.*issue" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -1122,6 +1183,7 @@ n=$((n+1)) echo_i "check nodata.example (max-stale-ttl default) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*30.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -1131,6 +1193,7 @@ n=$((n+1)) echo_i "check nxdomain.example (max-stale-ttl default) ($n)" ret=0 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "example\..*30.*IN.*SOA" dig.out.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi @@ -1142,6 +1205,7 @@ n=$((n+1)) echo_i "check notfound.example (max-stale-ttl default) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1257,6 +1321,7 @@ n=$((n+1)) echo_i "check fail of data.example (serve-stale answers disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1265,6 +1330,7 @@ n=$((n+1)) echo_i "check fail of othertype.example (serve-stale answers disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1273,6 +1339,7 @@ n=$((n+1)) echo_i "check fail of nodata.example (serve-stale answers disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1281,6 +1348,7 @@ n=$((n+1)) echo_i "check fail of nxdomain.example (serve-stale answers disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1463,6 +1531,7 @@ n=$((n+1)) echo_i "check fail of data.example (serve-stale cache disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1471,6 +1540,7 @@ n=$((n+1)) echo_i "check fail of othertype.example (serve-stale cache disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1479,6 +1549,7 @@ n=$((n+1)) echo_i "check fail of nodata.example (serve-stale cache disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1487,6 +1558,7 @@ n=$((n+1)) echo_i "check fail of nxdomain.example (serve-stale cache disabled) ($n)" ret=0 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1666,6 +1738,7 @@ echo_i "check stale data.example comes from cache (stale-answer-client-timeout 1 ret=0 wait_for_log 5 "data.example client timeout, stale answer used" ns3/named.run || ret=1 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (client timeout)" 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 # Configured stale-answer-client-timeout is 1.8s, we allow some extra time @@ -1677,6 +1750,7 @@ status=$((status+ret)) n=$((n+1)) echo_i "check stale nodata.example comes from cache (stale-answer-client-timeout 1.8) ($n)" grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE: 3 (Stale Answer): (client timeout)" 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 @@ -1717,6 +1791,7 @@ n=$((n+1)) echo_i "check not in cache longttl.example comes from authoritative (stale-answer-client-timeout 1.8) ($n)" ret=0 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1 +grep "EDE" 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)) @@ -1763,6 +1838,7 @@ 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 "EDE" 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 @@ -1821,6 +1897,7 @@ nextpart ns3/named.run > /dev/null $DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$n wait_for_log 5 "nodata.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 "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" 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 @@ -1833,6 +1910,7 @@ 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 "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" 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 @@ -1861,6 +1939,7 @@ echo_i "check stale data.example was refreshed (stale-answer-client-timeout 0) ( 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 "EDE" 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 @@ -1939,6 +2018,7 @@ 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 "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" 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 @@ -1962,6 +2042,7 @@ echo_i "check stale data.example was refreshed (stale-answer-client-timeout 0 st 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 "EDE" 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 @@ -1986,6 +2067,7 @@ 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 "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" 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 @@ -2006,6 +2088,7 @@ 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 "EDE: 3 (Stale Answer): (query within stale refresh time window)" 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 @@ -2032,6 +2115,7 @@ 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 "EDE: 3 (Stale Answer): (query within stale refresh time window)" 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 @@ -2046,6 +2130,7 @@ echo_i "check stale data.example comes from cache (stale-answer-client-timeout 0 $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 "EDE: 3 (Stale Answer): (stale data prioritized over lookup)" 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 @@ -2056,6 +2141,7 @@ 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 "EDE" 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 @@ -2152,6 +2238,7 @@ 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 "EDE: 3 (Stale Answer): (resolver failure" 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 @@ -2165,6 +2252,7 @@ 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 "EDE: 3 (Stale Answer): (resolver failure" 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 diff --git a/lib/ns/query.c b/lib/ns/query.c index ec6b379a0d..d18bf7e22e 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -5794,6 +5794,7 @@ query_lookup(query_ctx_t *qctx) { bool stale_found = false; bool refresh_rrset = false; bool stale_refresh_window = false; + uint16_t ede = 0; CCTRACE(ISC_LOG_DEBUG(3), "query_lookup"); @@ -5906,8 +5907,14 @@ query_lookup(query_ctx_t *qctx) { dns_rdataset_count(qctx->rdataset) > 0 && STALE(qctx->rdataset)) { - qctx->rdataset->ttl = qctx->view->staleanswerttl; stale_found = true; + if (result == DNS_R_NCACHENXDOMAIN || + result == DNS_R_NXDOMAIN) { + ede = DNS_EDE_STALENXANSWER; + } else { + ede = DNS_EDE_STALEANSWER; + } + qctx->rdataset->ttl = qctx->view->staleanswerttl; inc_stats(qctx->client, ns_statscounter_usedstale); } else { stale_found = false; @@ -5919,7 +5926,10 @@ query_lookup(query_ctx_t *qctx) { NS_LOGMODULE_QUERY, ISC_LOG_INFO, "%s resolver failure, stale answer %s", namebuf, stale_found ? "used" : "unavailable"); - if (!stale_found) { + if (stale_found) { + ns_client_extendederror(qctx->client, ede, + "resolver failure"); + } else { /* * Resolver failure, no stale data, nothing more we * can do, return SERVFAIL. @@ -5938,7 +5948,11 @@ query_lookup(query_ctx_t *qctx) { "answer %s", namebuf, stale_found ? "used" : "unavailable"); - if (!stale_found) { + if (stale_found) { + ns_client_extendederror( + qctx->client, ede, + "query within stale refresh time window"); + } else { /* * During the stale refresh window explicitly do not try * to refresh the data, because a recent lookup failed. @@ -5978,6 +5992,9 @@ query_lookup(query_ctx_t *qctx) { namebuf); refresh_rrset = STALE(qctx->rdataset); qctx->client->nodetach = refresh_rrset; + ns_client_extendederror( + qctx->client, ede, + "stale data prioritized over lookup"); } } else { /* @@ -5990,7 +6007,10 @@ query_lookup(query_ctx_t *qctx) { "%s client timeout, stale answer %s", namebuf, stale_found ? "used" : "unavailable"); - if (!stale_found) { + if (stale_found) { + ns_client_extendederror(qctx->client, ede, + "client timeout"); + } else { return (result); }