From 7cab78503accb854fabab462ffd788e51c46b90a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 Jun 2023 18:51:58 +0900 Subject: [PATCH 1/3] network: introduce IPV6_PRIVACY_EXTENSIONS_KERNEL enum value No functional change. Preparation for using the _INVALID value in later commit. --- src/network/networkd-sysctl.c | 45 ++++++----------------------------- src/network/networkd-sysctl.h | 3 ++- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 51a697a667..729bd68dab 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -100,8 +100,8 @@ static int link_set_ipv6_privacy_extensions(Link *link) { if (!link->network) return 0; - // this is the special "kernel" value - if (link->network->ipv6_privacy_extensions == _IPV6_PRIVACY_EXTENSIONS_INVALID) + /* When "kernel", do not update the setting. */ + if (link->network->ipv6_privacy_extensions == IPV6_PRIVACY_EXTENSIONS_KERNEL) return 0; return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); @@ -307,44 +307,13 @@ int link_set_sysctl(Link *link) { } static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { - [IPV6_PRIVACY_EXTENSIONS_NO] = "no", + [IPV6_PRIVACY_EXTENSIONS_NO] = "no", [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", - [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", + [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", + [IPV6_PRIVACY_EXTENSIONS_KERNEL] = "kernel", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions, IPV6_PRIVACY_EXTENSIONS_YES); - -int config_parse_ipv6_privacy_extensions( - const char* unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - IPv6PrivacyExtensions s, *ipv6_privacy_extensions = ASSERT_PTR(data); - - assert(filename); - assert(lvalue); - assert(rvalue); - - s = ipv6_privacy_extensions_from_string(rvalue); - if (s < 0) { - if (streq(rvalue, "kernel")) - s = _IPV6_PRIVACY_EXTENSIONS_INVALID; - else { - log_syntax(unit, LOG_WARNING, filename, line, 0, - "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); - return 0; - } - } - - *ipv6_privacy_extensions = s; - - return 0; -} +DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_privacy_extensions, ipv6_privacy_extensions, IPv6PrivacyExtensions, + "Failed to parse IPv6 privacy extensions option"); diff --git a/src/network/networkd-sysctl.h b/src/network/networkd-sysctl.h index cb1db10fe8..df5d6e08ff 100644 --- a/src/network/networkd-sysctl.h +++ b/src/network/networkd-sysctl.h @@ -11,7 +11,8 @@ typedef enum IPv6PrivacyExtensions { /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ IPV6_PRIVACY_EXTENSIONS_NO, IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, - IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ + IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ + IPV6_PRIVACY_EXTENSIONS_KERNEL, /* keep the kernel's default value */ _IPV6_PRIVACY_EXTENSIONS_MAX, _IPV6_PRIVACY_EXTENSIONS_INVALID = -EINVAL, } IPv6PrivacyExtensions; From 932ef6ecd45662b25bc5ce7f82b64db39289b216 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 Jun 2023 19:09:53 +0900 Subject: [PATCH 2/3] network: add global setting for IPv6PrivacyExtensions= Closes #28186. --- man/networkd.conf.xml | 10 ++++++++++ man/systemd.network.xml | 6 ++++-- src/network/networkd-gperf.gperf | 1 + src/network/networkd-manager.c | 1 + src/network/networkd-manager.h | 2 ++ src/network/networkd-network.c | 2 +- src/network/networkd-sysctl.c | 12 ++++++++++-- src/network/networkd.conf | 1 + 8 files changed, 30 insertions(+), 5 deletions(-) diff --git a/man/networkd.conf.xml b/man/networkd.conf.xml index 85b21ee7f9..abf47d17b6 100644 --- a/man/networkd.conf.xml +++ b/man/networkd.conf.xml @@ -94,6 +94,16 @@ specified earlier are cleared. Defaults to unset. + + IPv6PrivacyExtensions= + + Specifies the default value for per-network IPv6PrivacyExtensions=. + Takes a boolean or the special values prefer-public and + kernel. See for details in + systemd.network5. + Defaults to no. + + diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1b34000052..f527f31111 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -724,8 +724,10 @@ Table=1234 enables the privacy extensions and prefers temporary addresses over public addresses. When prefer-public, enables the privacy extensions, but prefers public addresses over temporary addresses. When false, the privacy extensions remain disabled. When - kernel, the kernel's default setting will be left in place. Defaults to - no. + kernel, the kernel's default setting will be left in place. When unspecified, + the value specified in the same setting in + networkd.conf5, + which defaults to no, will be used. diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf index 8ed90f0e4b..8542ffa6b5 100644 --- a/src/network/networkd-gperf.gperf +++ b/src/network/networkd-gperf.gperf @@ -26,6 +26,7 @@ Network.SpeedMeterIntervalSec, config_parse_sec, Network.ManageForeignRoutingPolicyRules, config_parse_bool, 0, offsetof(Manager, manage_foreign_rules) Network.ManageForeignRoutes, config_parse_bool, 0, offsetof(Manager, manage_foreign_routes) Network.RouteTable, config_parse_route_table_names, 0, 0 +Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Manager, ipv6_privacy_extensions) DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp_duid) DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, dhcp_duid) DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Manager, dhcp6_duid) diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 303b76c0c6..b6ba216eee 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -589,6 +589,7 @@ int manager_new(Manager **ret, bool test_mode) { *m = (Manager) { .keep_configuration = _KEEP_CONFIGURATION_INVALID, + .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO, .test_mode = test_mode, .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL, .online_state = _LINK_ONLINE_STATE_INVALID, diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index c9cbcf9289..a27137a845 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -13,6 +13,7 @@ #include "hashmap.h" #include "networkd-link.h" #include "networkd-network.h" +#include "networkd-sysctl.h" #include "ordered-set.h" #include "set.h" #include "time-util.h" @@ -29,6 +30,7 @@ struct Manager { int ethtool_fd; KeepConfiguration keep_configuration; + IPv6PrivacyExtensions ipv6_privacy_extensions; bool test_mode; bool enumerating; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 9a0511eeef..7eef3d5b52 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -467,7 +467,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi .ipv4_accept_local = -1, .ipv4_route_localnet = -1, - .ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO, + .ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID, .ipv6_dad_transmits = -1, .ipv6_hop_limit = -1, .ipv6_proxy_ndp = -1, diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c index 729bd68dab..7c9a83ba57 100644 --- a/src/network/networkd-sysctl.c +++ b/src/network/networkd-sysctl.c @@ -5,6 +5,7 @@ #include "missing_network.h" #include "networkd-link.h" +#include "networkd-manager.h" #include "networkd-network.h" #include "networkd-sysctl.h" #include "socket-util.h" @@ -89,7 +90,10 @@ static int link_set_ipv6_forward(Link *link) { } static int link_set_ipv6_privacy_extensions(Link *link) { + IPv6PrivacyExtensions val; + assert(link); + assert(link->manager); if (!socket_ipv6_is_supported()) return 0; @@ -100,11 +104,15 @@ static int link_set_ipv6_privacy_extensions(Link *link) { if (!link->network) return 0; + val = link->network->ipv6_privacy_extensions; + if (val < 0) /* If not specified, then use the global setting. */ + val = link->manager->ipv6_privacy_extensions; + /* When "kernel", do not update the setting. */ - if (link->network->ipv6_privacy_extensions == IPV6_PRIVACY_EXTENSIONS_KERNEL) + if (val == IPV6_PRIVACY_EXTENSIONS_KERNEL) return 0; - return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) val); } static int link_set_ipv6_accept_ra(Link *link) { diff --git a/src/network/networkd.conf b/src/network/networkd.conf index 38dc9f1f79..f2c0790d87 100644 --- a/src/network/networkd.conf +++ b/src/network/networkd.conf @@ -18,6 +18,7 @@ #ManageForeignRoutingPolicyRules=yes #ManageForeignRoutes=yes #RouteTable= +#IPv6PrivacyExtensions=no [DHCPv4] #DUIDType=vendor From 856a247e193760b490428d673188f55644546d99 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 29 Jun 2023 21:58:23 +0900 Subject: [PATCH 3/3] test-network: add test for global IPv6PrivacyExtensions= setting --- .../conf/25-global-ipv6-privacy-extensions.conf | 3 +++ test/test-network/conf/25-sysctl.network | 7 +++---- .../25-ipv6-privacy-extensions.conf | 3 +++ test/test-network/systemd-networkd-tests.py | 11 +++++++++-- 4 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 test/test-network/conf/25-global-ipv6-privacy-extensions.conf create mode 100644 test/test-network/conf/25-sysctl.network.d/25-ipv6-privacy-extensions.conf diff --git a/test/test-network/conf/25-global-ipv6-privacy-extensions.conf b/test/test-network/conf/25-global-ipv6-privacy-extensions.conf new file mode 100644 index 0000000000..ced7f7bd9b --- /dev/null +++ b/test/test-network/conf/25-global-ipv6-privacy-extensions.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Network] +IPv6PrivacyExtensions=prefer-public diff --git a/test/test-network/conf/25-sysctl.network b/test/test-network/conf/25-sysctl.network index 72575eec8d..e7d078aba0 100644 --- a/test/test-network/conf/25-sysctl.network +++ b/test/test-network/conf/25-sysctl.network @@ -3,11 +3,10 @@ Name=dummy98 [Network] -IPForward=true -IPv6PrivacyExtensions=true +IPForward=yes IPv6DuplicateAddressDetection=3 IPv6HopLimit=5 -IPv4ProxyARP=true -IPv6ProxyNDP=true +IPv4ProxyARP=yes +IPv6ProxyNDP=yes IPv6AcceptRA=no IPv4AcceptLocal=yes diff --git a/test/test-network/conf/25-sysctl.network.d/25-ipv6-privacy-extensions.conf b/test/test-network/conf/25-sysctl.network.d/25-ipv6-privacy-extensions.conf new file mode 100644 index 0000000000..35782d7555 --- /dev/null +++ b/test/test-network/conf/25-sysctl.network.d/25-ipv6-privacy-extensions.conf @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +[Network] +IPv6PrivacyExtensions=yes diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index c068f37a8a..e70d359fa9 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3121,12 +3121,13 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'inet6 .* scope link') def test_sysctl(self): - copy_network_unit('25-sysctl.network', '12-dummy.netdev') + copy_networkd_conf_dropin('25-global-ipv6-privacy-extensions.conf') + copy_network_unit('25-sysctl.network', '12-dummy.netdev', copy_dropins=False) start_networkd() self.wait_online(['dummy98:degraded']) self.check_ipv6_sysctl_attr('dummy98', 'forwarding', '1') - self.check_ipv6_sysctl_attr('dummy98', 'use_tempaddr', '2') + self.check_ipv6_sysctl_attr('dummy98', 'use_tempaddr', '1') self.check_ipv6_sysctl_attr('dummy98', 'dad_transmits', '3') self.check_ipv6_sysctl_attr('dummy98', 'hop_limit', '5') self.check_ipv6_sysctl_attr('dummy98', 'proxy_ndp', '1') @@ -3134,6 +3135,12 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities): self.check_ipv4_sysctl_attr('dummy98', 'proxy_arp', '1') self.check_ipv4_sysctl_attr('dummy98', 'accept_local', '1') + copy_network_unit('25-sysctl.network.d/25-ipv6-privacy-extensions.conf') + networkctl_reload() + self.wait_online(['dummy98:degraded']) + + self.check_ipv6_sysctl_attr('dummy98', 'use_tempaddr', '2') + def test_sysctl_disable_ipv6(self): copy_network_unit('25-sysctl-disable-ipv6.network', '12-dummy.netdev')