Commit 33350626 authored by Michał Kępień's avatar Michał Kępień

Track forwarder timeouts in fetch contexts

Since following a delegation resets most fetch context state, address
marks (FCTX_ADDRINFO_MARK) set inside lib/dns/resolver.c are not
preserved when a delegation is followed.  This is fine for full
recursive resolution but when named is configured with "forward first;"
and one of the specified forwarders times out, triggering a fallback to
full recursive resolution, that forwarder should no longer be consulted
at each delegation point subsequently reached within a given fetch

Add a new badnstype_t enum value, badns_forwarder, and use it to mark a
forwarder as bad when it times out in a "forward first;" configuration.
Since the bad server list is not cleaned when a fetch context follows a
delegation, this prevents a forwarder from being queried again after
falling back to full recursive resolution.  Yet, as each fetch context
maintains its own list of bad servers, this change does not cause a
forwarder timeout to prevent that forwarder from being used by other
fetch contexts.
parent a38b31cc
......@@ -26,3 +26,6 @@ ns.example2 A
example3 NS ns.example3
ns.example3 A
example7 NS ns.example7
ns.example7 A
......@@ -46,6 +46,11 @@ zone "example4." {
file "example.db";
zone "example7." {
type master;
file "example.db";
zone "grafted." {
type master;
file "example.db";
......@@ -44,3 +44,9 @@ zone "example3." {
forward only;
forwarders { };
zone "example7." {
type forward;
forward first;
forwarders {; };
......@@ -11,6 +11,7 @@ SYSTEMTESTTOP=..
......@@ -131,5 +132,20 @@ $CHECKCONF ula-notinherited.conf | grep "forward first;" >/dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "checking that a forwarder timeout prevents it from being reused in the same fetch context"
# Make ans6 receive queries without responding to them.
echo "//" | $SENDCMD
# Query for a record in a zone which is forwarded to a non-responding forwarder
# and is delegated from the root to check whether the forwarder will be retried
# when a delegation is encountered after falling back to full recursive
# resolution.
$DIG $DIGOPTS txt.example7. txt @$f1 > dig.out.f1 || ret=1
# The forwarder for the "example7" zone should only be queried once.
sent=`sed -n '/sending packet to,/^$/p' ns3/ | grep ";txt.example7.*IN.*TXT" | wc -l`
if [ $sent -ne 1 ]; then ret=1; fi
if [ $ret != 0 ]; then echo_i "failed"; fi
status=`expr $status + $ret`
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
......@@ -253,7 +253,8 @@ typedef enum {
typedef enum {
badns_unreachable = 0,
} badnstype_t;
struct fetchctx {
......@@ -1206,6 +1207,18 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
dns_adb_timeout(fctx->adb, query->addrinfo);
* If "forward first;" is used and a forwarder timed
* out, do not attempt to query it again in this fetch
* context.
if (fctx->fwdpolicy == dns_fwdpolicy_first &&
add_bad(fctx, query->addrinfo, ISC_R_TIMEDOUT,
* We don't have an RTT for this query. Maybe the
* packet was lost, or maybe this server is very
......@@ -3176,6 +3189,12 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason,
case badns_validation:
break; /* counted as 'valfail' */
case badns_forwarder:
* We were called to prevent the given forwarder from
* being used again for this fetch context.
......@@ -638,6 +638,7 @@
./bin/tests/system/formerr/ SH 2018,2019
./bin/tests/system/formerr/ SH 2013,2015,2016,2018,2019
./bin/tests/system/formerr/twoquestions X 2013,2018,2019
./bin/tests/system/forward/ans6/startme X 2019
./bin/tests/system/forward/ SH 2000,2001,2004,2007,2012,2014,2015,2016,2018,2019
./bin/tests/system/forward/ns1/example.db X 2000,2001,2018
./bin/tests/system/forward/ns2/example.db X 2000,2001,2018
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment