From: Yu Watanabe Date: Thu, 16 Jul 2020 01:31:49 +0000 (+0900) Subject: network: dhcp4: fix another race with SendDecline=yes X-Git-Tag: v246-rc2~59^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=153cf041399fe76c80c2c96d98ec5489a83f44ed;p=thirdparty%2Fsystemd.git network: dhcp4: fix another race with SendDecline=yes If the SD_IPV4ACD_EVENT_BIND event happens before all routes are assigned, then the link stuck in configuring state. --- diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index fd26be18fdb..f732f385671 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -52,12 +52,16 @@ static void dhcp4_release_old_lease(Link *link) { } static void dhcp4_check_ready(Link *link) { - if (link->dhcp4_messages == 0) { - link->dhcp4_configured = true; - /* New address and routes are configured now. Let's release old lease. */ - dhcp4_release_old_lease(link); - link_check_ready(link); - } + if (link->network->dhcp_send_decline && !link->dhcp4_address_bind) + return; + + if (link->dhcp4_messages > 0) + return; + + link->dhcp4_configured = true; + /* New address and routes are configured now. Let's release old lease. */ + dhcp4_release_old_lease(link); + link_check_ready(link); } static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { @@ -86,20 +90,18 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li return 1; } - if (link->dhcp4_messages == 0) { - if (link->dhcp4_route_failed) { - link->dhcp4_route_failed = false; - link->dhcp4_route_retrying = true; + if (link->dhcp4_messages == 0 && link->dhcp4_route_failed) { + link->dhcp4_route_failed = false; + link->dhcp4_route_retrying = true; - r = dhcp4_remove_all(link); - if (r < 0) - link_enter_failed(link); - return 1; - } - if (!link->network->dhcp_send_decline) - dhcp4_check_ready(link); + r = dhcp4_remove_all(link); + if (r < 0) + link_enter_failed(link); + return 1; } + dhcp4_check_ready(link); + return 1; } @@ -836,6 +838,7 @@ static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { (void) in_addr_to_string(AF_INET, &address, &pretty); log_link_debug(link, "Successfully claimed DHCP4 address %s", strna(pretty)); } + link->dhcp4_address_bind = true; dhcp4_check_ready(link); break; @@ -886,6 +889,44 @@ static int configure_dhcpv4_duplicate_address_detection(Link *link) { return 0; } +static int dhcp4_start_acd(Link *link) { + union in_addr_union addr; + int r; + + if (!link->network->dhcp_send_decline) + return 0; + + if (!link->dhcp_lease) + return 0; + + link->dhcp4_address_bind = false; + + r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr.in); + if (r < 0) + return r; + + r = sd_ipv4acd_set_address(link->network->dhcp_acd, &addr.in); + if (r < 0) + return r; + + r = sd_ipv4acd_set_callback(link->network->dhcp_acd, dhcp_address_on_acd, link); + if (r < 0) + return r; + + if (DEBUG_LOGGING) { + _cleanup_free_ char *pretty = NULL; + + (void) in_addr_to_string(AF_INET, &addr, &pretty); + log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty)); + } + + r = sd_ipv4acd_start(link->network->dhcp_acd, true); + if (r < 0) + return r; + + return 1; +} + static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int r; @@ -915,31 +956,14 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link * return 1; } - if (link->network->dhcp_send_decline) { - union in_addr_union addr; - - (void) sd_dhcp_lease_get_address(link->dhcp_lease, &addr.in); - - r = sd_ipv4acd_set_address(link->network->dhcp_acd, &addr.in); - if (r < 0) - return r; - - r = sd_ipv4acd_set_callback(link->network->dhcp_acd, dhcp_address_on_acd, link); - if (r < 0) - return r; - - if (DEBUG_LOGGING) { - _cleanup_free_ char *pretty = NULL; - - (void) in_addr_to_string(AF_INET, &addr, &pretty); - log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty)); - } + r = dhcp4_start_acd(link); + if (r < 0) { + log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCP4 adddress: %m"); + link_enter_failed(link); + return 1; + } - r = sd_ipv4acd_start(link->network->dhcp_acd, true); - if (r < 0) - log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m"); - } else - dhcp4_check_ready(link); + dhcp4_check_ready(link); return 1; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 7b39dd91ae5..fb12301fe6e 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -108,6 +108,7 @@ typedef struct Link { bool dhcp4_route_failed:1; bool dhcp4_route_retrying:1; bool dhcp4_configured:1; + bool dhcp4_address_bind:1; bool dhcp6_address_configured:1; bool dhcp6_route_configured:1; bool dhcp6_pd_address_configured:1;