resolved: skip cache flush on server switch/re-probe when StaleRetentionSec is set

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.
This commit is contained in:
azureuser
2026-04-10 10:10:26 +02:00
committed by Lennart Poettering
parent d3a1710bc2
commit fb0ae7436d
+6 -1
View File
@@ -1036,7 +1036,8 @@ DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
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");
@@ -1155,6 +1156,10 @@ void dns_server_flush_cache(DnsServer *s) {
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);
}