mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '2066-fix-serve-stale' into 'main'
Resolve "Fix serve-stale so that it is usable when needed" Closes #2066 See merge request isc-projects/bind9!4273
This commit is contained in:
commit
fece7a4881
29 changed files with 688 additions and 92 deletions
5
CHANGES
5
CHANGES
|
|
@ -1,3 +1,8 @@
|
|||
5533. [func] Add "stale-refresh-time" option, a time window that
|
||||
starts after a failed lookup, during which stale rrset
|
||||
will be served directly from cache before a new
|
||||
attempt to refresh it is made. [GL #2066]
|
||||
|
||||
5532. [cleanup] Unused header files were removed:
|
||||
bin/rndc/include/rndc/os.h, lib/isc/timer_p.h,
|
||||
lib/isccfg/include/isccfg/dnsconf.h and code related
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ options {\n\
|
|||
servfail-ttl 1;\n\
|
||||
# sortlist <none>\n\
|
||||
stale-answer-enable false;\n\
|
||||
stale-refresh-time 30; /* 30 seconds */\n\
|
||||
stale-answer-ttl 1; /* 1 second */\n\
|
||||
stale-cache-enable false;\n\
|
||||
synth-from-dnssec no;\n\
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ OPTIONS
|
|||
stale-answer-enable boolean;
|
||||
stale-answer-ttl duration;
|
||||
stale-cache-enable boolean;
|
||||
stale-refresh-time duration;
|
||||
startup-notify-rate integer;
|
||||
statistics-file quoted_string;
|
||||
synth-from-dnssec boolean;
|
||||
|
|
@ -797,6 +798,7 @@ VIEW
|
|||
stale-answer-enable boolean;
|
||||
stale-answer-ttl duration;
|
||||
stale-cache-enable boolean;
|
||||
stale-refresh-time duration;
|
||||
synth-from-dnssec boolean;
|
||||
transfer-format ( many-answers | one-answer );
|
||||
transfer-source ( ipv4_address | * ) [ port ( integer | * ) ] [
|
||||
|
|
|
|||
|
|
@ -1869,7 +1869,7 @@ cache_reusable(dns_view_t *originview, dns_view_t *view,
|
|||
static bool
|
||||
cache_sharable(dns_view_t *originview, dns_view_t *view,
|
||||
bool new_zero_no_soattl, uint64_t new_max_cache_size,
|
||||
uint32_t new_stale_ttl) {
|
||||
uint32_t new_stale_ttl, uint32_t new_stale_refresh_time) {
|
||||
/*
|
||||
* If the cache cannot even reused for the same view, it cannot be
|
||||
* shared with other views.
|
||||
|
|
@ -1883,6 +1883,8 @@ cache_sharable(dns_view_t *originview, dns_view_t *view,
|
|||
* the sharing views.
|
||||
*/
|
||||
if (dns_cache_getservestalettl(originview->cache) != new_stale_ttl ||
|
||||
dns_cache_getservestalerefresh(originview->cache) !=
|
||||
new_stale_refresh_time ||
|
||||
dns_cache_getcachesize(originview->cache) != new_max_cache_size)
|
||||
{
|
||||
return (false);
|
||||
|
|
@ -3897,6 +3899,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
size_t max_adb_size;
|
||||
uint32_t lame_ttl, fail_ttl;
|
||||
uint32_t max_stale_ttl = 0;
|
||||
uint32_t stale_refresh_time = 0;
|
||||
dns_tsig_keyring_t *ring = NULL;
|
||||
dns_view_t *pview = NULL; /* Production view */
|
||||
isc_mem_t *cmctx = NULL, *hmctx = NULL;
|
||||
|
|
@ -4395,6 +4398,11 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
view->staleanswersok = dns_stale_answer_conf;
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "stale-refresh-time", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
stale_refresh_time = cfg_obj_asduration(obj);
|
||||
|
||||
/*
|
||||
* Configure the view's cache.
|
||||
*
|
||||
|
|
@ -4429,7 +4437,8 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
nsc = cachelist_find(cachelist, cachename, view->rdclass);
|
||||
if (nsc != NULL) {
|
||||
if (!cache_sharable(nsc->primaryview, view, zero_no_soattl,
|
||||
max_cache_size, max_stale_ttl))
|
||||
max_cache_size, max_stale_ttl,
|
||||
stale_refresh_time))
|
||||
{
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
|
|
@ -4529,6 +4538,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
|||
|
||||
dns_cache_setcachesize(cache, max_cache_size);
|
||||
dns_cache_setservestalettl(cache, max_stale_ttl);
|
||||
dns_cache_setservestalerefresh(cache, stale_refresh_time);
|
||||
|
||||
dns_cache_detach(&cache);
|
||||
|
||||
|
|
@ -16162,6 +16172,7 @@ named_server_servestale(named_server_t *server, isc_lex_t *lex,
|
|||
view = ISC_LIST_NEXT(view, link))
|
||||
{
|
||||
dns_ttl_t stale_ttl = 0;
|
||||
uint32_t stale_refresh = 0;
|
||||
dns_db_t *db = NULL;
|
||||
|
||||
if (classtxt != NULL && rdclass != view->rdclass) {
|
||||
|
|
@ -16181,6 +16192,7 @@ named_server_servestale(named_server_t *server, isc_lex_t *lex,
|
|||
db = NULL;
|
||||
dns_db_attach(view->cachedb, &db);
|
||||
(void)dns_db_getservestalettl(db, &stale_ttl);
|
||||
(void)dns_db_getservestalerefresh(db, &stale_refresh);
|
||||
dns_db_detach(&db);
|
||||
if (found) {
|
||||
CHECK(putstr(text, "\n"));
|
||||
|
|
@ -16210,8 +16222,10 @@ named_server_servestale(named_server_t *server, isc_lex_t *lex,
|
|||
}
|
||||
if (stale_ttl > 0) {
|
||||
snprintf(msg, sizeof(msg),
|
||||
" (stale-answer-ttl=%u max-stale-ttl=%u)",
|
||||
view->staleanswerttl, stale_ttl);
|
||||
" (stale-answer-ttl=%u max-stale-ttl=%u "
|
||||
"stale-refresh-time=%u)",
|
||||
view->staleanswerttl, stale_ttl,
|
||||
stale_refresh);
|
||||
CHECK(putstr(text, msg));
|
||||
}
|
||||
found = true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
options {
|
||||
stale-refresh-time 0;
|
||||
};
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
options {
|
||||
stale-refresh-time 29;
|
||||
};
|
||||
|
|
@ -139,6 +139,19 @@ grep '.*' < checkconf.out$n.2 > /dev/null && ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "checking named-checkconf servestale warnings ($n)"
|
||||
ret=0
|
||||
$CHECKCONF servestale.stale-refresh-time.0.conf > checkconf.out$n.1 2>&1
|
||||
grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" < checkconf.out$n.1 > /dev/null && ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
ret=0
|
||||
$CHECKCONF servestale.stale-refresh-time.29.conf > checkconf.out$n.1 2>&1
|
||||
grep "'stale-refresh-time' should either be 0 or otherwise 30 seconds or higher" < checkconf.out$n.1 > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
n=`expr $n + 1`
|
||||
echo_i "range checking fields that do not allow zero ($n)"
|
||||
ret=0
|
||||
|
|
|
|||
|
|
@ -589,6 +589,8 @@ static dns_dbmethods_t sampledb_methods = {
|
|||
NULL, /* getsize */
|
||||
NULL, /* setservestalettl */
|
||||
NULL, /* getservestalettl */
|
||||
NULL, /* setservestalerefresh */
|
||||
NULL, /* getservestalerefresh */
|
||||
NULL, /* setgluecachestats */
|
||||
NULL /* adjusthashsize */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ options {
|
|||
listen-on-v6 { none; };
|
||||
recursion yes;
|
||||
max-stale-ttl 3600;
|
||||
stale-answer-ttl 2;
|
||||
stale-answer-ttl 4;
|
||||
stale-answer-enable yes;
|
||||
stale-cache-enable yes;
|
||||
stale-refresh-time 30;
|
||||
servfail-ttl 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
41
bin/tests/system/serve-stale/ns1/named3.conf.in
Normal file
41
bin/tests/system/serve-stale/ns1/named3.conf.in
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
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";
|
||||
};
|
||||
|
|
@ -12,15 +12,6 @@
|
|||
. ../conf.sh
|
||||
|
||||
RNDCCMD="$RNDC -c ../common/rndc.conf -p ${CONTROLPORT} -s"
|
||||
|
||||
# wait up to 11 seconds to ensure that a file has been written
|
||||
waitfile () {
|
||||
for try in 0 1 2 3 4 5 6 7 8 9 10; do
|
||||
[ -s "$1" ] && break
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
DIG="$DIG +time=11"
|
||||
|
||||
max_stale_ttl=$(sed -ne 's,^[[:space:]]*max-stale-ttl \([[:digit:]]*\).*,\1,p' $TOP_SRCDIR/bin/named/config.c)
|
||||
|
|
@ -108,7 +99,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: on (stale-answer-ttl=2 max-stale-ttl=3600)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: on (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -120,18 +111,14 @@ $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
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 "data\.example\..*2.*IN.*TXT.*A text record with a 2 second ttl" 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))
|
||||
|
||||
|
|
@ -153,7 +140,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 "othertype\.example\..*2.*IN.*CAA.*0.*issue" 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,7 +149,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 "example\..*2.*IN.*SOA" 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,7 +158,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 "example\..*2.*IN.*SOA" 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))
|
||||
|
||||
|
|
@ -194,6 +181,77 @@ grep "1 #NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
|
|||
status=$((status+ret))
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
|
||||
# Test stale-refresh-time when serve-stale is enabled via configuration.
|
||||
# Steps for testing stale-refresh-time option (default).
|
||||
# 1. Prime cache data.example txt
|
||||
# 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)
|
||||
# 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.
|
||||
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: on (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
# Step 1-3 done above.
|
||||
|
||||
# Step 4.
|
||||
n=$((n+1))
|
||||
echo_i "sending query for test ($n)"
|
||||
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
|
||||
|
||||
# Step 5.
|
||||
echo_i "check stale data.example (stale-refresh-time) ($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 "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))
|
||||
|
||||
# Step 6.
|
||||
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))
|
||||
|
||||
# Step 7.
|
||||
echo_i "sending query for test $((n+1))"
|
||||
$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 cache (stale-refresh-time) ($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 "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))
|
||||
|
||||
#
|
||||
# Test disabling serve-stale via rndc.
|
||||
#
|
||||
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))
|
||||
echo_i "running 'rndc serve-stale off' ($n)"
|
||||
ret=0
|
||||
|
|
@ -205,7 +263,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: off (rndc) (stale-answer-ttl=2 max-stale-ttl=3600)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: off (rndc) (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -215,11 +273,7 @@ $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check stale data.example (serve-stale off) ($n)"
|
||||
|
|
@ -249,6 +303,9 @@ grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
#
|
||||
# Test enabling serve-stale via rndc.
|
||||
#
|
||||
n=$((n+1))
|
||||
echo_i "running 'rndc serve-stale on' ($n)"
|
||||
ret=0
|
||||
|
|
@ -260,7 +317,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: on (rndc) (stale-answer-ttl=2 max-stale-ttl=3600)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: on (rndc) (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -270,18 +327,14 @@ $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
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 "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
|
||||
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))
|
||||
|
||||
|
|
@ -290,7 +343,7 @@ echo_i "check stale othertype.example (serve-stale on) ($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 "othertype\.example\..*2.*IN.*CAA.*0.*issue" 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))
|
||||
|
||||
|
|
@ -299,7 +352,7 @@ echo_i "check stale nodata.example (serve-stale on) ($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 "example\..*2.*IN.*SOA" 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))
|
||||
|
||||
|
|
@ -308,7 +361,7 @@ echo_i "check stale nxdomain.example (serve-stale on) ($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 "example\..*2.*IN.*SOA" 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))
|
||||
|
||||
|
|
@ -330,7 +383,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: on (stale-answer-ttl=2 max-stale-ttl=3600)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: on (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -340,18 +393,14 @@ $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
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 "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
|
||||
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))
|
||||
|
||||
|
|
@ -360,7 +409,7 @@ echo_i "check stale othertype.example (serve-stale reset) ($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 "othertype.example\..*2.*IN.*CAA.*0.*issue" 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))
|
||||
|
||||
|
|
@ -369,7 +418,7 @@ echo_i "check stale nodata.example (serve-stale reset) ($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 "example\..*2.*IN.*SOA" 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))
|
||||
|
||||
|
|
@ -378,7 +427,7 @@ echo_i "check stale nxdomain.example (serve-stale reset) ($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 "example\..*2.*IN.*SOA" 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))
|
||||
|
||||
|
|
@ -393,7 +442,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: off (rndc) (stale-answer-ttl=2 max-stale-ttl=3600)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: off (rndc) (stale-answer-ttl=4 max-stale-ttl=3600 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -421,7 +470,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: off (rndc) (stale-answer-ttl=3 max-stale-ttl=20)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: off (rndc) (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -440,7 +489,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: on (rndc) (stale-answer-ttl=3 max-stale-ttl=20)' rndc.out.test$n > /dev/null || ret=1
|
||||
grep '_default: on (rndc) (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -498,6 +547,10 @@ grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
# keep track of time so we can access these rrset later,
|
||||
# when we expect them to become ancient.
|
||||
t1=`$PERL -e 'print time()'`
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "verify prime cache statistics (low max-stale-ttl) ($n)"
|
||||
ret=0
|
||||
|
|
@ -532,11 +585,7 @@ $DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check stale data.example (low max-stale-ttl) ($n)"
|
||||
|
|
@ -594,17 +643,27 @@ grep "1 #NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
|
|||
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 ';'`
|
||||
# we add 2 seconds to it since this is the ttl value of the records being tested.
|
||||
interval_to_ancient=$((interval_to_ancient + 2))
|
||||
t2=`$PERL -e 'print time()'`
|
||||
elapsed=$((t2 - t1))
|
||||
|
||||
# if elapsed time so far is less than max-stale-ttl + 2 seconds,
|
||||
# then we sleep enough to ensure that we'll ask for ancient rrsets
|
||||
# in the next queries.
|
||||
if [ $elapsed -lt $interval_to_ancient ]; then
|
||||
sleep $((interval_to_ancient - elapsed))
|
||||
fi
|
||||
|
||||
echo_i "sending queries for tests $((n+1))-$((n+4))..."
|
||||
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$((n+1)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 othertype.example CAA > dig.out.test$((n+2)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.1 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check ancient data.example (low max-stale-ttl) ($n)"
|
||||
|
|
@ -638,6 +697,201 @@ grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
|
|||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
# Test stale-refresh-time when serve-stale is enabled via rndc.
|
||||
# Steps for testing stale-refresh-time option (default).
|
||||
# 1. Prime cache data.example txt
|
||||
# 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)
|
||||
# 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.
|
||||
n=$((n+1))
|
||||
echo_i "flush cache, enable responses from authoritative server ($n)"
|
||||
ret=0
|
||||
$RNDCCMD 10.53.0.1 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 "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: on (rndc) (stale-answer-ttl=3 max-stale-ttl=20 stale-refresh-time=30)' rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
# Step 1.
|
||||
n=$((n+1))
|
||||
echo_i "prime cache data.example (stale-refresh-time rndc) ($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 "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))
|
||||
|
||||
# Step 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))
|
||||
|
||||
# Step 3.
|
||||
sleep 2
|
||||
|
||||
# Step 4.
|
||||
n=$((n+1))
|
||||
echo_i "sending query for test ($n)"
|
||||
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
|
||||
|
||||
# Step 5.
|
||||
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 "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))
|
||||
|
||||
# Step 6.
|
||||
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))
|
||||
|
||||
# Step 7.
|
||||
echo_i "sending query for test $((n+1))"
|
||||
$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 cache (stale-refresh-time rndc) ($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 "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))
|
||||
|
||||
# Steps for testing stale-refresh-time option (disabled).
|
||||
# 1. Prime cache data.example txt
|
||||
# 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)
|
||||
# 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.
|
||||
n=$((n+1))
|
||||
echo_i "updating ns1/named.conf ($n)"
|
||||
ret=0
|
||||
copy_setports ns1/named3.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: on (rndc) (stale-answer-ttl=3 max-stale-ttl=20 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 "flush cache, enable responses from authoritative server ($n)"
|
||||
ret=0
|
||||
$RNDCCMD 10.53.0.1 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))
|
||||
|
||||
# Step 1.
|
||||
n=$((n+1))
|
||||
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 "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))
|
||||
|
||||
# Step 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))
|
||||
|
||||
# Step 3.
|
||||
sleep 2
|
||||
|
||||
# Step 4.
|
||||
n=$((n+1))
|
||||
echo_i "sending query for test ($n)"
|
||||
$DIG -p ${PORT} @10.53.0.1 data.example TXT > dig.out.test$n
|
||||
|
||||
# Step 5.
|
||||
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 "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))
|
||||
|
||||
# Step 6.
|
||||
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))
|
||||
|
||||
# Step 7.
|
||||
echo_i "sending query for test $((n+1))"
|
||||
$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)"
|
||||
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\..*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))
|
||||
|
||||
#
|
||||
# Now test server with no serve-stale options set.
|
||||
#
|
||||
|
|
@ -731,7 +985,7 @@ 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: off (stale-answer-ttl=1 max-stale-ttl=$max_stale_ttl)" rndc.out.test$n > /dev/null || ret=1
|
||||
grep "_default: off (stale-answer-ttl=1 max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -743,11 +997,7 @@ $DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check fail of data.example (max-stale-ttl default) ($n)"
|
||||
|
|
@ -812,7 +1062,7 @@ 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=1 max-stale-ttl=$max_stale_ttl)" rndc.out.test$n > /dev/null || ret=1
|
||||
grep "_default: on (rndc) (stale-answer-ttl=1 max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -824,11 +1074,7 @@ $DIG -p ${PORT} @10.53.0.3 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.3 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.3 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check data.example (max-stale-ttl default) ($n)"
|
||||
|
|
@ -959,7 +1205,7 @@ n=$((n+1))
|
|||
echo_i "check 'rndc serve-stale status' ($n)"
|
||||
ret=0
|
||||
$RNDCCMD 10.53.0.4 serve-stale status > rndc.out.test$n 2>&1 || ret=1
|
||||
grep "_default: off (stale-answer-ttl=1 max-stale-ttl=$max_stale_ttl)" rndc.out.test$n > /dev/null || ret=1
|
||||
grep "_default: off (stale-answer-ttl=1 max-stale-ttl=$max_stale_ttl stale-refresh-time=30)" rndc.out.test$n > /dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
|
@ -971,11 +1217,7 @@ $DIG -p ${PORT} @10.53.0.4 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.4 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.4 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check fail of data.example (serve-stale answers disabled) ($n)"
|
||||
|
|
@ -1181,11 +1423,7 @@ $DIG -p ${PORT} @10.53.0.5 othertype.example CAA > dig.out.test$((n+2)) &
|
|||
$DIG -p ${PORT} @10.53.0.5 nodata.example TXT > dig.out.test$((n+3)) &
|
||||
$DIG -p ${PORT} @10.53.0.5 nxdomain.example TXT > dig.out.test$((n+4))
|
||||
|
||||
# ensure all files have been written before proceeding
|
||||
waitfile dig.out.test$((n+1))
|
||||
waitfile dig.out.test$((n+2))
|
||||
waitfile dig.out.test$((n+3))
|
||||
waitfile dig.out.test$((n+4))
|
||||
wait
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check fail of data.example (serve-stale cache disabled) ($n)"
|
||||
|
|
|
|||
|
|
@ -1839,6 +1839,19 @@ Boolean Options
|
|||
``stale-cache-enable``
|
||||
If ``yes``, enable the retaining of "stale" cached answers. Default ``no``.
|
||||
|
||||
``stale-refresh-time``
|
||||
If the name servers for a given zone are not answering, this sets the time
|
||||
window for which ``named`` will promptly return "stale" cached answers for
|
||||
that RRSet being requested before a new attempt in contacting the servers
|
||||
is made. For convenience, TTL-style time-unit suffixes may be used to
|
||||
specify the value. It also accepts ISO 8601 duration formats.
|
||||
|
||||
The default ``stale-refresh-time`` is 30 seconds, as RFC 8767 recommends
|
||||
that attempts to refresh to be done no more frequently than every 30
|
||||
seconds. A value of zero disables the feature, meaning that normal
|
||||
resolution will take place first, if that fails only then ``named`` will
|
||||
return "stale" cached answers.
|
||||
|
||||
``nocookie-udp-size``
|
||||
This sets the maximum size of UDP responses that are sent to queries
|
||||
without a valid server COOKIE. A value below 128 is silently
|
||||
|
|
|
|||
|
|
@ -464,6 +464,7 @@ options {
|
|||
stale\-answer\-enable boolean;
|
||||
stale\-answer\-ttl duration;
|
||||
stale\-cache\-enable boolean;
|
||||
stale\-refresh\-time duration;
|
||||
startup\-notify\-rate integer;
|
||||
statistics\-file quoted_string;
|
||||
synth\-from\-dnssec boolean;
|
||||
|
|
@ -892,6 +893,7 @@ view string [ class ] {
|
|||
stale\-answer\-enable boolean;
|
||||
stale\-answer\-ttl duration;
|
||||
stale\-cache\-enable boolean;
|
||||
stale\-refresh\-time duration;
|
||||
synth\-from\-dnssec boolean;
|
||||
transfer\-format ( many\-answers | one\-answer );
|
||||
transfer\-source ( ipv4_address | * ) [ port ( integer | * ) ] [
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ options {
|
|||
stale-answer-enable <boolean>;
|
||||
stale-answer-ttl <duration>;
|
||||
stale-cache-enable <boolean>;
|
||||
stale-refresh-time <duration>;
|
||||
startup-notify-rate <integer>;
|
||||
statistics-file <quoted_string>;
|
||||
statistics-interval <integer>; // ancient
|
||||
|
|
@ -758,6 +759,7 @@ view <string> [ <class> ] {
|
|||
stale-answer-enable <boolean>;
|
||||
stale-answer-ttl <duration>;
|
||||
stale-cache-enable <boolean>;
|
||||
stale-refresh-time <duration>;
|
||||
suppress-initial-notify <boolean>; // not yet implemented
|
||||
synth-from-dnssec <boolean>;
|
||||
topology { <address_match_element>; ... }; // ancient
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ options {
|
|||
stale-answer-enable <boolean>;
|
||||
stale-answer-ttl <duration>;
|
||||
stale-cache-enable <boolean>;
|
||||
stale-refresh-time <duration>;
|
||||
startup-notify-rate <integer>;
|
||||
statistics-file <quoted_string>;
|
||||
synth-from-dnssec <boolean>;
|
||||
|
|
@ -686,6 +687,7 @@ view <string> [ <class> ] {
|
|||
stale-answer-enable <boolean>;
|
||||
stale-answer-ttl <duration>;
|
||||
stale-cache-enable <boolean>;
|
||||
stale-refresh-time <duration>;
|
||||
synth-from-dnssec <boolean>;
|
||||
transfer-format ( many-answers | one-answer );
|
||||
transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ] [
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@
|
|||
stale-answer-enable <boolean>;
|
||||
stale-answer-ttl <duration>;
|
||||
stale-cache-enable <boolean>;
|
||||
stale-refresh-time <duration>;
|
||||
startup-notify-rate <integer>;
|
||||
statistics-file <quoted_string>;
|
||||
synth-from-dnssec <boolean>;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ New Features
|
|||
|
||||
- None.
|
||||
|
||||
- A new configuration option ``stale-refresh-time`` has been introduced, it
|
||||
allows stale RRset to be served directly from cache for a period of time
|
||||
after a failed lookup, before a new attempt to refresh it is made. [GL #2066]
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
|||
|
|
@ -1662,6 +1662,17 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
|
|||
}
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(options, "stale-refresh-time", &obj);
|
||||
if (obj != NULL) {
|
||||
uint32_t refresh_time = cfg_obj_asduration(obj);
|
||||
if (refresh_time > 0 && refresh_time < 30) {
|
||||
cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
|
||||
"'stale-refresh-time' should either be 0 "
|
||||
"or otherwise 30 seconds or higher");
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ struct dns_cache {
|
|||
char **db_argv;
|
||||
size_t size;
|
||||
dns_ttl_t serve_stale_ttl;
|
||||
dns_ttl_t serve_stale_refresh;
|
||||
isc_stats_t *stats;
|
||||
|
||||
/* Locked by 'filelock'. */
|
||||
|
|
@ -999,6 +1000,28 @@ dns_cache_getservestalettl(dns_cache_t *cache) {
|
|||
return (result == ISC_R_SUCCESS ? ttl : 0);
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_setservestalerefresh(dns_cache_t *cache, dns_ttl_t interval) {
|
||||
REQUIRE(VALID_CACHE(cache));
|
||||
|
||||
LOCK(&cache->lock);
|
||||
cache->serve_stale_refresh = interval;
|
||||
UNLOCK(&cache->lock);
|
||||
|
||||
(void)dns_db_setservestalerefresh(cache->db, interval);
|
||||
}
|
||||
|
||||
dns_ttl_t
|
||||
dns_cache_getservestalerefresh(dns_cache_t *cache) {
|
||||
isc_result_t result;
|
||||
dns_ttl_t interval;
|
||||
|
||||
REQUIRE(VALID_CACHE(cache));
|
||||
|
||||
result = dns_db_getservestalerefresh(cache->db, &interval);
|
||||
return (result == ISC_R_SUCCESS ? interval : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The cleaner task is shutting down; do the necessary cleanup.
|
||||
*/
|
||||
|
|
|
|||
22
lib/dns/db.c
22
lib/dns/db.c
|
|
@ -1089,6 +1089,28 @@ dns_db_getservestalettl(dns_db_t *db, dns_ttl_t *ttl) {
|
|||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_db_setservestalerefresh(dns_db_t *db, uint32_t interval) {
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
|
||||
|
||||
if (db->methods->setservestalerefresh != NULL) {
|
||||
return ((db->methods->setservestalerefresh)(db, interval));
|
||||
}
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_db_getservestalerefresh(dns_db_t *db, uint32_t *interval) {
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
|
||||
|
||||
if (db->methods->getservestalerefresh != NULL) {
|
||||
return ((db->methods->getservestalerefresh)(db, interval));
|
||||
}
|
||||
return (ISC_R_NOTIMPLEMENTED);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
|
||||
REQUIRE(dns_db_iszone(db));
|
||||
|
|
|
|||
|
|
@ -967,6 +967,8 @@ static dns_dbmethods_t rpsdb_db_methods = {
|
|||
NULL, /* getsize */
|
||||
NULL, /* setservestalettl */
|
||||
NULL, /* getservestalettl */
|
||||
NULL, /* setservestalerefresh */
|
||||
NULL, /* getservestalerefresh */
|
||||
NULL, /* setgluecachestats */
|
||||
NULL /* adjusthashsize */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -255,6 +255,28 @@ dns_cache_getservestalettl(dns_cache_t *cache);
|
|||
*\li 'cache' to be valid.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_cache_setservestalerefresh(dns_cache_t *cache, dns_ttl_t interval);
|
||||
/*%<
|
||||
* Sets the length of time to wait before attempting to refresh a rrset
|
||||
* if a previous attempt in doing so has failed.
|
||||
* During this time window if stale rrset are available in cache they
|
||||
* will be directly returned to client.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'cache' to be valid.
|
||||
*/
|
||||
|
||||
dns_ttl_t
|
||||
dns_cache_getservestalerefresh(dns_cache_t *cache);
|
||||
/*%<
|
||||
* Gets the 'stale-refresh-time' value, set by a previous call to
|
||||
* 'dns_cache_setservestalerefresh'.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'cache' to be valid.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_cache_flush(dns_cache_t *cache);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ typedef struct dns_dbmethods {
|
|||
uint64_t *records, uint64_t *bytes);
|
||||
isc_result_t (*setservestalettl)(dns_db_t *db, dns_ttl_t ttl);
|
||||
isc_result_t (*getservestalettl)(dns_db_t *db, dns_ttl_t *ttl);
|
||||
isc_result_t (*setservestalerefresh)(dns_db_t *db, uint32_t interval);
|
||||
isc_result_t (*getservestalerefresh)(dns_db_t *db, uint32_t *interval);
|
||||
isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
|
||||
isc_result_t (*adjusthashsize)(dns_db_t *db, size_t size);
|
||||
} dns_dbmethods_t;
|
||||
|
|
@ -238,6 +240,7 @@ struct dns_dbonupdatelistener {
|
|||
#define DNS_DBFIND_ADDITIONALOK 0x0100
|
||||
#define DNS_DBFIND_NOZONECUT 0x0200
|
||||
#define DNS_DBFIND_STALEOK 0x0400
|
||||
#define DNS_DBFIND_STALEENABLED 0x0800
|
||||
/*@}*/
|
||||
|
||||
/*@{*/
|
||||
|
|
@ -1701,6 +1704,39 @@ dns_db_getservestalettl(dns_db_t *db, dns_ttl_t *ttl);
|
|||
* \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_setservestalerefresh(dns_db_t *db, uint32_t interval);
|
||||
/*%<
|
||||
* Sets the length of time to wait before attempting to refresh a rrset
|
||||
* if a previous attempt in doing so has failed.
|
||||
* During this time window if stale rrset are available in cache they
|
||||
* will be directly returned to client.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'db' is a valid cache database.
|
||||
* \li 'interval' is number of seconds before attempting to refresh data.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS
|
||||
* \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_getservestalerefresh(dns_db_t *db, uint32_t *interval);
|
||||
/*%<
|
||||
* Gets the length of time in which stale answers are directly returned from
|
||||
* cache before attempting to refresh them, in case a previous attempt in
|
||||
* doing so has failed.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'db' is a valid cache database.
|
||||
* \li 'interval' is number of seconds before attempting to refresh data.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_SUCCESS
|
||||
* \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ typedef struct rdatasetheader {
|
|||
rbtdb_rdatatype_t type;
|
||||
atomic_uint_least16_t attributes;
|
||||
dns_trust_t trust;
|
||||
isc_stdtime_t last_refresh_fail_ts;
|
||||
struct noqname *noqname;
|
||||
struct noqname *closest;
|
||||
unsigned int is_mmapped : 1;
|
||||
|
|
@ -488,6 +489,13 @@ struct dns_rbtdb {
|
|||
*/
|
||||
dns_ttl_t serve_stale_ttl;
|
||||
|
||||
/*
|
||||
* The time after a failed lookup, where stale answers from cache
|
||||
* may be used directly in a DNS response without attempting a
|
||||
* new iterative lookup.
|
||||
*/
|
||||
uint32_t serve_stale_refresh;
|
||||
|
||||
/*
|
||||
* This is a linked list used to implement the LRU cache. There will
|
||||
* be node_lock_count linked lists here. Nodes in bucket 1 will be
|
||||
|
|
@ -4547,6 +4555,27 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
|
|||
stale > search->now) {
|
||||
mark_header_stale(search->rbtdb, header);
|
||||
*header_prev = header;
|
||||
/*
|
||||
* If DNS_DBFIND_STALEOK is set then it means we failed
|
||||
* to resolve the name during recursion, in this case we
|
||||
* mark the time in which the refresh failed.
|
||||
*/
|
||||
if ((search->options & DNS_DBFIND_STALEOK) != 0) {
|
||||
header->last_refresh_fail_ts = search->now;
|
||||
} else if ((search->options &
|
||||
DNS_DBFIND_STALEENABLED) != 0 &&
|
||||
search->now <
|
||||
(header->last_refresh_fail_ts +
|
||||
search->rbtdb->serve_stale_refresh))
|
||||
{
|
||||
/*
|
||||
* If we are within interval between last
|
||||
* refresh failure time + 'stale-refresh-time',
|
||||
* then don't skip this stale entry but use it
|
||||
* instead.
|
||||
*/
|
||||
return (false);
|
||||
}
|
||||
return ((search->options & DNS_DBFIND_STALEOK) == 0);
|
||||
}
|
||||
|
||||
|
|
@ -8379,6 +8408,29 @@ getservestalettl(dns_db_t *db, dns_ttl_t *ttl) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
setservestalerefresh(dns_db_t *db, uint32_t interval) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(IS_CACHE(rbtdb));
|
||||
|
||||
/* currently no bounds checking. 0 means disable. */
|
||||
rbtdb->serve_stale_refresh = interval;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getservestalerefresh(dns_db_t *db, uint32_t *interval) {
|
||||
dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
|
||||
|
||||
REQUIRE(VALID_RBTDB(rbtdb));
|
||||
REQUIRE(IS_CACHE(rbtdb));
|
||||
|
||||
*interval = rbtdb->serve_stale_refresh;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static dns_dbmethods_t zone_methods = { attach,
|
||||
detach,
|
||||
beginload,
|
||||
|
|
@ -8426,6 +8478,8 @@ static dns_dbmethods_t zone_methods = { attach,
|
|||
getsize,
|
||||
NULL, /* setservestalettl */
|
||||
NULL, /* getservestalettl */
|
||||
NULL, /* setservestalerefresh */
|
||||
NULL, /* getservestalerefresh */
|
||||
setgluecachestats,
|
||||
adjusthashsize };
|
||||
|
||||
|
|
@ -8476,6 +8530,8 @@ static dns_dbmethods_t cache_methods = { attach,
|
|||
NULL, /* getsize */
|
||||
setservestalettl,
|
||||
getservestalettl,
|
||||
setservestalerefresh,
|
||||
getservestalerefresh,
|
||||
NULL,
|
||||
adjusthashsize };
|
||||
|
||||
|
|
|
|||
|
|
@ -1309,6 +1309,8 @@ static dns_dbmethods_t sdb_methods = {
|
|||
NULL, /* getsize */
|
||||
NULL, /* setservestalettl */
|
||||
NULL, /* getservestalettl */
|
||||
NULL, /* setservestalerefresh */
|
||||
NULL, /* getservestalerefresh */
|
||||
NULL, /* setgluecachestats */
|
||||
NULL /* adjusthashsize */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1281,6 +1281,8 @@ static dns_dbmethods_t sdlzdb_methods = {
|
|||
NULL, /* getsize */
|
||||
NULL, /* setservestalettl */
|
||||
NULL, /* getservestalettl */
|
||||
NULL, /* setservestalerefresh */
|
||||
NULL, /* getservestalerefresh */
|
||||
NULL, /* setgluecachestats */
|
||||
NULL /* adjusthashsize */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ dns_cache_flushname
|
|||
dns_cache_flushnode
|
||||
dns_cache_getcachesize
|
||||
dns_cache_getname
|
||||
dns_cache_getservestalerefresh
|
||||
dns_cache_getservestalettl
|
||||
dns_cache_getstats
|
||||
dns_cache_load
|
||||
|
|
@ -93,6 +94,7 @@ dns_cache_renderxml
|
|||
@END LIBXML2
|
||||
dns_cache_setcachesize
|
||||
dns_cache_setfilename
|
||||
dns_cache_setservestalerefresh
|
||||
dns_cache_setservestalettl
|
||||
dns_cache_updatestats
|
||||
dns_catz_add_zone
|
||||
|
|
@ -198,6 +200,7 @@ dns_db_getnsec3parameters
|
|||
dns_db_getoriginnode
|
||||
dns_db_getrrsetstats
|
||||
dns_db_getservestalettl
|
||||
dns_db_getservestalerefresh
|
||||
dns_db_getsigningtime
|
||||
dns_db_getsize
|
||||
dns_db_getsoaserial
|
||||
|
|
@ -223,6 +226,7 @@ dns_db_serialize
|
|||
dns_db_setcachestats
|
||||
dns_db_setgluecachestats
|
||||
dns_db_setservestalettl
|
||||
dns_db_setservestalerefresh
|
||||
dns_db_setsigningtime
|
||||
dns_db_settask
|
||||
dns_db_subtractrdataset
|
||||
|
|
|
|||
|
|
@ -2051,6 +2051,7 @@ static cfg_clausedef_t view_clauses[] = {
|
|||
{ "stale-answer-enable", &cfg_type_boolean, 0 },
|
||||
{ "stale-answer-ttl", &cfg_type_duration, 0 },
|
||||
{ "stale-cache-enable", &cfg_type_boolean, 0 },
|
||||
{ "stale-refresh-time", &cfg_type_duration, 0 },
|
||||
{ "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
|
||||
{ "synth-from-dnssec", &cfg_type_boolean, 0 },
|
||||
{ "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_ANCIENT },
|
||||
|
|
|
|||
|
|
@ -5523,6 +5523,9 @@ query_lookup(query_ctx_t *qctx) {
|
|||
dns_clientinfo_t ci;
|
||||
dns_name_t *rpzqname = NULL;
|
||||
unsigned int dboptions;
|
||||
dns_ttl_t stale_ttl = 0;
|
||||
dns_ttl_t stale_refresh = 0;
|
||||
bool dbfind_stale = false;
|
||||
|
||||
CCTRACE(ISC_LOG_DEBUG(3), "query_lookup");
|
||||
|
||||
|
|
@ -5581,6 +5584,22 @@ query_lookup(query_ctx_t *qctx) {
|
|||
dboptions |= DNS_DBFIND_COVERINGNSEC;
|
||||
}
|
||||
|
||||
dns_db_getservestalerefresh(qctx->client->view->cachedb,
|
||||
&stale_refresh);
|
||||
dns_db_getservestalettl(qctx->client->view->cachedb, &stale_ttl);
|
||||
if (stale_refresh > 0) {
|
||||
if (qctx->client->view->staleanswersok == dns_stale_answer_yes)
|
||||
{
|
||||
dboptions |= DNS_DBFIND_STALEENABLED;
|
||||
} else if (qctx->client->view->staleanswersok ==
|
||||
dns_stale_answer_conf) {
|
||||
if (qctx->client->view->staleanswersenable &&
|
||||
stale_ttl > 0) {
|
||||
dboptions |= DNS_DBFIND_STALEENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = dns_db_findext(qctx->db, rpzqname, qctx->version, qctx->type,
|
||||
dboptions, qctx->client->now, &qctx->node,
|
||||
qctx->fname, &cm, &ci, qctx->rdataset,
|
||||
|
|
@ -5601,10 +5620,28 @@ query_lookup(query_ctx_t *qctx) {
|
|||
dns_cache_updatestats(qctx->view->cache, result);
|
||||
}
|
||||
|
||||
if ((qctx->client->query.dboptions & DNS_DBFIND_STALEOK) != 0) {
|
||||
/*
|
||||
* If DNS_DBFIND_STALEOK is set this means we are dealing with a
|
||||
* lookup following a failed lookup and it is okay to serve a stale
|
||||
* answer. This will start a time window in rbtdb, tracking the last
|
||||
* time the RRset lookup failed.
|
||||
*
|
||||
* A stale answer may also be served if this is a normal lookup,
|
||||
* the view has enabled serve-stale (DNS_DBFIND_STALE_ENABLED is set),
|
||||
* and the request is within the stale-refresh-time window. If this
|
||||
* is the case we have to make sure that the lookup found a stale
|
||||
* answer, otherwise "fresh" answers are also treated as stale.
|
||||
*/
|
||||
dbfind_stale = ((dboptions & DNS_DBFIND_STALEOK) != 0);
|
||||
if (dbfind_stale != 0 ||
|
||||
(((dboptions & DNS_DBFIND_STALEENABLED) != 0) &&
|
||||
STALE(qctx->rdataset)))
|
||||
{
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
bool success;
|
||||
|
||||
inc_stats(qctx->client, ns_statscounter_trystale);
|
||||
|
||||
qctx->client->query.dboptions &= ~DNS_DBFIND_STALEOK;
|
||||
if (dns_rdataset_isassociated(qctx->rdataset) &&
|
||||
dns_rdataset_count(qctx->rdataset) > 0 &&
|
||||
|
|
@ -5618,10 +5655,20 @@ query_lookup(query_ctx_t *qctx) {
|
|||
|
||||
dns_name_format(qctx->client->query.qname, namebuf,
|
||||
sizeof(namebuf));
|
||||
isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
"%s resolver failure, stale answer %s", namebuf,
|
||||
success ? "used" : "unavailable");
|
||||
if (dbfind_stale) {
|
||||
isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
"%s resolver failure, stale answer %s",
|
||||
namebuf,
|
||||
success ? "used" : "unavailable");
|
||||
} else {
|
||||
isc_log_write(ns_lctx, NS_LOGCATEGORY_SERVE_STALE,
|
||||
NS_LOGMODULE_QUERY, ISC_LOG_INFO,
|
||||
"%s query within stale refresh time, "
|
||||
"stale answer %s",
|
||||
namebuf,
|
||||
success ? "used" : "unavailable");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
QUERY_ERROR(qctx, DNS_R_SERVFAIL);
|
||||
|
|
@ -6833,7 +6880,6 @@ query_usestale(query_ctx_t *qctx) {
|
|||
|
||||
if (staleanswersok) {
|
||||
qctx->client->query.dboptions |= DNS_DBFIND_STALEOK;
|
||||
inc_stats(qctx->client, ns_statscounter_trystale);
|
||||
if (qctx->client->query.fetch != NULL) {
|
||||
dns_resolver_destroyfetch(&qctx->client->query.fetch);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue