diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c index cc5c0223b5..7383c84724 100644 --- a/src/libsystemd-network/sd-radv.c +++ b/src/libsystemd-network/sd-radv.c @@ -77,6 +77,12 @@ _public_ sd_event *sd_radv_get_event(sd_radv *ra) { return ra->event; } +_public_ int sd_radv_is_running(sd_radv *ra) { + assert_return(ra, false); + + return ra->state != SD_RADV_STATE_IDLE; +} + static void radv_reset(sd_radv *ra) { assert(ra); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index fc15e510e9..24de9a7ac8 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3932,78 +3932,114 @@ int link_update(Link *link, sd_netlink_message *m) { /* The kernel may broadcast NEWLINK messages without the MAC address set, simply ignore them. */ r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac); - if (r >= 0) { - if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, - ETH_ALEN)) { + if (r >= 0 && memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN) != 0) { - memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, - ETH_ALEN); + memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN); - log_link_debug(link, "MAC address: " - "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - mac.ether_addr_octet[0], - mac.ether_addr_octet[1], - mac.ether_addr_octet[2], - mac.ether_addr_octet[3], - mac.ether_addr_octet[4], - mac.ether_addr_octet[5]); + log_link_debug(link, "Gained new MAC address: " + "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + mac.ether_addr_octet[0], + mac.ether_addr_octet[1], + mac.ether_addr_octet[2], + mac.ether_addr_octet[3], + mac.ether_addr_octet[4], + mac.ether_addr_octet[5]); - if (link->ipv4ll) { - r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); + if (link->ipv4ll) { + bool restart = sd_ipv4ll_is_running(link->ipv4ll) > 0; + + if (restart) { + r = sd_ipv4ll_stop(link->ipv4ll); if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); + return log_link_warning_errno(link, r, "Could not stop IPv4LL client: %m"); } - if (link->dhcp_client) { - r = sd_dhcp_client_set_mac(link->dhcp_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); + r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); - r = dhcp4_set_client_identifier(link); + if (restart) { + r = sd_ipv4ll_start(link->ipv4ll); if (r < 0) - return r; + return log_link_warning_errno(link, r, "Could not restart IPv4LL client: %m"); + } + } + + if (link->dhcp_client) { + r = sd_dhcp_client_set_mac(link->dhcp_client, + (const uint8_t *) &link->mac, + sizeof (link->mac), + ARPHRD_ETHER); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); + + r = dhcp4_set_client_identifier(link); + if (r < 0) + return log_link_warning_errno(link, r, "Could not set DHCP client identifier: %m"); + } + + if (link->dhcp6_client) { + const DUID* duid = link_get_duid(link); + bool restart = sd_dhcp6_client_is_running(link->dhcp6_client) > 0; + + if (restart) { + r = sd_dhcp6_client_stop(link->dhcp6_client); + if (r < 0) + return log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m"); } - if (link->dhcp6_client) { - const DUID* duid = link_get_duid(link); + r = sd_dhcp6_client_set_mac(link->dhcp6_client, + (const uint8_t *) &link->mac, + sizeof (link->mac), + ARPHRD_ETHER); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - r = sd_dhcp6_client_set_mac(link->dhcp6_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); + if (link->network->iaid_set) { + r = sd_dhcp6_client_set_iaid(link->dhcp6_client, link->network->iaid); if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - - if (link->network->iaid_set) { - r = sd_dhcp6_client_set_iaid(link->dhcp6_client, - link->network->iaid); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); - } - - r = sd_dhcp6_client_set_duid(link->dhcp6_client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); + return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); } - if (link->radv) { - r = sd_radv_set_mac(link->radv, &link->mac); + r = sd_dhcp6_client_set_duid(link->dhcp6_client, + duid->type, + duid->raw_data_len > 0 ? duid->raw_data : NULL, + duid->raw_data_len); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); + + if (restart) { + r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m"); + return log_link_warning_errno(link, r, "Could not restart DHCPv6 client: %m"); + } + } + + if (link->radv) { + bool restart = sd_radv_is_running(link->radv); + + if (restart) { + r = sd_radv_stop(link->radv); + if (r < 0) + return log_link_warning_errno(link, r, "Could not stop Router Advertisement: %m"); } - if (link->ndisc) { - r = sd_ndisc_set_mac(link->ndisc, &link->mac); + r = sd_radv_set_mac(link->radv, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC for Router Advertisement: %m"); + + if (restart) { + r = sd_radv_start(link->radv); if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC for ndisc: %m"); + return log_link_warning_errno(link, r, "Could not restart Router Advertisement: %m"); } } + + if (link->ndisc) { + r = sd_ndisc_set_mac(link->ndisc, &link->mac); + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m"); + } } old_master = link->master_ifindex; diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h index 011e40d8a5..0f1437829d 100644 --- a/src/systemd/sd-radv.h +++ b/src/systemd/sd-radv.h @@ -50,6 +50,7 @@ sd_event *sd_radv_get_event(sd_radv *ra); int sd_radv_start(sd_radv *ra); int sd_radv_stop(sd_radv *ra); +int sd_radv_is_running(sd_radv *ra); int sd_radv_set_ifindex(sd_radv *ra, int interface_index); int sd_radv_set_mac(sd_radv *ra, const struct ether_addr *mac_addr);