1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-12 13:18:14 +03:00

Merge pull request #11748 from yuwata/fix-11711

network: handle disable_ipv6 sysctl property
This commit is contained in:
Lennart Poettering 2019-02-21 11:28:35 +01:00 committed by GitHub
commit 09ba1fcc57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 161 additions and 59 deletions

View File

@ -10,8 +10,9 @@
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-network.h"
#include "string-util.h"
#include "socket-util.h"
#include "string-util.h"
#include "sysctl-util.h"
static bool ipv6_proxy_ndp_is_needed(Link *link) {
assert(link);
@ -32,8 +33,8 @@ static bool ipv6_proxy_ndp_is_needed(Link *link) {
}
static int ipv6_proxy_ndp_set(Link *link) {
const char *p = NULL;
int r, v;
bool v;
int r;
assert(link);
@ -41,9 +42,8 @@ static int ipv6_proxy_ndp_set(Link *link) {
return 0;
v = ipv6_proxy_ndp_is_needed(link);
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/proxy_ndp");
r = write_string_file(p, one_zero(v), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure proxy NDP for interface: %m");

View File

@ -29,6 +29,7 @@
#include "stdio-util.h"
#include "string-table.h"
#include "strv.h"
#include "sysctl-util.h"
#include "tmpfile-util.h"
#include "util.h"
#include "virt.h"
@ -73,6 +74,9 @@ static bool link_dhcp6_enabled(Link *link) {
if (link->network->bond)
return false;
if (manager_sysctl_ipv6_enabled(link->manager) == 0)
return false;
return link->network->dhcp & ADDRESS_FAMILY_IPV6;
}
@ -142,6 +146,9 @@ static bool link_ipv6ll_enabled(Link *link) {
if (link->network->bond)
return false;
if (manager_sysctl_ipv6_enabled(link->manager) == 0)
return false;
return link->network->link_local & ADDRESS_FAMILY_IPV6;
}
@ -154,6 +161,9 @@ static bool link_ipv6_enabled(Link *link) {
if (link->network->bridge || link->network->bond)
return false;
if (manager_sysctl_ipv6_enabled(link->manager) == 0)
return false;
/* DHCPv6 client will not be started if no IPv6 link-local address is configured. */
return link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
}
@ -233,6 +243,9 @@ static bool link_ipv6_forward_enabled(Link *link) {
if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
return false;
if (manager_sysctl_ipv6_enabled(link->manager) == 0)
return false;
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
}
@ -297,7 +310,6 @@ static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
}
static int link_enable_ipv6(Link *link) {
const char *p = NULL;
bool disabled;
int r;
@ -306,9 +318,7 @@ static int link_enable_ipv6(Link *link) {
disabled = !link_ipv6_enabled(link);
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6");
r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", disabled);
if (r < 0)
log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m",
enable_disable(!disabled), link->ifname);
@ -1330,15 +1340,12 @@ static int link_set_bridge_vlan(Link *link) {
}
static int link_set_proxy_arp(Link *link) {
const char *p = NULL;
int r;
if (!link_proxy_arp_enabled(link))
return 0;
p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp");
r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m");
@ -1912,20 +1919,12 @@ static int link_configure_addrgen_mode(Link *link) {
if (!link_ipv6ll_enabled(link))
ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
else {
const char *p = NULL;
_cleanup_free_ char *stable_secret = NULL;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/stable_secret");
else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0)
/* The file may not exist. And event if it exists, when stable_secret is unset,
* then reading the file fails and EIO is returned. */
r = read_one_line_file(p, &stable_secret);
if (r < 0)
ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
else
ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
}
* reading the file fails with EIO. */
ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
else
ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
if (r < 0)
@ -2653,7 +2652,7 @@ static int link_set_ipv4_forward(Link *link) {
* primarily to keep IPv4 and IPv6 packet forwarding behaviour
* somewhat in sync (see below). */
r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1");
if (r < 0)
log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m");
@ -2675,7 +2674,7 @@ static int link_set_ipv6_forward(Link *link) {
* same behaviour there and also propagate the setting from
* one to all, to keep things simple (see above). */
r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1");
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");
@ -2683,19 +2682,14 @@ static int link_set_ipv6_forward(Link *link) {
}
static int link_set_ipv6_privacy_extensions(Link *link) {
char buf[DECIMAL_STR_MAX(unsigned) + 1];
IPv6PrivacyExtensions s;
const char *p = NULL;
int r;
s = link_ipv6_privacy_extensions(link);
if (s < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr");
xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions);
r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m");
@ -2703,7 +2697,6 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
}
static int link_set_ipv6_accept_ra(Link *link) {
const char *p = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
@ -2716,10 +2709,7 @@ static int link_set_ipv6_accept_ra(Link *link) {
if (!link->network)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
/* We handle router advertisements ourselves, tell the kernel to GTFO */
r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0");
if (r < 0)
log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
@ -2727,8 +2717,6 @@ static int link_set_ipv6_accept_ra(Link *link) {
}
static int link_set_ipv6_dad_transmits(Link *link) {
char buf[DECIMAL_STR_MAX(int) + 1];
const char *p = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
@ -2744,10 +2732,7 @@ static int link_set_ipv6_dad_transmits(Link *link) {
if (link->network->ipv6_dad_transmits < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits");
xsprintf(buf, "%i", link->network->ipv6_dad_transmits);
r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m");
@ -2755,8 +2740,6 @@ static int link_set_ipv6_dad_transmits(Link *link) {
}
static int link_set_ipv6_hop_limit(Link *link) {
char buf[DECIMAL_STR_MAX(int) + 1];
const char *p = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
@ -2772,10 +2755,7 @@ static int link_set_ipv6_hop_limit(Link *link) {
if (link->network->ipv6_hop_limit < 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit");
xsprintf(buf, "%i", link->network->ipv6_hop_limit);
r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE | WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m");
@ -2783,8 +2763,6 @@ static int link_set_ipv6_hop_limit(Link *link) {
}
static int link_set_ipv6_mtu(Link *link) {
char buf[DECIMAL_STR_MAX(unsigned) + 1];
const char *p = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
@ -2797,11 +2775,7 @@ static int link_set_ipv6_mtu(Link *link) {
if (link->network->ipv6_mtu == 0)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/mtu");
xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
r = write_string_file(p, buf, WRITE_STRING_FILE_DISABLE_BUFFER);
r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m");

View File

@ -24,6 +24,7 @@
#include "path-util.h"
#include "set.h"
#include "strv.h"
#include "sysctl-util.h"
#include "tmpfile-util.h"
#include "virt.h"
@ -1379,6 +1380,8 @@ int manager_new(Manager **ret) {
if (!m->state_file)
return -ENOMEM;
m->sysctl_ipv6_enabled = -1;
r = sd_event_default(&m->event);
if (r < 0)
return r;
@ -1877,3 +1880,18 @@ int manager_request_product_uuid(Manager *m, Link *link) {
return 0;
}
int manager_sysctl_ipv6_enabled(Manager *manager) {
_cleanup_free_ char *value = NULL;
int r;
if (manager->sysctl_ipv6_enabled >= 0)
return manager->sysctl_ipv6_enabled;
r = sysctl_read_ip_property(AF_INET6, "all", "disable_ipv6", &value);
if (r < 0)
return log_warning_errno(r, "Failed to read net.ipv6.conf.all.disable_ipv6 sysctl property: %m");
manager->sysctl_ipv6_enabled = value[0] == '0';
return manager->sysctl_ipv6_enabled;
}

View File

@ -56,6 +56,8 @@ struct Manager {
Set *rules;
Set *rules_foreign;
Set *rules_saved;
int sysctl_ipv6_enabled;
};
extern const sd_bus_vtable manager_vtable[];
@ -93,4 +95,6 @@ Link *manager_dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
int manager_dhcp6_prefix_remove_all(Manager *m, Link *link);
int manager_sysctl_ipv6_enabled(Manager *manager);
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);

View File

@ -60,6 +60,22 @@ int sysctl_write(const char *property, const char *value) {
return 0;
}
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 **content) {
char *p;
@ -69,3 +85,25 @@ int sysctl_read(const char *property, char **content) {
p = strjoina("/proc/sys/", property);
return read_full_file(p, content, 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_one_line_file(p, &value);
if (r < 0)
return r;
if (ret)
*ret = TAKE_PTR(value);
return r;
}

View File

@ -1,7 +1,29 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "macro.h"
#include "stdio-util.h"
#include "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_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);

View File

@ -0,0 +1,6 @@
[Match]
Name=dummy98
[Network]
IPv6AcceptRA=no
Address=10.2.3.4/16

View File

@ -117,6 +117,7 @@ class Utilities():
return f.readline().strip()
def copy_unit_to_networkd_unit_path(self, *units):
print()
for unit in units:
shutil.copy(os.path.join(networkd_ci_path, unit), network_unit_file_path)
if (os.path.exists(os.path.join(networkd_ci_path, unit + '.d'))):
@ -172,7 +173,6 @@ class Utilities():
else:
subprocess.check_call('systemctl restart systemd-networkd', shell=True)
time.sleep(5)
print()
class NetworkdNetDevTests(unittest.TestCase, Utilities):
@ -598,6 +598,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
'25-route-section.network',
'25-route-tcp-window-settings.network',
'25-route-type.network',
'25-sysctl-disable-ipv6.network',
'25-sysctl.network',
'configure-without-carrier.network',
'routing-policy-rule.network',
@ -960,6 +961,45 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'forwarding'),'1')
self.assertEqual(self.read_ipv4_sysctl_attr('dummy98', 'proxy_arp'), '1')
def test_sysctl_disable_ipv6(self):
self.copy_unit_to_networkd_unit_path('25-sysctl-disable-ipv6.network', '12-dummy.netdev')
print('## Disable ipv6')
self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=1']), 0)
self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=1']), 0)
self.start_networkd()
self.assertTrue(self.link_exits('dummy98'))
output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
print(output)
self.assertEqual(output, '')
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
self.assertRegex(output, 'State: routable \(configured\)')
self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
print('## Enable ipv6')
self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.all.disable_ipv6=0']), 0)
self.assertEqual(subprocess.call(['sysctl', 'net.ipv6.conf.default.disable_ipv6=0']), 0)
self.start_networkd()
self.assertTrue(self.link_exits('dummy98'))
output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
print(output)
self.assertRegex(output, 'inet6 .* scope link')
output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
self.assertRegex(output, 'State: routable \(configured\)')
def test_bind_carrier(self):
self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
self.start_networkd()