resolved: rework dns_server_limited_domains(), replace by dns_scope_has_route_only_do...
authorLennart Poettering <lennart@poettering.net>
Tue, 4 Dec 2018 11:08:18 +0000 (12:08 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 21 Dec 2018 11:09:00 +0000 (12:09 +0100)
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
src/resolve/resolved-dns-scope.h
src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-resolv-conf.c

index c2e4d55..be45485 100644 (file)
@@ -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;
+}
index 546d01c..6f47a55 100644 (file)
@@ -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);
index 3e69741..b85eb75 100644 (file)
@@ -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",
index 6e73f32..3c4627b 100644 (file)
@@ -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);
index 5fcd59d..832251b 100644 (file)
@@ -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;
         }