diff --git a/man/systemd-resolved.service.xml b/man/systemd-resolved.service.xml
index 34f05bd8b0..f7be0793cf 100644
--- a/man/systemd-resolved.service.xml
+++ b/man/systemd-resolved.service.xml
@@ -217,13 +217,11 @@
If a query does not match any configured routing domain (either per-link or global), it
is sent to all DNS servers that are configured on links with the DefaultRoute=
- option set.
+ option set, as well as the globally configured DNS server.
- If no links are configured with DefaultRoute=, it is sent to the
- globally configured DNS server.
-
- If there is no link configured as DefaultRoute= and no global DNS
- server configured, one of the compiled-in fallback DNS servers is used.
+ If there are no DNS servers configured on any link also configured as
+ DefaultRoute= and no global DNS server configured, one of the compiled-in fallback
+ DNS servers is used.
Otherwise the unicast DNS query fails, as no suitable DNS servers can be determined.
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 3bb7c0aa21..4d4e952dac 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -779,7 +779,10 @@ DnsScopeMatch dns_scope_good_domain(
return DNS_SCOPE_NO;
/* Prefer suitable per-link scopes where possible */
- return s->link ? DNS_SCOPE_MAYBE : DNS_SCOPE_LAST_RESORT;
+ if (dns_server_is_fallback(dns_scope_get_dns_server(s)))
+ return DNS_SCOPE_LAST_RESORT;
+
+ return DNS_SCOPE_MAYBE;
}
case DNS_PROTOCOL_MDNS: {
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index 70894977eb..b48d8e1417 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -100,9 +100,7 @@ int dns_server_new(
/* A new DNS server that isn't fallback is added and the one
* we used so far was a fallback one? Then let's try to pick
* the new one */
- if (type != DNS_SERVER_FALLBACK &&
- m->current_dns_server &&
- m->current_dns_server->type == DNS_SERVER_FALLBACK)
+ if (type != DNS_SERVER_FALLBACK && dns_server_is_fallback(m->current_dns_server))
manager_set_dns_server(m, NULL);
if (ret)
@@ -909,7 +907,7 @@ DnsServer *manager_get_dns_server(Manager *m) {
* servers */
HASHMAP_FOREACH(l, m->links)
- if (l->dns_servers) {
+ if (l->dns_servers && l->default_route) {
found = true;
break;
}
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index 5e1d5698f6..7d7d294c82 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -182,4 +182,8 @@ void dns_server_unref_stream(DnsServer *s);
DnsScope *dns_server_scope(DnsServer *s);
+static inline bool dns_server_is_fallback(DnsServer *s) {
+ return s && s->type == DNS_SERVER_FALLBACK;
+}
+
int dns_server_dump_state_to_json(DnsServer *server, sd_json_variant **ret);
diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c
index f5a3b0e36b..5e9e5bf17a 100644
--- a/src/resolve/resolved-link-bus.c
+++ b/src/resolve/resolved-link-bus.c
@@ -463,8 +463,7 @@ int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, s
bus_client_log(message, "dns default route change");
if (l->default_route != b) {
- l->default_route = b;
-
+ link_set_default_route(l, b);
(void) link_save_user(l);
(void) manager_write_resolv_conf(l->manager);
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index bb43a73de4..928137b967 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -319,7 +319,7 @@ static int link_update_default_route(Link *l) {
if (r < 0)
goto clear;
- l->default_route = r > 0;
+ link_set_default_route(l, r > 0);
return 0;
clear:
@@ -766,6 +766,20 @@ void link_next_dns_server(Link *l, DnsServer *if_current) {
link_set_dns_server(l, l->dns_servers);
}
+void link_set_default_route(Link *l, bool b) {
+ assert(l);
+
+ if (l->default_route == b)
+ return;
+
+ l->default_route = b;
+
+ /* If we are currently using the fallback servers, changing a link to be default-route means
+ * we should reconsider whether or not the fallback servers are necessary. */
+ if (b && dns_server_is_fallback(l->manager->current_dns_server))
+ manager_set_dns_server(l->manager, NULL);
+}
+
DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) {
assert(l);
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index 0695a6ff83..482a4b4148 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -99,6 +99,7 @@ void link_allocate_scopes(Link *l);
DnsServer* link_set_dns_server(Link *l, DnsServer *s);
DnsServer* link_get_dns_server(Link *l);
void link_next_dns_server(Link *l, DnsServer *if_current);
+void link_set_default_route(Link *l, bool b);
DnssecMode link_get_dnssec_mode(Link *l);
bool link_dnssec_supported(Link *l);