Merge pull request #18896 from poettering/no-localhost-ipv6

if ipv6 is turned off, don't synthesize localhost as ::1 ever
This commit is contained in:
Yu Watanabe
2021-03-06 11:28:38 +09:00
committed by GitHub
8 changed files with 56 additions and 10 deletions
+2
View File
@@ -235,6 +235,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
+41 -2
View File
@@ -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"
@@ -277,10 +278,48 @@ const char* socket_address_get_path(const SocketAddress *a) {
}
bool socket_ipv6_is_supported(void) {
if (access("/proc/net/if_inet6", F_OK) != 0)
static int cached = -1;
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_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;
return true;
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) {
+1
View File
@@ -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);
+130
View File
@@ -0,0 +1,130 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "fd-util.h"
#include "fileio.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "string-util.h"
#include "sysctl-util.h"
char *sysctl_normalize(char *s) {
char *n;
n = strpbrk(s, "/.");
/* If the first separator is a slash, the path is
* assumed to be normalized and slashes remain slashes
* and dots remains dots. */
if (n && *n == '.')
/* Dots become slashes and slashes become dots. Fun. */
do {
if (*n == '.')
*n = '/';
else
*n = '.';
n = strpbrk(n + 1, "/.");
} while (n);
path_simplify(s, true);
/* Kill the leading slash, but keep the first character of the string in the same place. */
if (*s == '/' && *(s+1))
memmove(s, s+1, strlen(s));
return s;
}
int sysctl_write(const char *property, const char *value) {
char *p;
_cleanup_close_ int fd = -1;
assert(property);
assert(value);
log_debug("Setting '%s' to '%.*s'.", property, (int) strcspn(value, NEWLINE), value);
p = strjoina("/proc/sys/", property);
fd = open(p, O_WRONLY|O_CLOEXEC);
if (fd < 0)
return -errno;
if (!endswith(value, "\n"))
value = strjoina(value, "\n");
if (write(fd, value, strlen(value)) < 0)
return -errno;
return 0;
}
int sysctl_writef(const char *property, const char *format, ...) {
_cleanup_free_ char *v = NULL;
va_list ap;
int r;
va_start(ap, format);
r = vasprintf(&v, format, ap);
va_end(ap);
if (r < 0)
return -ENOMEM;
return sysctl_write(property, v);
}
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value) {
const char *p;
assert(IN_SET(af, AF_INET, AF_INET6));
assert(property);
assert(value);
p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
ifname ? "/conf/" : "", strempty(ifname),
property[0] == '/' ? "" : "/", property);
log_debug("Setting '%s' to '%s'", p, value);
return write_string_file(p, value, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
}
int sysctl_read(const char *property, char **ret) {
char *p;
assert(property);
assert(ret);
p = strjoina("/proc/sys/", property);
return read_full_virtual_file(p, ret, NULL);
}
int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret) {
_cleanup_free_ char *value = NULL;
const char *p;
int r;
assert(IN_SET(af, AF_INET, AF_INET6));
assert(property);
p = strjoina("/proc/sys/net/ipv", af == AF_INET ? "4" : "6",
ifname ? "/conf/" : "", strempty(ifname),
property[0] == '/' ? "" : "/", property);
r = read_full_virtual_file(p, &value, NULL);
if (r < 0)
return r;
truncate_nl(value);
if (ret)
*ret = TAKE_PTR(value);
return r;
}
+30
View File
@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "macro.h"
#include "stdio-util.h"
#include "string-util.h"
char *sysctl_normalize(char *s);
int sysctl_read(const char *property, char **value);
int sysctl_write(const char *property, const char *value);
int sysctl_writef(const char *property, const char *format, ...) _printf_(2, 3);
int sysctl_read_ip_property(int af, const char *ifname, const char *property, char **ret);
int sysctl_write_ip_property(int af, const char *ifname, const char *property, const char *value);
static inline int sysctl_write_ip_property_boolean(int af, const char *ifname, const char *property, bool value) {
return sysctl_write_ip_property(af, ifname, property, one_zero(value));
}
#define DEFINE_SYSCTL_WRITE_IP_PROPERTY(name, type, format) \
static inline int sysctl_write_ip_property_##name(int af, const char *ifname, const char *property, type value) { \
char buf[DECIMAL_STR_MAX(type)]; \
xsprintf(buf, format, value); \
return sysctl_write_ip_property(af, ifname, property, buf); \
}
DEFINE_SYSCTL_WRITE_IP_PROPERTY(int, int, "%i");
DEFINE_SYSCTL_WRITE_IP_PROPERTY(uint32, uint32_t, "%" PRIu32);