summaryrefslogtreecommitdiffstats
path: root/src/resolve/resolved-dns-scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/resolve/resolved-dns-scope.c')
-rw-r--r--src/resolve/resolved-dns-scope.c34
1 files changed, 19 insertions, 15 deletions
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c
index 4085b01..4780bc2 100644
--- a/src/resolve/resolved-dns-scope.c
+++ b/src/resolve/resolved-dns-scope.c
@@ -424,7 +424,15 @@ static int dns_scope_socket(
return r;
}
- if (ifindex != 0) {
+ bool addr_is_nonlocal = s->link &&
+ !manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
+ in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0;
+
+ if (addr_is_nonlocal && ifindex != 0) {
+ /* As a special exception we don't use UNICAST_IF if we notice that the specified IP address
+ * is on the local host. Otherwise, destination addresses on the local host result in
+ * EHOSTUNREACH, since Linux won't send the packets out of the specified interface, but
+ * delivers them directly to the local socket. */
r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
if (r < 0)
return r;
@@ -463,19 +471,13 @@ static int dns_scope_socket(
else {
bool bound = false;
- /* Let's temporarily bind the socket to the specified ifindex. The kernel currently takes
- * only the SO_BINDTODEVICE/SO_BINDTOINDEX ifindex into account when making routing decisions
+ /* Let's temporarily bind the socket to the specified ifindex. Older kernels only take
+ * the SO_BINDTODEVICE/SO_BINDTOINDEX ifindex into account when making routing decisions
* in connect() — and not IP_UNICAST_IF. We don't really want any of the other semantics of
* SO_BINDTODEVICE/SO_BINDTOINDEX, hence we immediately unbind the socket after the fact
* again.
- *
- * As a special exception we don't do this if we notice that the specified IP address is on
- * the local host. SO_BINDTODEVICE in combination with destination addresses on the local
- * host result in EHOSTUNREACH, since Linux won't send the packets out of the specified
- * interface, but delivers them directly to the local socket. */
- if (s->link &&
- !manager_find_link_address(s->manager, sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) &&
- in_addr_is_localhost(sa.sa.sa_family, sockaddr_in_addr(&sa.sa)) == 0) {
+ */
+ if (addr_is_nonlocal) {
r = socket_bind_to_ifindex(fd, ifindex);
if (r < 0)
return r;
@@ -594,6 +596,7 @@ DnsScopeMatch dns_scope_good_domain(
/* This returns the following return values:
*
* DNS_SCOPE_NO → This scope is not suitable for lookups of this domain, at all
+ * DNS_SCOPE_LAST_RESORT→ This scope is not suitable, unless we have no alternative
* 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
*
@@ -739,7 +742,7 @@ DnsScopeMatch dns_scope_good_domain(
if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
(s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0))
- return DNS_SCOPE_MAYBE;
+ return DNS_SCOPE_LAST_RESORT;
if ((dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */
dns_name_equal(domain, "local") == 0 && /* but not the single-label "local" name itself */
@@ -762,7 +765,7 @@ DnsScopeMatch dns_scope_good_domain(
if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) ||
(s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0))
- return DNS_SCOPE_MAYBE;
+ return DNS_SCOPE_LAST_RESORT;
if ((dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */
!is_gateway_hostname(domain) && /* don't resolve "_gateway" with LLMNR, let local synthesizing logic handle that */
@@ -1441,9 +1444,10 @@ int dns_scope_announce(DnsScope *scope, bool goodbye) {
continue;
}
- /* Collect service types for _services._dns-sd._udp.local RRs in a set */
+ /* Collect service types for _services._dns-sd._udp.local RRs in a set. Only two-label names
+ * (not selective names) are considered according to RFC6763 § 9. */
if (!scope->announced &&
- dns_resource_key_is_dnssd_ptr(z->rr->key)) {
+ dns_resource_key_is_dnssd_two_label_ptr(z->rr->key)) {
if (!set_contains(types, dns_resource_key_name(z->rr->key))) {
r = set_ensure_put(&types, &dns_name_hash_ops, dns_resource_key_name(z->rr->key));
if (r < 0)