diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h index 0ca650f48f..383615c288 100644 --- a/src/basic/errno-util.h +++ b/src/basic/errno-util.h @@ -50,7 +50,10 @@ static inline int errno_or_else(int fallback) { /* Hint #1: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5. * * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the - * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ + * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources. + * + * Hint #3: When asynchronous connect() on TCP fails because the host never acknowledges a single packet, + * kernel tells us that with ETIMEDOUT, see tcp(7). */ static inline bool ERRNO_IS_DISCONNECT(int r) { return IN_SET(abs(r), ECONNABORTED, @@ -66,7 +69,8 @@ static inline bool ERRNO_IS_DISCONNECT(int r) { ENOTCONN, EPIPE, EPROTO, - ESHUTDOWN); + ESHUTDOWN, + ETIMEDOUT); } /* Transient errors we might get on accept() that we should ignore. As per error handling comment in diff --git a/src/resolve/resolved-def.h b/src/resolve/resolved-def.h index 63c24a023f..1ce9feae7b 100644 --- a/src/resolve/resolved-def.h +++ b/src/resolve/resolved-def.h @@ -5,20 +5,30 @@ #include "time-util.h" -#define SD_RESOLVED_DNS (UINT64_C(1) << 0) -#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1) -#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2) -#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3) -#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4) -#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5) -#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6) -#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7) -#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8) -#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9) +/* Input + Output: The various protocols we can use */ +#define SD_RESOLVED_DNS (UINT64_C(1) << 0) +#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1) +#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2) +#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3) +#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4) -#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6) -#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6) +/* Input: Don't follow CNAMEs/DNAMEs */ +#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5) -#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS) +/* Input: When doing service (SRV) resolving, don't resolve associated mDNS-style TXT records */ +#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6) + +/* Input: When doing service (SRV) resolving, don't resolve A/AAA RR for included hostname */ +#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7) + +/* Input: Don't apply search domain logic to request */ +#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8) + +/* Output: Result is authenticated */ +#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9) + +#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6) +#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6) +#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS) #define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index 823c138b34..8253a4c9d2 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -321,6 +321,11 @@ int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) { assert(ret); + if (a == b) { + *ret = dns_answer_ref(a); + return 0; + } + if (dns_answer_size(a) <= 0) { *ret = dns_answer_ref(b); return 0; @@ -709,7 +714,7 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f) { fputs(t, f); - if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER)) + if (ifindex != 0 || flags != 0) fputs("\t;", f); if (ifindex != 0) @@ -720,6 +725,10 @@ void dns_answer_dump(DnsAnswer *answer, FILE *f) { fputs(" cacheable", f); if (flags & DNS_ANSWER_SHARED_OWNER) fputs(" shared-owner", f); + if (flags & DNS_ANSWER_CACHE_FLUSH) + fputs(" cache-flush", f); + if (flags & DNS_ANSWER_GOODBYE) + fputs(" goodbye", f); fputc('\n', f); } diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 9bf52d62e5..7579f5e328 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -589,6 +589,7 @@ DnsScopeMatch dns_scope_good_domain( 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 nss-myhostname handle this */ + dns_name_equal(domain, "local") == 0 && /* don't resolve "local" with LLMNR, it's the top-level domain of mDNS after all, see above */ manager_is_own_hostname(s->manager, domain) <= 0)) /* never resolve the local hostname via LLMNR */ return DNS_SCOPE_YES_BASE + 1; /* Return +1, as we consider ourselves authoritative * for single-label names, i.e. one label. This is diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index bb333e22eb..e00359f6a5 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -919,7 +919,11 @@ static int write_loop(int fd, void *message, size_t length) { int manager_write(Manager *m, int fd, DnsPacket *p) { int r; - log_debug("Sending %s packet with id %" PRIu16 ".", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p)); + log_debug("Sending %s%s packet with id %" PRIu16 " of size %zu.", + DNS_PACKET_TC(p) ? "truncated (!) " : "", + DNS_PACKET_QR(p) ? "response" : "query", + DNS_PACKET_ID(p), + p->size); r = write_loop(fd, DNS_PACKET_DATA(p), p->size); if (r < 0) @@ -1055,7 +1059,12 @@ int manager_send( assert(port > 0); assert(p); - log_debug("Sending %s packet with id %" PRIu16 " on interface %i/%s.", DNS_PACKET_QR(p) ? "response" : "query", DNS_PACKET_ID(p), ifindex, af_to_name(family)); + log_debug("Sending %s%s packet with id %" PRIu16 " on interface %i/%s of size %zu.", + DNS_PACKET_TC(p) ? "truncated (!) " : "", + DNS_PACKET_QR(p) ? "response" : "query", + DNS_PACKET_ID(p), + ifindex, af_to_name(family), + p->size); if (family == AF_INET) return manager_ipv4_send(m, fd, ifindex, &destination->in, port, source ? &source->in : NULL, p); diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index ba8f18f82d..a26fe8393a 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -156,6 +156,8 @@ int manager_read_resolv_conf(Manager *m) { r = manager_parse_search_domains_and_warn(m, a); if (r < 0) log_warning_errno(r, "Failed to parse search domain string '%s', ignoring.", a); + + continue; } log_syntax(NULL, LOG_DEBUG, "/etc/resolv.conf", n, 0, "Ignoring resolv.conf line: %s", l);