From f76fa088994a74be5aae636e4695bc27a50f0cc2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 4 Dec 2018 12:08:18 +0100 Subject: [PATCH] resolved: rework dns_server_limited_domains(), replace by dns_scope_has_route_only_domains() The function dns_server_limited_domains() was very strange as it enumerate the domains associated with a DnsScope object to determine whether any "route-only" domains, but did so as a function associated with a DnsServer object. Let's clear this up, and replace it by a function associated with a DnsScope instead. This makes more sense philosphically and allows us to reduce the loops through which we need to jump to determine whether a scope is suitable for default routing a bit. --- src/resolve/resolved-dns-scope.c | 33 ++++++++++++++++++++++++++---- src/resolve/resolved-dns-scope.h | 3 ++- src/resolve/resolved-dns-server.c | 30 +++++++++------------------ src/resolve/resolved-dns-server.h | 4 ++-- src/resolve/resolved-resolv-conf.c | 15 +++++++------- 5 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index c2e4d55a322..be45485998b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -527,12 +527,10 @@ DnsScopeMatch dns_scope_good_domain( switch (s->protocol) { case DNS_PROTOCOL_DNS: { - DnsServer *dns_server; int n_best = -1; /* Never route things to scopes that lack DNS servers */ - dns_server = dns_scope_get_dns_server(s); - if (!dns_server) + if (!dns_scope_get_dns_server(s)) return DNS_SCOPE_NO; /* Always honour search domains for routing queries, except if this scope lacks DNS servers. Note that @@ -558,7 +556,7 @@ DnsScopeMatch dns_scope_good_domain( /* If the DNS server has route-only domains, don't send other requests to it. This would be a privacy * violation, will most probably fail anyway, and adds unnecessary load. */ - if (dns_server_limited_domains(dns_server)) + if (dns_scope_has_route_only_domains(s)) return DNS_SCOPE_NO; /* Exclude link-local IP ranges */ @@ -1393,3 +1391,30 @@ int dns_scope_remove_dnssd_services(DnsScope *scope) { return 0; } + +bool dns_scope_has_route_only_domains(DnsScope *scope) { + DnsSearchDomain *domain, *first; + bool route_only = false; + + /* Check if the scope has any route-only domains except for "~.", i. e. whether it should only be + * used for particular domains */ + + if (scope->protocol != DNS_PROTOCOL_DNS) + return false; + + if (scope->link) + first = scope->link->search_domains; + else + first = scope->manager->search_domains; + + LIST_FOREACH(domains, domain, first) { + /* "." means "any domain", thus the interface takes any kind of traffic. */ + if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain))) + return false; + + if (domain->route_only) + route_only = true; + } + + return route_only; +} diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 546d01c6561..6f47a5593f0 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -107,5 +107,6 @@ int dns_scope_ifindex(DnsScope *s); int dns_scope_announce(DnsScope *scope, bool goodbye); int dns_scope_add_dnssd_services(DnsScope *scope); - int dns_scope_remove_dnssd_services(DnsScope *scope); + +bool dns_scope_has_route_only_domains(DnsScope *scope); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 3e69741b880..b85eb75273c 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -580,26 +580,6 @@ void dns_server_warn_downgrade(DnsServer *server) { server->warned_downgrade = true; } -bool dns_server_limited_domains(DnsServer *server) { - DnsSearchDomain *domain; - bool domain_restricted = false; - - /* Check if the server has route-only domains without ~., i. e. whether - * it should only be used for particular domains */ - if (!server->link) - return false; - - LIST_FOREACH(domains, domain, server->link->search_domains) - if (domain->route_only) { - domain_restricted = true; - /* ~. means "any domain", thus it is a global server */ - if (dns_name_is_root(DNS_SEARCH_DOMAIN_NAME(domain))) - return false; - } - - return domain_restricted; -} - static void dns_server_hash_func(const DnsServer *s, struct siphash *state) { assert(s); @@ -906,6 +886,16 @@ void dns_server_unref_stream(DnsServer *s) { dns_stream_unref(ref); } +DnsScope *dns_server_scope(DnsServer *s) { + assert(s); + assert((s->type == DNS_SERVER_LINK) == !!s->link); + + if (s->link) + return s->link->unicast_scope; + + return s->manager->unicast_scope; +} + static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = { [DNS_SERVER_SYSTEM] = "system", [DNS_SERVER_FALLBACK] = "fallback", diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 6e73f32df45..3c4627bca5a 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -122,8 +122,6 @@ bool dns_server_dnssec_supported(DnsServer *server); void dns_server_warn_downgrade(DnsServer *server); -bool dns_server_limited_domains(DnsServer *server); - DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex); void dns_server_unlink_all(DnsServer *first); @@ -153,3 +151,5 @@ void dns_server_reset_features_all(DnsServer *s); void dns_server_dump(DnsServer *s, FILE *f); void dns_server_unref_stream(DnsServer *s); + +DnsScope *dns_server_scope(DnsServer *s); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 5fcd59d8767..832251b6109 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -217,6 +217,8 @@ clear: } static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { + DnsScope *scope; + assert(s); assert(f); assert(count); @@ -226,13 +228,12 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { return; } - /* Check if the DNS server is limited to particular domains; - * resolv.conf does not have a syntax to express that, so it must not - * appear as a global name server to avoid routing unrelated domains to - * it (which is a privacy violation, will most probably fail anyway, - * and adds unnecessary load) */ - if (dns_server_limited_domains(s)) { - log_debug("DNS server %s has route-only domains, not using as global name server", dns_server_string(s)); + /* Check if the scope this DNS server belongs to is limited to particular domains; resolv.conf does not have a + * syntax to express that, so it must not appear as a global name server to avoid routing unrelated domains to + * it (which is a privacy violation, will most probably fail anyway, and adds unnecessary load) */ + scope = dns_server_scope(s); + if (scope && dns_scope_has_route_only_domains(scope)) { + log_debug("Scope of DNS server %s has only route-only domains, not using as global name server", dns_server_string(s)); return; } -- 2.39.2