resolved: never serve stale cache data on link-local scopes
Serving stale cache data on a retry is a resilience feature for unicast DNS: when the configured server does not respond, an expired answer beats no answer. The gate in dns_transaction_go() that switches the cache lookup into serve-stale mode from the second attempt on only checks StaleRetentionSec=, not the scope's protocol, so it applies to mDNS and LLMNR scopes as well. There it is wrong twice over: * With StaleRetentionSec= set, a query for a peer that has left the network misses the cache on the first attempt (the record's TTL has expired), gets no reply, and is then answered from the expired but retained record on the retry — for as long as the retention window lasts. On the link-local protocols a retry means that no peer answered, not that some server is unreachable, and RFC 6762 treats TTL expiry as a presence signal: a host whose records lapse is gone. * Independently of whether anything stale is cached, a cache hit made in serve-stale mode is reported with its TTL clamped to 30s (see dns_cache_lookup()) and counted in the served-stale statistics. mDNS transactions are retried at 1s, 2s, 4s, ... whenever nobody answers, so a record announced or learnt from another transaction in between is handed to the client with a 30s TTL instead of its real remaining TTL, and logged as a "Serve Stale response" although it never was stale. Hence only enter serve-stale mode on unicast DNS scopes. This is the lookup-side counterpart of the cache-side change that stops link-local records from being retained past their TTL at all.
This commit is contained in:
committed by
Yu Watanabe
parent
1aedc8fe5e
commit
f9185464bb
@@ -1812,9 +1812,16 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
|
||||
/* For the initial attempt or when no stale data is requested, disable serve stale
|
||||
* and answer the question from the cache (honors ttl property).
|
||||
* On the second attempt, if StaleRetentionSec is greater than zero,
|
||||
* try to answer the question using stale date (honors until property) */
|
||||
* try to answer the question using stale data (honors until property).
|
||||
*
|
||||
* Serving stale data is a fallback for unicast DNS, where a retry means the configured
|
||||
* server did not respond. The link-local protocols have no such server: a retry there
|
||||
* means no peer answered, and for mDNS RFC 6762 treats TTL expiry as a presence signal.
|
||||
* Hence never serve stale data on those scopes. */
|
||||
uint64_t query_flags = t->query_flags;
|
||||
if (t->n_attempts == 1 || t->scope->manager->stale_retention_usec == 0)
|
||||
if (t->n_attempts == 1 ||
|
||||
t->scope->protocol != DNS_PROTOCOL_DNS ||
|
||||
t->scope->manager->stale_retention_usec == 0)
|
||||
query_flags |= SD_RESOLVED_NO_STALE;
|
||||
|
||||
r = dns_cache_lookup(
|
||||
|
||||
Reference in New Issue
Block a user