From 4b30f2e135ee84041bb597edca7225858f4ef4fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Mar 2021 20:34:16 +0100 Subject: [PATCH 1/5] sysctl-util: use read_full_virtual_file() for reading sysctls Given these files are part of procfs, let's use the correct API calls for reading them. This changes one occasion of read_one_line_file() to read_full_virtual_file(), which superficially is a different thing, but shouldn't actually be a difference, since sysctls can't be longer than 4K anyway, and the piecemeal logic behind read_one_line_file() cannot work with the special semantics of procfs anyway. --- src/shared/sysctl-util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/sysctl-util.c b/src/shared/sysctl-util.c index a835a8bd0a..c96b5cd77f 100644 --- a/src/shared/sysctl-util.c +++ b/src/shared/sysctl-util.c @@ -96,14 +96,14 @@ int sysctl_write_ip_property(int af, const char *ifname, const char *property, c return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER); } -int sysctl_read(const char *property, char **content) { +int sysctl_read(const char *property, char **ret) { char *p; assert(property); - assert(content); + assert(ret); p = strjoina("/proc/sys/", property); - return read_full_file(p, content, NULL); + return read_full_virtual_file(p, ret, NULL); } int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) { @@ -118,7 +118,7 @@ int sysctl_read_ip_property(int af, const char *ifname, const char *property, ch ifname ? "/conf/" : "", strempty(ifname), property[0] == '/' ? "" : "/", property); - r = read_one_line_file(p, &value); + r = read_full_virtual_file(p, &value, NULL); if (r < 0) return r; From b0ffd2760c16bb3f188a8fedc459e9f99692efae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Mar 2021 20:39:58 +0100 Subject: [PATCH 2/5] =?UTF-8?q?basic:=20move=20shared/sysctl-util.[ch]=20?= =?UTF-8?q?=E2=86=92=20basic/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is self-contained ans allows us later to use the provided APIs from other code in src/basic/ --- src/basic/meson.build | 2 ++ src/{shared => basic}/sysctl-util.c | 0 src/{shared => basic}/sysctl-util.h | 0 src/shared/meson.build | 2 -- 4 files changed, 2 insertions(+), 2 deletions(-) rename src/{shared => basic}/sysctl-util.c (100%) rename src/{shared => basic}/sysctl-util.h (100%) diff --git a/src/basic/meson.build b/src/basic/meson.build index 282118bb1a..df4058a57b 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -237,6 +237,8 @@ basic_sources = files(''' strv.h strxcpyx.c strxcpyx.h + sysctl-util.c + sysctl-util.h syslog-util.c syslog-util.h terminal-util.c diff --git a/src/shared/sysctl-util.c b/src/basic/sysctl-util.c similarity index 100% rename from src/shared/sysctl-util.c rename to src/basic/sysctl-util.c diff --git a/src/shared/sysctl-util.h b/src/basic/sysctl-util.h similarity index 100% rename from src/shared/sysctl-util.h rename to src/basic/sysctl-util.h diff --git a/src/shared/meson.build b/src/shared/meson.build index 4b27a95cc2..e6d5ad8f72 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -242,8 +242,6 @@ shared_sources = files(''' specifier.h switch-root.c switch-root.h - sysctl-util.c - sysctl-util.h tmpfile-util-label.c tmpfile-util-label.h tomoyo-util.c From 571ec995fe035557d4166ae310f627bdf307714b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Mar 2021 18:46:31 +0100 Subject: [PATCH 3/5] socket-util: cache result of socket_ipv6_is_supported() And while we are at it, log about unexpected errors. --- src/basic/socket-util.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 8267988ad9..315a99c3fa 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -277,10 +277,23 @@ const char* socket_address_get_path(const SocketAddress *a) { } bool socket_ipv6_is_supported(void) { - if (access("/proc/net/if_inet6", F_OK) != 0) - return false; + static int cached = -1; - return true; + if (cached < 0) { + + if (access("/proc/net/if_inet6", F_OK) < 0) { + + if (errno != ENOENT) { + log_debug_errno(errno, "Unexpected error when checking whether /proc/net/if_inet6 exists: %m"); + return false; + } + + cached = false; + } else + cached = true; + } + + return cached; } bool socket_address_matches_fd(const SocketAddress *a, int fd) { From 83e03c4fc23dae0cbb3fd4e7c2f9ef533fc26160 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Mar 2021 20:37:24 +0100 Subject: [PATCH 4/5] socket-util: add helper for checking if IPv6 is enabled --- src/basic/socket-util.c | 26 ++++++++++++++++++++++++++ src/basic/socket-util.h | 1 + src/test/test-socket-util.c | 6 ++++++ 3 files changed, 33 insertions(+) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 315a99c3fa..4899c17589 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -31,6 +31,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" +#include "sysctl-util.h" #include "user-util.h" #include "utf8.h" @@ -296,6 +297,31 @@ bool socket_ipv6_is_supported(void) { return cached; } +bool socket_ipv6_is_enabled(void) { + _cleanup_free_ char *v; + int r; + + /* Much like socket_ipv6_is_supported(), but also checks that the sysctl that disables IPv6 on all + * interfaces isn't turned on */ + + if (!socket_ipv6_is_supported()) + return false; + + r = sysctl_read_ip_property(AF_INET6, "all", "disable_ipv6", &v); + if (r < 0) { + log_debug_errno(r, "Unexpected error reading 'net.ipv6.conf.all.disable_ipv6' sysctl: %m"); + return true; + } + + r = parse_boolean(v); + if (r < 0) { + log_debug_errno(r, "Failed to pare 'net.ipv6.conf.all.disable_ipv6' sysctl: %m"); + return true; + } + + return !r; +} + bool socket_address_matches_fd(const SocketAddress *a, int fd) { SocketAddress b; socklen_t solen; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 2c98283cd3..507a599d7c 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -101,6 +101,7 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) _pure_ const char* socket_address_get_path(const SocketAddress *a); bool socket_ipv6_is_supported(void); +bool socket_ipv6_is_enabled(void); int sockaddr_port(const struct sockaddr *_sa, unsigned *port); const union in_addr_union *sockaddr_in_addr(const struct sockaddr *sa); diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index 4ff7d714f8..584253c2fc 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -504,6 +504,11 @@ static void test_flush_accept(void) { assert_se(flush_accept(listen_seqpacket) >= 0); } +static void test_ipv6_enabled(void) { + log_info("IPv6 supported: %s", yes_no(socket_ipv6_is_supported())); + log_info("IPv6 enabled: %s", yes_no(socket_ipv6_is_enabled())); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -519,6 +524,7 @@ int main(int argc, char *argv[]) { test_send_nodata_nofd(); test_send_emptydata(); test_flush_accept(); + test_ipv6_enabled(); return 0; } From 747b596ff8276cfad977423c476ba6f00e29594a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 5 Mar 2021 18:47:10 +0100 Subject: [PATCH 5/5] resolved: never return ::1 when localhost or local hostname is resolved while IPv6 is off in the kernel Fixes: #18812 --- src/resolve/resolved-dns-synthesize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resolve/resolved-dns-synthesize.c b/src/resolve/resolved-dns-synthesize.c index 23c9ba14a9..d4a4be71b0 100644 --- a/src/resolve/resolved-dns-synthesize.c +++ b/src/resolve/resolved-dns-synthesize.c @@ -81,7 +81,7 @@ static int synthesize_localhost_rr(Manager *m, const DnsResourceKey *key, int if return r; } - if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY)) { + if (IN_SET(key->type, DNS_TYPE_AAAA, DNS_TYPE_ANY) && socket_ipv6_is_enabled()) { _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL; rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, dns_resource_key_name(key)); @@ -234,7 +234,7 @@ static int synthesize_system_hostname_rr(Manager *m, const DnsResourceKey *key, .address.in.s_addr = htobe32(0x7F000002), }; - if (IN_SET(af, AF_INET6, AF_UNSPEC)) + if (IN_SET(af, AF_INET6, AF_UNSPEC) && socket_ipv6_is_enabled()) buffer[n++] = (struct local_address) { .family = AF_INET6, .ifindex = dns_synthesize_ifindex(ifindex),