Merge branch '2267-extended-errors-stale-data-v9_18' into 'v9_18'

[v9_18] Add stale answer extended errors

See merge request isc-projects/bind9!6209
This commit is contained in:
Matthijs Mekking 2022-04-28 09:56:59 +00:00
commit cfcbdb6712
7 changed files with 172 additions and 17 deletions

View file

@ -1,3 +1,6 @@
5876. [func] Add DNS Extended Errors when stale answers are returned
from cache. [GL #2267]
5875. [bug] Fixed a deadlock that could occur if an rndc
connection arrived during the shutdown of network
interfaces. [GL #3272]

View file

@ -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;
};

View file

@ -33,7 +33,6 @@ options {
stale-answer-ttl 3;
stale-answer-enable yes;
stale-cache-enable yes;
stale-refresh-time 0;
servfail-ttl 0;
};

View file

@ -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";
};

View file

@ -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

View file

@ -25,7 +25,8 @@ Known Issues
New Features
~~~~~~~~~~~~
- None.
- Add DNS Extended Errors (:rfc:`8914`) when stale answers are returned from
cache. :gl:`#2267`
Removed Features
~~~~~~~~~~~~~~~~

View file

@ -5789,6 +5789,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");
@ -5901,8 +5902,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;
@ -5914,7 +5921,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.
@ -5933,7 +5943,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.
@ -5973,6 +5987,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 {
/*
@ -5985,7 +6002,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);
}