[wifi] Fix ESP8266 crash in cnx_node_search when lwIP transmits after disconnect (#18333)

This commit is contained in:
J. Nick Koston
2026-08-13 13:30:53 -05:00
committed by GitHub
parent 137351fa8d
commit 191686c5b3
@@ -136,10 +136,21 @@ bool WiFiComponent::wifi_apply_power_save_() {
https://github.com/d-a-v/Arduino/blob/0e7d21e17144cfc5f53c016191daca8723e89ee8/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L251 https://github.com/d-a-v/Arduino/blob/0e7d21e17144cfc5f53c016191daca8723e89ee8/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L251
*/ */
#undef netif_set_addr // need to call lwIP-v1.4 netif_set_addr() #undef netif_set_addr // need to call lwIP-v1.4 netif_set_addr()
#undef netif_set_down // need to call lwIP-v1.4 netif_set_down()
extern "C" { extern "C" {
struct netif *eagle_lwip_getif(int netif_index); struct netif *eagle_lwip_getif(int netif_index);
void netif_set_addr(struct netif *netif, const ip4_addr_t *ip, const ip4_addr_t *netmask, const ip4_addr_t *gw); void netif_set_addr(struct netif *netif, const ip4_addr_t *ip, const ip4_addr_t *netmask, const ip4_addr_t *gw);
void netif_set_down(struct netif *netif);
}; };
// The SDK can free its WiFi connection node before taking the STA netif down, letting lwIP
// timers (e.g. IGMP reports armed by mDNS) transmit into the dead driver and crash in
// cnx_node_search; taking the netif down first makes the glue drop such frames (#18308).
static void sta_netif_down() {
struct netif *iface = eagle_lwip_getif(STATION_IF);
if (iface != nullptr)
netif_set_down(iface);
}
#endif #endif
bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) { bool WiFiComponent::wifi_sta_ip_config_(const optional<ManualIP> &manual_ip) {
@@ -523,6 +534,9 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_FAILED); global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_FAILED);
} }
global_wifi_component->error_from_callback_ = true; global_wifi_component->error_from_callback_ = true;
#if LWIP_VERSION_MAJOR != 1
sta_netif_down();
#endif
#ifdef USE_WIFI_CONNECT_STATE_LISTENERS #ifdef USE_WIFI_CONNECT_STATE_LISTENERS
global_wifi_component->pending_.disconnect = true; global_wifi_component->pending_.disconnect = true;
#endif #endif
@@ -536,6 +550,9 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) {
// https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors // https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors
if (it.old_mode != AUTH_OPEN && it.new_mode == AUTH_OPEN) { if (it.old_mode != AUTH_OPEN && it.new_mode == AUTH_OPEN) {
ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting"); ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting");
#if LWIP_VERSION_MAJOR != 1
sta_netif_down();
#endif
wifi_station_disconnect(); wifi_station_disconnect();
global_wifi_component->error_from_callback_ = true; global_wifi_component->error_from_callback_ = true;
} }
@@ -719,8 +736,12 @@ bool WiFiComponent::wifi_scan_start_(bool passive) {
bool WiFiComponent::wifi_disconnect_() { bool WiFiComponent::wifi_disconnect_() {
bool ret = true; bool ret = true;
// Only call disconnect if interface is up // Only call disconnect if interface is up
if (wifi_get_opmode() & WIFI_STA) if (wifi_get_opmode() & WIFI_STA) {
#if LWIP_VERSION_MAJOR != 1
sta_netif_down();
#endif
ret = wifi_station_disconnect(); ret = wifi_station_disconnect();
}
station_config conf{}; station_config conf{};
memset(&conf, 0, sizeof(conf)); memset(&conf, 0, sizeof(conf));
ETS_UART_INTR_DISABLE(); ETS_UART_INTR_DISABLE();