From f7705c85892f32366eb1906969119a2464c9a943 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 14 Feb 2026 05:22:39 -0700 Subject: [PATCH] =?UTF-8?q?[wifi]=20Remove=20dhcp=5Frenew()=20entirely=20?= =?UTF-8?q?=E2=80=94=20it=20can=20never=20run=20usefully?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dhcp_renew() loop was cargo-culted from Arduino ESP8266's WiFi.hostname() which was designed for changing the hostname on an already-connected system with multiple interfaces (WiFi+Ethernet). In ESPHome, wifi_apply_hostname_() is only called from: - setup_() — before WiFi connects (link never up) - wifi_sta_connect_() — after wifi_disconnect_() (link always down) The hostname is fixed at compile time and never changes at runtime. Setting intf->hostname is sufficient — lwIP automatically includes it in DHCP DISCOVER/REQUEST packets via LWIP_NETIF_HOSTNAME. Co-Authored-By: Claude Opus 4.6 --- .../wifi/wifi_component_esp8266.cpp | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 4e94f86ef53..6f8decc0ae7 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -16,8 +16,7 @@ extern "C" { #include "lwip/err.h" #include "lwip/dns.h" #include "lwip/dhcp.h" -#include "lwip/prot/dhcp.h" // DHCP_STATE_BOUND -#include "lwip/init.h" // LWIP_VERSION_ +#include "lwip/init.h" // LWIP_VERSION_ #include "lwip/apps/sntp.h" #include "lwip/netif.h" // struct netif #include @@ -217,34 +216,17 @@ bool WiFiComponent::wifi_apply_hostname_() { ESP_LOGV(TAG, "Set hostname failed"); } - // inform dhcp server of hostname change using dhcp_renew() + // Update hostname on all lwIP interfaces so DHCP packets include it. + // No dhcp_renew() call here — the hostname is fixed at compile time and + // this function is only called during setup() or wifi_sta_connect_() when + // the interface is always disconnected. lwIP includes the hostname in + // DHCP DISCOVER/REQUEST automatically via LWIP_NETIF_HOSTNAME. for (netif *intf = netif_list; intf; intf = intf->next) { - // unconditionally update all known interfaces #if LWIP_VERSION_MAJOR == 1 intf->hostname = (char *) wifi_station_get_hostname(); #else intf->hostname = wifi_station_get_hostname(); #endif - struct dhcp *dhcp_data = netif_dhcp_data(intf); - if (dhcp_data != nullptr && dhcp_data->state == DHCP_STATE_BOUND && netif_is_link_up(intf)) { - // Renew already-bound DHCP leases to inform server of hostname change. - // Both conditions are required: - // - DHCP must be BOUND (have an active lease to renew) - // - Interface must have link (able to send packets) - // During reconnection, DHCP can remain BOUND from a previous connection - // while the link is down. Calling dhcp_renew() without link 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) { - ESP_LOGW(TAG, "wifi_apply_hostname_(%s): lwIP error %d on interface %c%c (index %d)", intf->hostname, - (int) lwipret, intf->name[0], intf->name[1], intf->num); - ret = false; - } - } } return ret;