manager_set_dns_server() and dns_server_flush_cache() call dns_cache_flush()
unconditionally, wiping the entire cache even when StaleRetentionSec is
configured. This defeats serve-stale by discarding cached records that should
remain available during server switches and feature-level re-probes.
The original serve-stale commit (
5ed91481ab) added a stale_retention_usec
guard to link_set_dns_server(), and a later commit (
7928c0e0a1) added the
same guard to dns_delegate_set_dns_server(), but these two call sites in
resolved-dns-server.c were missed.
This is particularly visible with DNSOverTLS, where TLS handshake failures
trigger frequent feature-level downgrades and re-probes via
dns_server_flush_cache(), flushing the cache each time.
Add the same stale_retention_usec guard to both call sites so that cache
entries are allowed to expire naturally via dns_cache_prune() when
serve-stale is enabled.
Fixes: #40781
This commit was prepared with assistance from an AI coding agent (GitHub
Copilot). All changes have been reviewed for correctness and adherence to the
systemd coding style.
dns_server_unref(m->current_dns_server);
m->current_dns_server = dns_server_ref(s);
- if (m->unicast_scope)
+ /* Skip flushing the cache if server stale feature is enabled. */
+ if (m->unicast_scope && m->stale_retention_usec == 0)
dns_cache_flush(&m->unicast_scope->cache);
(void) manager_send_changed(m, "CurrentDNSServer");
if (!scope)
return;
+ /* Skip flushing the cache if server stale feature is enabled. */
+ if (s->manager->stale_retention_usec > 0)
+ return;
+
dns_cache_flush(&scope->cache);
}