diff options
-rw-r--r-- | src/network/networkd-ipv6ll.c | 10 | ||||
-rw-r--r-- | src/network/networkd-ipv6ll.h | 1 | ||||
-rw-r--r-- | src/network/networkd-setlink.c | 13 |
3 files changed, 24 insertions, 0 deletions
diff --git a/src/network/networkd-ipv6ll.c b/src/network/networkd-ipv6ll.c index 992be2fca6..79cf679daf 100644 --- a/src/network/networkd-ipv6ll.c +++ b/src/network/networkd-ipv6ll.c @@ -223,6 +223,16 @@ int link_set_ipv6ll_stable_secret(Link *link) { return sysctl_write_ip_property(AF_INET6, link->ifname, "stable_secret", str); } +int link_set_ipv6ll_addrgen_mode(Link *link, IPv6LinkLocalAddressGenMode mode) { + assert(link); + assert(mode >= 0 && mode < _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX); + + if (mode == link->ipv6ll_address_gen_mode) + return 0; + + return sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "addr_gen_mode", mode); +} + static const char* const ipv6_link_local_address_gen_mode_table[_IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_MAX] = { [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_EUI64] = "eui64", [IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE] = "none", diff --git a/src/network/networkd-ipv6ll.h b/src/network/networkd-ipv6ll.h index ac7a7d3e3e..a9763debb1 100644 --- a/src/network/networkd-ipv6ll.h +++ b/src/network/networkd-ipv6ll.h @@ -29,6 +29,7 @@ int ipv6ll_addrgen_mode_fill_message(sd_netlink_message *message, IPv6LinkLocalA int link_update_ipv6ll_addrgen_mode(Link *link, sd_netlink_message *message); int link_set_ipv6ll_stable_secret(Link *link); +int link_set_ipv6ll_addrgen_mode(Link *link, IPv6LinkLocalAddressGenMode mode); const char* ipv6_link_local_address_gen_mode_to_string(IPv6LinkLocalAddressGenMode s) _const_; IPv6LinkLocalAddressGenMode ipv6_link_local_address_gen_mode_from_string(const char *s) _pure_; diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c index 7540f6f60f..846528eb44 100644 --- a/src/network/networkd-setlink.c +++ b/src/network/networkd-setlink.c @@ -688,6 +688,19 @@ int link_request_to_set_addrgen_mode(Link *link) { if (mode == link->ipv6ll_address_gen_mode) return 0; + /* If the link is already up, then changing the mode by netlink does not take effect until the + * link goes down. Hence, we need to reset the interface. However, setting the mode by sysctl + * does not need that. Let's use the sysctl interface when the link is already up. + * See also issue #22424. */ + if (mode != IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE && + FLAGS_SET(link->flags, IFF_UP)) { + r = link_set_ipv6ll_addrgen_mode(link, mode); + if (r < 0) + log_link_warning_errno(link, r, "Cannot set IPv6 address generation mode, ignoring: %m"); + + return 0; + } + r = link_request_set_link(link, SET_LINK_ADDRESS_GENERATION_MODE, link_set_addrgen_mode_handler, &req); if (r < 0) return r; |