From 8d50c14252031c5f5d0d222f6d21acdc396035b0 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 6 Nov 2020 14:30:25 +0100 Subject: [PATCH 1/7] errno: ETIMEDOUT is also a connection error --- src/basic/errno-util.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 From 02c205359b7dfcb4501cab564218f21d0a0523f8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Nov 2020 15:49:15 +0100 Subject: [PATCH 2/7] resolved: suppress misleading debug message about ignored resolv.conf line --- src/resolve/resolved-resolv-conf.c | 2 ++ 1 file changed, 2 insertions(+) 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); From 032b3982240f164f9b839bda3ea8e96ce7e1d925 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Nov 2020 20:42:02 +0100 Subject: [PATCH 3/7] resolved: add minor optimization path to dns_answer_merge() --- src/resolve/resolved-dns-answer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index 823c138b34..1939ec163e 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; From 5cdcac6cf6879826407433f2cfcf2b763f89d74a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 4 Nov 2020 21:01:49 +0100 Subject: [PATCH 4/7] resolved: show all answer flags when dumping answer --- src/resolve/resolved-dns-answer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-answer.c b/src/resolve/resolved-dns-answer.c index 1939ec163e..8253a4c9d2 100644 --- a/src/resolve/resolved-dns-answer.c +++ b/src/resolve/resolved-dns-answer.c @@ -714,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) @@ -725,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); } From dc194dce8010e2ded0e1eb0ee1d3a3d9ccc11b10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Nov 2020 09:45:12 +0100 Subject: [PATCH 5/7] resolved: add comments for various query flags --- src/resolve/resolved-def.h | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) 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) From 088648d081e9bc27f53c6471b91109569b29322f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 5 Nov 2020 14:16:03 +0100 Subject: [PATCH 6/7] resolved: don't resolve "local." via LLMNR It's the mDNS top-level domain, hence don't consider it for LLMNR, ever. Fixes: #16233 --- src/resolve/resolved-dns-scope.c | 1 + 1 file changed, 1 insertion(+) 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 From 76f772298e3473f00eff7cb6dc294926a7d8cc4f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 6 Nov 2020 11:46:39 +0100 Subject: [PATCH 7/7] resolved: slightly extend debug log output about outgoing messages --- src/resolve/resolved-manager.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) 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);