verbose(VERB_ALGO, "cachedb msg expired");
/* If serve-expired is enabled, we still use an expired message
* setting the TTL to 0. */
- if(qstate->env->cfg->serve_expired)
- adjust = -1;
- else
+ if(!qstate->env->cfg->serve_expired ||
+ (FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
+ != LDNS_RCODE_NOERROR &&
+ FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
+ != LDNS_RCODE_NXDOMAIN &&
+ FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
+ != LDNS_RCODE_YXDOMAIN))
return 0; /* message expired */
+ else
+ adjust = -1;
}
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
adjust_msg_ttl(qstate->return_msg, adjust);
if(worker->env.cfg->serve_expired_ttl &&
rep->serve_expired_ttl < timenow)
return 0;
+ /* Ignore expired failure answers */
+ if(FLAGS_GET_RCODE(rep->flags) !=
+ LDNS_RCODE_NOERROR &&
+ FLAGS_GET_RCODE(rep->flags) !=
+ LDNS_RCODE_NXDOMAIN &&
+ FLAGS_GET_RCODE(rep->flags) !=
+ LDNS_RCODE_YXDOMAIN)
+ return 0;
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
return 0;
*is_expired_answer = 1;
goto bail_out;
}
} else {
- /* We don't check the global ede as this is a warning, not
- * an error */
if (*is_expired_answer == 1 &&
worker->env.cfg->ede_serve_expired && worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
+22 November 2022: George
+ - Ignore expired error responses.
+
11 November 2022: Wouter
- Fix #779: [doc] Missing documention in ub_resolve_event() for
callback parameter was_ratelimited.
r->serve_expired_ttl < now) {
return NULL;
}
+ /* Ignore expired failure answers */
+ if(FLAGS_GET_RCODE(r->flags) !=
+ LDNS_RCODE_NOERROR &&
+ FLAGS_GET_RCODE(r->flags) !=
+ LDNS_RCODE_NXDOMAIN &&
+ FLAGS_GET_RCODE(r->flags) !=
+ LDNS_RCODE_YXDOMAIN)
+ return 0;
} else {
return NULL;
}
; config options go here.
server:
serve-expired: yes
+ prefetch: yes
forward-zone: name: "." forward-addr: 216.0.0.1
CONFIG_END
ENTRY_END
; enough to pass by the TTL of the servfail answer in cache
-STEP 50 TIME_PASSES ELAPSE 40
+STEP 50 TIME_PASSES ELAPSE 5
; this query triggers a prefetch
STEP 210 QUERY
--- /dev/null
+; config options
+server:
+ module-config: "validator iterator"
+ qname-minimisation: "no"
+ minimal-responses: no
+ serve-expired: yes
+ serve-expired-reply-ttl: 123
+ log-servfail: yes
+ ede: yes
+ ede-serve-expired: yes
+
+
+stub-zone:
+ name: "example.com"
+ stub-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Test serve-expired with client-timeout and a SERVFAIL upstream reply
+; Scenario overview:
+; - query for example.com. IN A
+; - answer from upstream is SERVFAIL; will be cached for NORR_TTL(5)
+; - check that the client gets the SERVFAIL; also cached
+; - query again right after the TTL expired
+; - cached SERVFAIL should be ignored and upstream queried
+; - check that we get the correct answer
+
+; ns.example.com.
+RANGE_BEGIN 0 20
+ ADDRESS 1.2.3.4
+ ; response to A query
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR AA SERVFAIL
+ SECTION QUESTION
+ example.com. IN A
+ ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 30 100
+ ADDRESS 1.2.3.4
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ example.com. 10 IN NS
+ SECTION ANSWER
+ example.com. 10 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. 10 IN A 1.2.3.4
+ ENTRY_END
+
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ example.com. IN A
+ SECTION ANSWER
+ example.com. 10 IN A 5.6.7.8
+ SECTION AUTHORITY
+ example.com. 10 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. 10 IN A 1.2.3.4
+ ENTRY_END
+RANGE_END
+
+; Query with RD flag
+STEP 0 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ example.com. IN A
+ENTRY_END
+
+; Check that we get the SERVFAIL (will be cached)
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all
+ REPLY QR RD RA SERVFAIL
+ SECTION QUESTION
+ example.com. IN A
+ENTRY_END
+
+; Query again
+STEP 20 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ example.com. IN A
+ENTRY_END
+
+; Check that we get the cached SERVFAIL
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all
+ REPLY QR RD RA SERVFAIL
+ SECTION QUESTION
+ example.com. IN A
+ENTRY_END
+
+; Wait for the SERVFAIL to expire
+STEP 31 TIME_PASSES ELAPSE 6
+
+; Query again
+STEP 40 QUERY
+ENTRY_BEGIN
+ REPLY RD
+ SECTION QUESTION
+ example.com. IN A
+ENTRY_END
+
+; Check that we got the correct answer
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+ MATCH all ttl
+ REPLY QR RD RA NOERROR
+ SECTION QUESTION
+ example.com. IN A
+ SECTION ANSWER
+ example.com. 10 IN A 5.6.7.8
+ SECTION AUTHORITY
+ example.com. 10 IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. 10 IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
qname-minimisation: "no"
minimal-responses: no
serve-expired: yes
- serve-expired-client-timeout: 1800
+ serve-expired-client-timeout: 1
serve-expired-reply-ttl: 123
log-servfail: yes
ede: yes
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
- example.com. IN NS
+ example.com. 10 IN NS
SECTION ANSWER
- example.com. IN NS ns.example.com.
+ example.com. 10 IN NS ns.example.com.
SECTION ADDITIONAL
- ns.example.com. IN A 1.2.3.4
+ ns.example.com. 10 IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
SECTION ANSWER
example.com. 10 IN A 5.6.7.8
SECTION AUTHORITY
- example.com. IN NS ns.example.com.
+ example.com. 10 IN NS ns.example.com.
SECTION ADDITIONAL
- ns.example.com. IN A 1.2.3.4
+ ns.example.com. 10 IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
-RANGE_BEGIN 30 100
+RANGE_BEGIN 30 70
ADDRESS 1.2.3.4
; response to A query
ENTRY_BEGIN
SECTION ANSWER
example.com. 10 IN A 5.6.7.8
SECTION AUTHORITY
- example.com. IN NS ns.example.com.
+ example.com. 10 IN NS ns.example.com.
SECTION ADDITIONAL
- ns.example.com. IN A 1.2.3.4
+ ns.example.com. 10 IN A 1.2.3.4
ENTRY_END
; Wait for the TTL to expire
-STEP 11 TIME_PASSES ELAPSE 3601
+STEP 11 TIME_PASSES ELAPSE 11
; Query again
STEP 30 QUERY
--- /dev/null
+; Check if an expired SERVFAIL answer stored in the global cache does not block
+; ECS queries to reach the ECS cache.
+
+server:
+ trust-anchor-signaling: no
+ target-fetch-policy: "0 0 0 0 0"
+ send-client-subnet: 1.2.3.4
+ max-client-subnet-ipv4: 21
+ module-config: "subnetcache iterator"
+ verbosity: 3
+ access-control: 127.0.0.1 allow_snoop
+ qname-minimisation: no
+ minimal-responses: no
+ serve-expired: yes
+ prefetch: yes
+
+stub-zone:
+ name: "example.com."
+ stub-addr: 1.2.3.4
+CONFIG_END
+
+SCENARIO_BEGIN Test that expired SERVFAIL in global cache does not block clients to reach the ECS cache
+
+; ns.example.com.
+RANGE_BEGIN 0 10
+ ADDRESS 1.2.3.4
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ example.com. IN NS
+ SECTION ANSWER
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 1.2.3.4
+ ENTRY_END
+
+ ; response to query of interest
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR SERVFAIL
+ SECTION QUESTION
+ www.example.com. IN A
+ ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 11 100
+ ADDRESS 1.2.3.4
+ ENTRY_BEGIN
+ MATCH opcode qtype qname
+ ADJUST copy_id
+ REPLY QR NOERROR
+ SECTION QUESTION
+ example.com. IN NS
+ SECTION ANSWER
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ ns.example.com. IN A 1.2.3.4
+ ENTRY_END
+
+ ; response to query of interest
+ ENTRY_BEGIN
+ MATCH opcode qtype qname ednsdata
+ ADJUST copy_id copy_ednsdata_assume_clientsubnet
+ REPLY QR NOERROR
+ SECTION QUESTION
+ www.example.com. IN A
+ SECTION ANSWER
+ www.example.com. 10 IN A 10.20.30.40
+ SECTION AUTHORITY
+ example.com. IN NS ns.example.com.
+ SECTION ADDITIONAL
+ HEX_EDNSDATA_BEGIN
+ ; client is 127.0.0.1
+ 00 08 ; OPC
+ 00 05 ; option length
+ 00 01 ; Family
+ 08 00 ; source mask, scopemask
+ 7f ; address
+ HEX_EDNSDATA_END
+ ns.example.com. IN A 1.2.3.4
+ ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; This answer should be in the global cache
+STEP 2 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Bring the cached SERVFAIL to prefetch time
+STEP 10 TIME_PASSES ELAPSE 5
+
+STEP 11 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+SECTION ADDITIONAL
+HEX_EDNSDATA_BEGIN
+ 00 08 00 05 ; OPC, optlen
+ 00 01 08 00 ; ip4, source 8, scope 0
+ 7f ; 127.0.0.0/8
+HEX_EDNSDATA_END
+ENTRY_END
+
+; This answer was cached but a prefetch was triggerred
+STEP 12 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH opcode qtype qname
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; Wait for the SERVFAIL to expire
+STEP 13 TIME_PASSES ELAPSE 2
+
+; Query again to verify that the record was prefetched and stored in the ECS
+; cache (because the server replied with ECS this time)
+STEP 14 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+SECTION ADDITIONAL
+HEX_EDNSDATA_BEGIN
+ 00 08 00 05 ; OPC, optlen
+ 00 01 08 00 ; ip4, source 8, scope 0
+ 7f ; 127.0.0.0/8
+HEX_EDNSDATA_END
+ENTRY_END
+
+; This record came from the ECS cache
+STEP 15 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all ttl
+REPLY QR RD RA DO NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. 8 IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. 3598 IN NS ns.example.com.
+SECTION ADDITIONAL
+HEX_EDNSDATA_BEGIN
+ 00 08 00 05 ; OPC, optlen
+ 00 01 08 08 ; ip4, source 8, scope 0
+ 7f ; 127.0.0.0/8
+HEX_EDNSDATA_END
+ns.example.com. 3598 IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END