From: Yu Watanabe Date: Fri, 13 Mar 2026 16:33:54 +0000 (+0900) Subject: sd-dhcp-client: notify SD_DHCP_CLIENT_EVENT_EXPIRED only when we already have a bound... X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dff63a31ce33e4525f68351b47516a69b27334c;p=thirdparty%2Fsystemd.git sd-dhcp-client: notify SD_DHCP_CLIENT_EVENT_EXPIRED only when we already have a bound lease Otherwise, if we emit the notification without a valid bound lease, networkd may be confused (of course should not, but for safety). Also, increment the delay before calling client_start_delayed(). Otherwise, the first reboot is done instantaneously. --- diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index f6ab4b34dfc..6ff6329ccf1 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -1328,6 +1328,34 @@ static int client_start(sd_dhcp_client *client) { return client_start_delayed(client); } +static int client_restart(sd_dhcp_client *client) { + assert(client); + DHCP_CLIENT_DONT_DESTROY(client); + + /* This is called when we receive a DHCPNAK or could not receive any replies. */ + + /* First, if we have a bound lease, then notify it is expired. */ + if (IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING)) { + client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); + + if (client->state == DHCP_STATE_STOPPED) + return 0; /* The notify callback stopped the client. */ + } + + /* On reboot, DHCPNAK or no reply suggests that the network is changed or the address is already + * used by another host. Let's restart the client immediately without any delay to speed up the + * reboot process. */ + if (client->state == DHCP_STATE_REBOOTING) + return client_start(client); + + /* Otherwise, we should restart the client with a short delay. */ + client->start_delay = CLAMP(client->start_delay * 2, + RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); + + log_dhcp_client(client, "REBOOT in %s", FORMAT_TIMESPAN(client->start_delay, USEC_PER_SEC)); + return client_start_delayed(client); +} + static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); @@ -1775,23 +1803,6 @@ static int client_enter_bound(sd_dhcp_client *client, int notify_event) { return 0; } -static int client_restart(sd_dhcp_client *client) { - int r; - assert(client); - - client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); - - r = client_start_delayed(client); - if (r < 0) - return r; - - log_dhcp_client(client, "REBOOT in %s", FORMAT_TIMESPAN(client->start_delay, USEC_PER_SEC)); - - client->start_delay = CLAMP(client->start_delay * 2, - RESTART_AFTER_NAK_MIN_USEC, RESTART_AFTER_NAK_MAX_USEC); - return 0; -} - static int client_verify_message_header(sd_dhcp_client *client, DHCPMessage *message, size_t len) { const uint8_t *expected_chaddr = NULL; uint8_t expected_hlen = 0;