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",
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_;
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;