diff --git a/src/network/meson.build b/src/network/meson.build index 28941b4468..c2a197162f 100644 --- a/src/network/meson.build +++ b/src/network/meson.build @@ -111,6 +111,8 @@ sources = files(''' networkd-speed-meter.h networkd-sriov.c networkd-sriov.h + networkd-sysctl.c + networkd-sysctl.h networkd-util.c networkd-util.h networkd-wifi.c diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 69cc90544f..0f41cae3fd 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -38,6 +38,7 @@ #include "networkd-neighbor.h" #include "networkd-nexthop.h" #include "networkd-sriov.h" +#include "networkd-sysctl.h" #include "networkd-radv.h" #include "networkd-routing-policy-rule.h" #include "networkd-wifi.h" @@ -106,7 +107,7 @@ bool link_ipv6ll_enabled(Link *link) { return link->network->link_local & ADDRESS_FAMILY_IPV6; } -static bool link_ipv6_enabled(Link *link) { +bool link_ipv6_enabled(Link *link) { assert(link); if (!socket_ipv6_is_supported()) @@ -128,71 +129,6 @@ static bool link_ipv6_enabled(Link *link) { return false; } -bool link_ip_forward_enabled(Link *link, int family) { - assert(link); - assert(IN_SET(family, AF_INET, AF_INET6)); - - if (family == AF_INET6 && !socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); -} - -static bool link_proxy_arp_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->proxy_arp < 0) - return false; - - return true; -} - -static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (link->flags & IFF_LOOPBACK) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (!link->network) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - return link->network->ipv6_privacy_extensions; -} - -static int link_update_ipv6_sysctl(Link *link) { - bool enabled; - int r; - - if (link->flags & IFF_LOOPBACK) - return 0; - - enabled = link_ipv6_enabled(link); - if (enabled) { - r = sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false); - if (r < 0) - return log_link_warning_errno(link, r, "Cannot enable IPv6: %m"); - - log_link_info(link, "IPv6 successfully enabled"); - } - - return 0; -} - static bool link_is_enslaved(Link *link) { if (link->flags & IFF_SLAVE) /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */ @@ -947,19 +883,6 @@ static int link_set_static_configs(Link *link) { return 0; } -static int link_set_proxy_arp(Link *link) { - int r; - - if (!link_proxy_arp_enabled(link)) - return 0; - - 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"); - - return 0; -} - static int link_configure_continue(Link *link); static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -1983,179 +1906,6 @@ static int link_enter_join_netdev(Link *link) { return 0; } -static int link_set_ipv4_forward(Link *link) { - int r; - - if (!link_ipv4_forward_enabled(link)) - return 0; - - /* We propagate the forwarding flag from one interface to the - * global setting one way. This means: as long as at least one - * interface was configured at any time that had IP forwarding - * enabled the setting will stay on for good. We do this - * primarily to keep IPv4 and IPv6 packet forwarding behaviour - * somewhat in sync (see below). */ - - 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"); - - return 0; -} - -static int link_set_ipv6_forward(Link *link) { - int r; - - if (!link_ipv6_forward_enabled(link)) - return 0; - - /* On Linux, the IPv6 stack does not know a per-interface - * packet forwarding setting: either packet forwarding is on - * for all, or off for all. We hence don't bother with a - * per-interface setting, but simply propagate the interface - * flag, if it is set, to the global flag, one-way. Note that - * while IPv4 would allow a per-interface flag, we expose the - * same behaviour there and also propagate the setting from - * one to all, to keep things simple (see above). */ - - 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"); - - return 0; -} - -static int link_set_ipv6_privacy_extensions(Link *link) { - IPv6PrivacyExtensions s; - int r; - - s = link_ipv6_privacy_extensions(link); - if (s < 0) - return 0; - - 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"); - - return 0; -} - -static int link_set_ipv6_accept_ra(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - 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"); - - return 0; -} - -static int link_set_ipv6_dad_transmits(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_dad_transmits < 0) - return 0; - - 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"); - - return 0; -} - -static int link_set_ipv6_hop_limit(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_hop_limit < 0) - return 0; - - 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"); - - return 0; -} - -static int link_set_ipv6_mtu(Link *link) { - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (link->network->ipv6_mtu == 0) - return 0; - - /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes - * on the interface. Bump up IPv6 MTU bytes to IPV6_MTU_MIN. */ - if (link->network->ipv6_mtu < IPV6_MIN_MTU) { - log_link_notice(link, "Bumping IPv6 MTU to "STRINGIFY(IPV6_MIN_MTU)" byte minimum required"); - link->network->ipv6_mtu = IPV6_MIN_MTU; - } - - r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu); - if (r < 0) { - if (link->mtu < link->network->ipv6_mtu) - log_link_warning(link, "Cannot set IPv6 MTU %"PRIu32" higher than device MTU %"PRIu32, - link->network->ipv6_mtu, link->mtu); - else - log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface: %m"); - } - - link->ipv6_mtu_set = true; - - return 0; -} - -static int link_set_ipv4_accept_local(Link *link) { - int r; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (link->network->ipv4_accept_local < 0) - return 0; - - r = sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface: %m"); - - return 0; -} - static int link_enumerate_ipv6_tentative_addresses(Link *link) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; sd_netlink_message *addr; @@ -2258,46 +2008,14 @@ int link_configure(Link *link) { if (link->iftype == ARPHRD_CAN) return link_configure_can(link); - /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled - * for this interface, then enable IPv6 */ - (void) link_update_ipv6_sysctl(link); - - r = link_set_proxy_arp(link); + r = link_set_sysctl(link); if (r < 0) - return r; + return r; r = link_set_ipv6_proxy_ndp_addresses(link); if (r < 0) return r; - r = link_set_ipv4_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_privacy_extensions(link); - if (r < 0) - return r; - - r = link_set_ipv6_accept_ra(link); - if (r < 0) - return r; - - r = link_set_ipv6_dad_transmits(link); - if (r < 0) - return r; - - r = link_set_ipv6_hop_limit(link); - if (r < 0) - return r; - - r = link_set_ipv4_accept_local(link); - if (r < 0) - return r; - r = link_set_flags(link); if (r < 0) return r; @@ -2395,7 +2113,7 @@ static int link_configure_continue(Link *link) { * we must set this here, after we've set device mtu */ r = link_set_ipv6_mtu(link); if (r < 0) - return r; + log_link_warning_errno(link, r, "Cannot set IPv6 MTU for interface, ignoring: %m"); if (link_has_carrier(link) || link->network->configure_without_carrier) { r = link_acquire_conf(link); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 43451ee2de..08cfc60c1f 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -221,17 +221,10 @@ int link_save_and_clean(Link *link); int link_carrier_reset(Link *link); bool link_has_carrier(Link *link); +bool link_ipv6_enabled(Link *link); bool link_ipv6ll_enabled(Link *link); int link_ipv6ll_gained(Link *link, const struct in6_addr *address); -bool link_ip_forward_enabled(Link *link, int family); -static inline bool link_ipv4_forward_enabled(Link *link) { - return link_ip_forward_enabled(link, AF_INET); -} -static inline bool link_ipv6_forward_enabled(Link *link) { - return link_ip_forward_enabled(link, AF_INET6); -} - int link_set_mtu(Link *link, uint32_t mtu); bool link_ipv4ll_enabled(Link *link, AddressFamily mask); diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 89f2b0475b..0e42e768da 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -14,6 +14,7 @@ #include "networkd-dhcp6.h" #include "networkd-manager.h" #include "networkd-ndisc.h" +#include "networkd-sysctl.h" #include "string-table.h" #include "string-util.h" #include "strv.h" @@ -57,7 +58,7 @@ bool link_ipv6_accept_ra_enabled(Link *link) { */ if (link->network->ipv6_accept_ra < 0) /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ - return !link_ipv6_forward_enabled(link); + return !link_ip_forward_enabled(link, AF_INET6); else if (link->network->ipv6_accept_ra > 0) /* accept RA even if ip_forward is enabled */ return true; diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index e02b7e9586..78b888582b 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -991,50 +991,6 @@ int config_parse_ipv6token( return 0; } -static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { - [IPV6_PRIVACY_EXTENSIONS_NO] = "no", - [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", - [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", -}; - -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 = data; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ipv6_privacy_extensions); - - 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; -} - int config_parse_hostname( const char *unit, const char *filename, diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 99cce40533..ad61995ca6 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -21,20 +21,12 @@ #include "networkd-lldp-tx.h" #include "networkd-ndisc.h" #include "networkd-radv.h" +#include "networkd-sysctl.h" #include "networkd-util.h" #include "ordered-set.h" #include "resolve-util.h" #include "socket-netlink.h" -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_MAX, - _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, -} IPv6PrivacyExtensions; - typedef enum KeepConfiguration { KEEP_CONFIGURATION_NO = 0, KEEP_CONFIGURATION_DHCP_ON_START = 1 << 0, @@ -329,7 +321,6 @@ bool network_has_static_ipv6_configurations(Network *network); CONFIG_PARSER_PROTOTYPE(config_parse_stacked_netdev); CONFIG_PARSER_PROTOTYPE(config_parse_tunnel); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6token); -CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions); CONFIG_PARSER_PROTOTYPE(config_parse_domains); CONFIG_PARSER_PROTOTYPE(config_parse_dns); CONFIG_PARSER_PROTOTYPE(config_parse_hostname); @@ -342,9 +333,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); -const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; -IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; - const char* keep_configuration_to_string(KeepConfiguration i) _const_; KeepConfiguration keep_configuration_from_string(const char *s) _pure_; diff --git a/src/network/networkd-sysctl.c b/src/network/networkd-sysctl.c new file mode 100644 index 0000000000..c8facbf831 --- /dev/null +++ b/src/network/networkd-sysctl.c @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include +#include + +#include "missing_network.h" +#include "networkd-link.h" +#include "networkd-network.h" +#include "networkd-sysctl.h" +#include "socket-util.h" +#include "string-table.h" +#include "sysctl-util.h" + +static int link_update_ipv6_sysctl(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link_ipv6_enabled(link)) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false); +} + +static int link_set_proxy_arp(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->proxy_arp < 0) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0); +} + +bool link_ip_forward_enabled(Link *link, int family) { + assert(link); + assert(IN_SET(family, AF_INET, AF_INET6)); + + if (family == AF_INET6 && !socket_ipv6_is_supported()) + return false; + + if (link->flags & IFF_LOOPBACK) + return false; + + if (!link->network) + return false; + + return link->network->ip_forward & (family == AF_INET ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_IPV6); +} + +static int link_set_ipv4_forward(Link *link) { + assert(link); + + if (!link_ip_forward_enabled(link, AF_INET)) + return 0; + + /* We propagate the forwarding flag from one interface to the + * global setting one way. This means: as long as at least one + * interface was configured at any time that had IP forwarding + * enabled the setting will stay on for good. We do this + * primarily to keep IPv4 and IPv6 packet forwarding behaviour + * somewhat in sync (see below). */ + + return sysctl_write_ip_property(AF_INET, NULL, "ip_forward", "1"); +} + +static int link_set_ipv6_forward(Link *link) { + assert(link); + + if (!link_ip_forward_enabled(link, AF_INET6)) + return 0; + + /* On Linux, the IPv6 stack does not know a per-interface + * packet forwarding setting: either packet forwarding is on + * for all, or off for all. We hence don't bother with a + * per-interface setting, but simply propagate the interface + * flag, if it is set, to the global flag, one-way. Note that + * while IPv4 would allow a per-interface flag, we expose the + * same behaviour there and also propagate the setting from + * one to all, to keep things simple (see above). */ + + return sysctl_write_ip_property(AF_INET6, "all", "forwarding", "1"); +} + +static int link_set_ipv6_privacy_extensions(Link *link) { + assert(link); + + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions); +} + +static int link_set_ipv6_accept_ra(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0"); +} + +static int link_set_ipv6_dad_transmits(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_dad_transmits < 0) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits); +} + +static int link_set_ipv6_hop_limit(Link *link) { + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (!link->network) + return 0; + + if (link->network->ipv6_hop_limit < 0) + return 0; + + return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit); +} + +static int link_set_ipv4_accept_local(Link *link) { + assert(link); + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (link->network->ipv4_accept_local < 0) + return 0; + + return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0); +} + +int link_set_sysctl(Link *link) { + int r; + + assert(link); + + /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled + * for this interface, then enable IPv6 */ + r = link_update_ipv6_sysctl(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot enable IPv6, ignoring: %m"); + + r = link_set_proxy_arp(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface, ignoring: %m"); + + r = link_set_ipv4_forward(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); + + r = link_set_ipv6_forward(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m");; + + r = link_set_ipv6_privacy_extensions(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignorign: %m"); + + r = link_set_ipv6_accept_ra(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface, ignoring: %m"); + + r = link_set_ipv6_dad_transmits(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface, ignoring: %m"); + + r = link_set_ipv6_hop_limit(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface, ignoring: %m"); + + r = link_set_ipv4_accept_local(link); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface, ignoring: %m"); + + return 0; +} + +int link_set_ipv6_mtu(Link *link) { + int r; + + assert(link); + + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->flags & IFF_LOOPBACK) + return 0; + + if (link->network->ipv6_mtu == 0) + return 0; + + r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", link->network->ipv6_mtu); + if (r < 0) + return r; + + link->ipv6_mtu_set = true; + + return 0; +} + +static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { + [IPV6_PRIVACY_EXTENSIONS_NO] = "no", + [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", + [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", +}; + +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 = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(ipv6_privacy_extensions); + + 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; +} diff --git a/src/network/networkd-sysctl.h b/src/network/networkd-sysctl.h new file mode 100644 index 0000000000..a409d8f54f --- /dev/null +++ b/src/network/networkd-sysctl.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include + +#include "conf-parser.h" + +typedef struct Link Link; + +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_MAX, + _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, +} IPv6PrivacyExtensions; + +bool link_ip_forward_enabled(Link *link, int family); +int link_set_sysctl(Link *link); +int link_set_ipv6_mtu(Link *link); + +const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; +IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; + +CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);