[wifi] Use DHCP_STATE_BOUND check instead of netif_is_link_up

netif_is_link_up() is insufficient — if wifi_station_connect()
completes quickly (e.g. fast_connect), the setup() call at line 710
could reach dhcp_renew() with link up but DHCP still in SELECTING
or REQUESTING state, causing the same state corruption.

Check dhcp->state == DHCP_STATE_BOUND directly to ensure dhcp_renew()
is only called when there is an actual lease to renew.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
J. Nick Koston
2026-02-13 14:36:51 -06:00
parent de76dfd117
commit c53d50b6cf

View File

@@ -16,7 +16,8 @@ extern "C" {
#include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/dhcp.h"
#include "lwip/init.h" // LWIP_VERSION_
#include "lwip/prot/dhcp.h" // DHCP_STATE_BOUND
#include "lwip/init.h" // LWIP_VERSION_
#include "lwip/apps/sntp.h"
#include "lwip/netif.h" // struct netif
#include <AddrList.h>
@@ -224,13 +225,14 @@ bool WiFiComponent::wifi_apply_hostname_() {
#else
intf->hostname = wifi_station_get_hostname();
#endif
if (netif_dhcp_data(intf) != nullptr && netif_is_link_up(intf)) {
// Renew already started DHCP leases to inform server of hostname change.
// Only attempt when the interface has link — calling dhcp_renew() without
// an active connection corrupts lwIP's DHCP state machine (it unconditionally
// sets state to RENEWING before attempting to send, and never rolls back on
// failure). This causes dhcp_network_changed() to call dhcp_reboot() instead
// of dhcp_discover() when WiFi later connects, sending a bogus DHCP REQUEST
struct dhcp *dhcp_data = netif_dhcp_data(intf);
if (dhcp_data != nullptr && dhcp_data->state == DHCP_STATE_BOUND) {
// Renew already-bound DHCP leases to inform server of hostname change.
// Only attempt when DHCP is BOUND — calling dhcp_renew() in any other
// state corrupts lwIP's DHCP state machine (it unconditionally sets state
// to RENEWING before attempting to send, and never rolls back on failure).
// This causes dhcp_network_changed() to call dhcp_reboot() instead of
// dhcp_discover() when WiFi later connects, sending a bogus DHCP REQUEST
// for IP 0.0.0.0 that can put some routers into a persistent bad state.
err_t lwipret = dhcp_renew(intf);
if (lwipret != ERR_OK) {