diff options
author | Lennart Poettering <lennart@poettering.net> | 2018-12-03 16:25:00 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2018-12-21 11:04:11 +0100 |
commit | a97a3b256cd6c56ab1d817440d3b8acb3272ee17 (patch) | |
tree | 94da4e0aab9a052c5d9c0765359ae07ae2e04b72 | |
parent | resolved: add comment, explaining when Scope variables are copied from Link (diff) | |
download | systemd-a97a3b256cd6c56ab1d817440d3b8acb3272ee17.tar.gz systemd-a97a3b256cd6c56ab1d817440d3b8acb3272ee17.tar.bz2 systemd-a97a3b256cd6c56ab1d817440d3b8acb3272ee17.zip |
resolved: rework how we determine which scope to send a query to
Fixes: #10830 #9825 #9472
-rw-r--r-- | src/resolve/resolved-dns-query.c | 27 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 37 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.h | 3 |
3 files changed, 47 insertions, 20 deletions
diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c index 746ff1b8b..7a4f97754 100644 --- a/src/resolve/resolved-dns-query.c +++ b/src/resolve/resolved-dns-query.c @@ -682,22 +682,15 @@ int dns_query_go(DnsQuery *q) { continue; match = dns_scope_good_domain(s, q->ifindex, q->flags, name); - if (match < 0) - return match; - - if (match == DNS_SCOPE_NO) + if (match < 0) { + log_debug("Couldn't check if '%s' matches against scope, ignoring.", name); continue; + } - found = match; - - if (match == DNS_SCOPE_YES) { + if (match > found) { /* Does this match better? If so, remember how well it matched, and the first one + * that matches this well */ + found = match; first = s; - break; - } else { - assert(match == DNS_SCOPE_MAYBE); - - if (!first) - first = s; } } @@ -725,10 +718,12 @@ int dns_query_go(DnsQuery *q) { continue; match = dns_scope_good_domain(s, q->ifindex, q->flags, name); - if (match < 0) - goto fail; + if (match < 0) { + log_debug("Couldn't check if '%s' matches agains scope, ignoring.", name); + continue; + } - if (match != found) + if (match < found) continue; r = dns_query_add_candidate(q, s); diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 8ea46054a..59f76b0ae 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -459,9 +459,25 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address); } -DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { +DnsScopeMatch dns_scope_good_domain( + DnsScope *s, + int ifindex, + uint64_t flags, + const char *domain) { + DnsSearchDomain *d; + /* This returns the following return values: + * + * DNS_SCOPE_NO → This scope is not suitable for lookups of this domain, at all + * DNS_SCOPE_MAYBE → This scope is suitable, but only if nothing else wants it + * DNS_SCOPE_YES_BASE+n → This scope is suitable, and 'n' suffix labels match + * + * (The idea is that the caller will only use the scopes with the longest 'n' returned. If no scopes return + * DNS_SCOPE_YES_BASE+n, then it should use those which returned DNS_SCOPE_MAYBE. It should never use those + * which returned DNS_SCOPE_NO.) + */ + assert(s); assert(domain); @@ -497,6 +513,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co 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); @@ -507,8 +524,22 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co * we return DNS_SCOPE_YES here, rather than just DNS_SCOPE_MAYBE, which means other wildcard scopes * won't be considered anymore. */ LIST_FOREACH(domains, d, dns_scope_get_search_domains(s)) - if (dns_name_endswith(domain, d->name) > 0) - return DNS_SCOPE_YES; + if (dns_name_endswith(domain, d->name) > 0) { + int c; + + c = dns_name_count_labels(d->name); + if (c < 0) + continue; + + if (c > n_best) + n_best = c; + } + + /* Let's return the number of labels in the best matching result */ + if (n_best >= 0) { + assert(n_best <= DNS_SCOPE_YES_END - DNS_SCOPE_YES_BASE); + return DNS_SCOPE_YES_BASE + n_best; + } /* 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. */ diff --git a/src/resolve/resolved-dns-scope.h b/src/resolve/resolved-dns-scope.h index 7b7236751..546d01c65 100644 --- a/src/resolve/resolved-dns-scope.h +++ b/src/resolve/resolved-dns-scope.h @@ -18,7 +18,8 @@ typedef struct DnsScope DnsScope; typedef enum DnsScopeMatch { DNS_SCOPE_NO, DNS_SCOPE_MAYBE, - DNS_SCOPE_YES, + DNS_SCOPE_YES_BASE, /* Add the number of matching labels to this */ + DNS_SCOPE_YES_END = DNS_SCOPE_YES_BASE + DNS_N_LABELS_MAX, _DNS_SCOPE_MATCH_MAX, _DNS_SCOPE_MATCH_INVALID = -1 } DnsScopeMatch; |