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);