diff --git a/components/esp_wifi/CMakeLists.txt b/components/esp_wifi/CMakeLists.txt index 02b0c411e7b..7743744f0da 100644 --- a/components/esp_wifi/CMakeLists.txt +++ b/components/esp_wifi/CMakeLists.txt @@ -67,7 +67,7 @@ idf_component_register(SRCS "${srcs}" PRIV_REQUIRES driver esptool_py esp_pm esp_timer nvs_flash wpa_supplicant hal lwip esp_coex ${extra_priv_requires} PRIV_INCLUDE_DIRS ../wpa_supplicant/src/ ../wpa_supplicant/esp_supplicant/src/ - wifi_apps/roaming_app/include + wifi_apps/roaming_app/include wifi_apps/roaming_app/src LDFRAGMENTS "${ldfragments}") if(CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_HOST_WIFI_ENABLED) diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 8d23390e814..74933a73fd7 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -181,8 +181,9 @@ static esp_err_t wifi_deinit_internal(void) esp_supplicant_deinit(); -#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP - roam_deinit_app(); +#if CONFIG_ESP_WIFI_SLP_SAMPLE_BEACON_FEATURE + wifi_beacon_offset_config_t offset_config = WIFI_BEACON_OFFSET_CONFIG_DEFAULT(false); + esp_wifi_beacon_offset_configure(&offset_config); #endif err = esp_wifi_deinit_internal(); @@ -446,10 +447,6 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) goto _deinit; } -#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP - roam_init_app(); -#endif - } else { goto _deinit; } diff --git a/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h b/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h index 6ed20ce949d..28ccb7a79e1 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h +++ b/components/esp_wifi/wifi_apps/roaming_app/include/esp_roaming.h @@ -16,9 +16,11 @@ struct roam_config { int8_t low_rssi_threshold; uint8_t rssi_threshold_reduction_offset; bool scan_monitor; +#if CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR uint8_t scan_interval; int8_t scan_rssi_threshold; uint8_t scan_rssi_diff; +#endif bool legacy_roam_enabled; uint8_t btm_retry_cnt; bool btm_roaming_enabled; @@ -37,6 +39,10 @@ void roam_sta_disconnected(void *disconn); esp_err_t roam_get_config_params(struct roam_config *config); esp_err_t roam_set_config_params(struct roam_config *config); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP +void esp_wifi_roaming_set_current_bssid(const uint8_t *bssid); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming b/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming index 22f641377d7..57bc23649a5 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming +++ b/components/esp_wifi/wifi_apps/roaming_app/src/Kconfig.roaming @@ -73,7 +73,7 @@ menu "Roaming Methods" config ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM bool "Support Network Assisted roaming using 802.11v" depends on ESP_WIFI_WNM_SUPPORT - default n + default y help Roaming between APs using network assisted Roaming. This involves BSS Transition Management mechanisms outlined in 802.11v. @@ -139,13 +139,7 @@ menu "Scan Configuration" Duration for which the results from the most recent scans can be used by the roaming app for determining the roaming candidates. - config ESP_WIFI_ROAMING_MAX_CANDIDATES - int "Max Candidates in the network" - default 3 - range 3 20 - help - Max candidates that can be considered while scanning as a part of the - network at one time. + endmenu #"Scan Configuration" @@ -160,7 +154,7 @@ config ESP_WIFI_ROAMING_BACKOFF_TIME config ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING bool "Send periodic neighbor report request to AP for internal list updation" depends on ESP_WIFI_RRM_SUPPORT - default y + default n help This option will enable station to keep sending RRM neighbor list request to AP and update its internal list. @@ -182,3 +176,50 @@ config ESP_WIFI_ROAMING_RRM_MONITOR_THRESHOLD range -99 0 help The RSSI threshold beyond which we start sending periodic neighbor report requests. + +menu "Blacklist Configuration" + config ESP_WIFI_ROAMING_BSSID_BLACKLIST + bool "Enable BSSID blacklisting" + default n + help + Enable this to blacklist BSSIDs. + + config ESP_WIFI_ROAMING_AUTO_BLACKLISTING + bool "Enable automatic BSSID blacklisting" + depends on ESP_WIFI_ROAMING_BSSID_BLACKLIST + help + Enable this to automatically blacklist BSSIDs after multiple failed connection attempts. + + config ESP_WIFI_ROAMING_MAX_CONN_FAILURES + int "Maximum connection failures" + depends on ESP_WIFI_ROAMING_AUTO_BLACKLISTING + range 1 10 + default 3 + help + Maximum number of connection failures before a BSSID is blacklisted. + + config ESP_WIFI_ROAMING_BLACKLIST_TIMEOUT + int "Blacklist timeout (in seconds)" + depends on ESP_WIFI_ROAMING_BSSID_BLACKLIST + range 10 3600 + default 300 + help + Time in seconds for which a BSSID remains in the blacklist. + This applies to both automatically and manually blacklisted BSSIDs. + + config ESP_WIFI_ROAMING_MAX_CANDIDATES + int "Maximum number of roaming candidates" + range 1 10 + default 5 + help + Maximum number of roaming candidates to consider. This also defines the size of the blacklist. + + config ESP_WIFI_ROAMING_PREVENT_DOWNGRADE + bool "Prevent security downgrade when roaming" + default n + help + If the currently connected AP sends a "transition disable" bit, + this option will make the roaming logic ignore less secure APs. + This helps prevent security downgrades when roaming in a mixed + security environment (e.g., WPA2/WPA3). +endmenu # "Blacklist Configuration" diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h b/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h index 9ca515e6afe..29d3effc5b3 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h +++ b/components/esp_wifi/wifi_apps/roaming_app/src/esp_roaming_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,12 +22,18 @@ extern "C" { #define ROAMING_BACKOFF_TIME CONFIG_ESP_WIFI_ROAMING_BACKOFF_TIME /* Low RSSI based roaming configuration */ +#ifndef CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING +#define CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING 0 +#endif #define LOW_RSSI_ROAMING_ENABLED CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_ROAMING #if LOW_RSSI_ROAMING_ENABLED #define ROAMING_LOW_RSSI_THRESHOLD CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD #define RSSI_THRESHOLD_REDUCTION_OFFSET CONFIG_ESP_WIFI_ROAMING_LOW_RSSI_OFFSET #endif /*LOW_RSSI_ROAMING_ENABLED*/ +#ifndef CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR +#define CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR 0 +#endif /* Periodic Scan based Roaming configuration */ #define PERIODIC_SCAN_MONITORING CONFIG_ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR #if PERIODIC_SCAN_MONITORING @@ -134,6 +140,16 @@ struct roaming_app { #endif #if PERIODIC_SCAN_MONITORING bool periodic_scan_active; +#endif +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + struct blacklist_entry { + uint8_t bssid[ETH_ALEN]; +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + uint8_t failures; +#endif + struct timeval timestamp; + } bssid_blacklist[CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES]; + uint8_t bssid_blacklist_count; #endif bool allow_reconnect; }; diff --git a/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c b/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c index 20dcc083663..1256ea4c0a6 100644 --- a/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c +++ b/components/esp_wifi/wifi_apps/roaming_app/src/roaming_app.c @@ -28,22 +28,17 @@ #include "utils/eloop.h" #include "rom/ets_sys.h" #include "common/ieee802_11_defs.h" -static struct roaming_app g_roaming_app; +#include "common/wpa_common.h" +#include "esp_wpas_glue.h" + +struct roaming_app g_roaming_app; typedef void (* scan_done_cb_t)(void *arg, ETS_STATUS status); extern int esp_wifi_promiscuous_scan_start(wifi_scan_config_t *config, scan_done_cb_t cb); -static void *scan_results_lock = NULL; -#define ROAM_SCAN_RESULTS_LOCK() os_mutex_lock(scan_results_lock) -#define ROAM_SCAN_RESULTS_UNLOCK() os_mutex_unlock(scan_results_lock) - -#if PERIODIC_RRM_MONITORING -static void *neighbor_list_lock = NULL; -#define ROAM_NEIGHBOR_LIST_LOCK() os_mutex_lock(neighbor_list_lock) -#define ROAM_NEIGHBOR_LIST_UNLOCK() os_mutex_unlock(neighbor_list_lock) -#endif /*PERIODIC_RRM_MONITORING*/ static int wifi_post_roam_event(struct cand_bss *bss); static void determine_best_ap(int8_t rssi_threshold); +static bool is_bssid_blacklisted(const uint8_t *bssid); #if PERIODIC_RRM_MONITORING static void roaming_app_periodic_rrm_internal_handler(void *data, void *ctx); #endif @@ -53,6 +48,13 @@ static void roaming_app_periodic_scan_internal_handler(void *data, void *ctx); static const char *ROAMING_TAG = "ROAM"; +void esp_wifi_roaming_set_current_bssid(const uint8_t *bssid) +{ + if (bssid) { + memcpy(g_roaming_app.current_bss.ap.bssid, bssid, ETH_ALEN); + } +} + static inline long time_diff_sec(struct timeval *a, struct timeval *b) { return (a->tv_sec - b->tv_sec); @@ -139,12 +141,6 @@ static void init_periodic_rrm_event(void) ESP_LOGI(ROAMING_TAG, "RRM monitor is disabled in config"); return; } - if (!neighbor_list_lock) { - neighbor_list_lock = os_recursive_mutex_create(); - if (!neighbor_list_lock) { - ESP_LOGE(ROAMING_TAG, "%s: failed to create roaming neighbor list lock", __func__); - } - } ESP_LOGV(ROAMING_TAG, "Initialised Periodic RRM Monitoring event!"); g_roaming_app.periodic_rrm_active = true; if (eloop_register_timeout(g_roaming_app.config.rrm_monitor_time, 0, roaming_app_periodic_rrm_internal_handler, NULL, NULL)) { @@ -179,23 +175,77 @@ static void roaming_app_disconnected_event_handler(void *ctx, void *data) #endif /*PERIODIC_SCAN_MONITORING*/ wifi_event_sta_disconnected_t *disconn = data; - ESP_LOGD(ROAMING_TAG, "station got disconnected reason=%d", disconn->reason); +#define RSSI_INVALID -128 + g_roaming_app.current_bss.ap.rssi = RSSI_INVALID; +#undef RSSI_INVALID + + ESP_LOGD(ROAMING_TAG, "station got disconnected reason=%d, rssi =%d", disconn->reason, disconn->rssi); +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + if (disconn->reason == WIFI_REASON_CONNECTION_FAIL || disconn->reason == WIFI_REASON_AUTH_FAIL) { + bool found = false; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN) == 0) { + g_roaming_app.bssid_blacklist[i].failures++; + gettimeofday(&g_roaming_app.bssid_blacklist[i].timestamp, NULL); + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " connection failures: %d", MAC2STR(g_roaming_app.current_bss.ap.bssid), g_roaming_app.bssid_blacklist[i].failures); + if (g_roaming_app.bssid_blacklist[i].failures >= CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES) { + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " blacklisted", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + /* The BSSID is now blacklisted. The logic later in this function + * will check the blacklist and trigger a scan for a new AP + * instead of trying to reconnect to this one. */ + } + found = true; + break; + } + } + if (!found) { + if (g_roaming_app.bssid_blacklist_count < CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES) { + memcpy(g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN); + g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].failures = 1; + gettimeofday(&g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].timestamp, NULL); + g_roaming_app.bssid_blacklist_count++; + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " added to blacklist tracking", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + } else { + int oldest_idx = 0; + for (int i = 1; i < g_roaming_app.bssid_blacklist_count; i++) { + if (g_roaming_app.bssid_blacklist[i].timestamp.tv_sec < g_roaming_app.bssid_blacklist[oldest_idx].timestamp.tv_sec) { + oldest_idx = i; + } + } + ESP_LOGD(ROAMING_TAG, "Blacklist is full. Replacing oldest entry for " MACSTR, MAC2STR(g_roaming_app.bssid_blacklist[oldest_idx].bssid)); + memcpy(g_roaming_app.bssid_blacklist[oldest_idx].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN); + g_roaming_app.bssid_blacklist[oldest_idx].failures = 1; + gettimeofday(&g_roaming_app.bssid_blacklist[oldest_idx].timestamp, NULL); + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " added to blacklist tracking", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + } + } + } +#endif if (disconn->reason == WIFI_REASON_ROAMING) { ESP_LOGD(ROAMING_TAG, "station roaming, do nothing"); } else if (g_roaming_app.allow_reconnect == false) { ESP_LOGD(ROAMING_TAG, "station initiated disconnect, do nothing"); } else { +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + if (is_bssid_blacklisted(g_roaming_app.current_bss.ap.bssid)) { + ESP_LOGD(ROAMING_TAG, "AP " MACSTR " is blacklisted, finding another AP", MAC2STR(g_roaming_app.current_bss.ap.bssid)); + determine_best_ap(0); + } else { +#endif #if LEGACY_ROAM_ENABLED - /* - * Resetting the Bssid param as it is possible that a previous force - * roam has set config to connect to a specific bssid and now further - * roaming attempts using BTM could lead to a spiral of connecting to - * the previous AP */ - if (g_roaming_app.force_roam_ongoing) { - legacy_roam_clear_bssid_flag(); - } + /* + * Resetting the Bssid param as it is possible that a previous force + * roam has set config to connect to a specific bssid and now further + * roaming attempts using BTM could lead to a spiral of connecting to + * the previous AP */ + if (g_roaming_app.force_roam_ongoing) { + legacy_roam_clear_bssid_flag(); + } #endif /*LEGACY_ROAM_ENABLED*/ - esp_wifi_connect(); + esp_wifi_connect(); +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + } +#endif } os_free(disconn); } @@ -357,26 +407,27 @@ cleanup: } return buf; } -static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) + +static void roaming_app_neighbor_report_recv_internal_handler(void *ctx, void *data) { + wifi_event_neighbor_report_t *neighbor_report_event = data; if (!g_roaming_app.rrm_request_active) { ESP_LOGV(ROAMING_TAG, "Not the response for our Neighbor Report Request"); - return; + goto cleanup; } g_roaming_app.rrm_request_active = false; - if (!event_data) { + if (!neighbor_report_event) { ESP_LOGE(ROAMING_TAG, "No data received for neighbor report"); - return; + goto cleanup; } - wifi_event_neighbor_report_t *neighbor_report_event = (wifi_event_neighbor_report_t*)event_data; ESP_LOGD(ROAMING_TAG, "Received cb for Neighbor Report Request"); uint8_t *pos = (uint8_t *)neighbor_report_event->report; if (!pos) { ESP_LOGE(ROAMING_TAG, "Neighbor report is empty"); - return; + goto cleanup; } uint8_t report_len = neighbor_report_event->report_len; @@ -384,22 +435,42 @@ static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t ESP_LOGD(ROAMING_TAG, "rrm: neighbor report len=%d", report_len); ESP_LOG_BUFFER_HEXDUMP(ROAMING_TAG, pos, report_len, ESP_LOG_DEBUG); - ROAM_NEIGHBOR_LIST_LOCK(); if (g_roaming_app.btm_neighbor_list) { os_free(g_roaming_app.btm_neighbor_list); g_roaming_app.btm_neighbor_list = NULL; } /* create neighbor list */ g_roaming_app.btm_neighbor_list = get_btm_neighbor_list(pos + 1, report_len - 1); - ROAM_NEIGHBOR_LIST_UNLOCK(); +cleanup: + if (neighbor_report_event) { + os_free(neighbor_report_event); + } +} + +static void roaming_app_neighbor_report_recv_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + wifi_event_neighbor_report_t *event = (wifi_event_neighbor_report_t*)event_data; + if (!event) { + return; + } + wifi_event_neighbor_report_t *event_copy = os_malloc(sizeof(wifi_event_neighbor_report_t) + event->report_len); + if (!event_copy) { + ESP_LOGE(ROAMING_TAG, "Failed to allocate memory for neighbor report event"); + return; + } + memcpy(event_copy, event, sizeof(wifi_event_neighbor_report_t) + event->report_len); + + if (eloop_register_timeout(0, 0, roaming_app_neighbor_report_recv_internal_handler, NULL, event_copy) != 0) { + os_free(event_copy); + } } #endif /*PERIODIC_RRM_MONITORING*/ #if LOW_RSSI_ROAMING_ENABLED -static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +static void roaming_app_rssi_low_internal_handler(void *ctx, void *data) { - wifi_event_bss_rssi_low_t *event = event_data; + wifi_event_bss_rssi_low_t *event = data; ESP_LOGI(ROAMING_TAG, "%s:bss rssi is=%ld", __func__, event->rssi); roaming_app_get_ap_info(&g_roaming_app.current_bss.ap); @@ -408,25 +479,34 @@ static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, ESP_LOGD(ROAMING_TAG, "Resetting RSSI Threshold to %d", g_roaming_app.current_low_rssi_threshold); esp_wifi_set_rssi_threshold(g_roaming_app.current_low_rssi_threshold); + os_free(event); +} + +static void roaming_app_rssi_low_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + wifi_event_bss_rssi_low_t *event = event_data; + if (!event) { + return; + } + wifi_event_bss_rssi_low_t *event_copy = os_malloc(sizeof(wifi_event_bss_rssi_low_t)); + if (!event_copy) { + ESP_LOGE(ROAMING_TAG, "Failed to allocate memory for rssi low event"); + return; + } + memcpy(event_copy, event, sizeof(wifi_event_bss_rssi_low_t)); + + if (eloop_register_timeout(0, 0, roaming_app_rssi_low_internal_handler, NULL, event_copy) != 0) { + os_free(event_copy); + } } #endif #if NETWORK_ASSISTED_ROAMING_ENABLED static void trigger_network_assisted_roam(void) { -#if PERIODIC_RRM_MONITORING - if (g_roaming_app.current_bss.rrm_support) { - ROAM_NEIGHBOR_LIST_LOCK(); - } -#endif /*PERIODIC_RRM_MONITORING*/ if (esp_wnm_send_bss_transition_mgmt_query(REASON_RSSI, g_roaming_app.btm_neighbor_list, 1) < 0) { ESP_LOGD(ROAMING_TAG, "failed to send btm query"); } -#if PERIODIC_RRM_MONITORING - if (g_roaming_app.current_bss.rrm_support) { - ROAM_NEIGHBOR_LIST_UNLOCK(); - } -#endif /*PERIODIC_RRM_MONITORING*/ ESP_LOGD(ROAMING_TAG, "Sent BTM Query"); gettimeofday(&g_roaming_app.last_roamed_time, NULL); #if LEGACY_ROAM_ENABLED @@ -444,6 +524,7 @@ static void trigger_legacy_roam(struct cand_bss *bss) wifi_cfg.sta.bssid_set = true; os_memcpy(wifi_cfg.sta.bssid, bss->bssid, ETH_ALEN); esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); + esp_wifi_roaming_set_current_bssid(bss->bssid); esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); esp_wifi_connect(); ESP_LOGI(ROAMING_TAG, "Disconnecting and connecting to "MACSTR" on account of better rssi",MAC2STR(bss->bssid)); @@ -458,7 +539,7 @@ void roaming_app_trigger_roam(struct cand_bss *bss) gettimeofday(&now, NULL); ESP_LOGD(ROAMING_TAG,"Processing trigger roaming request."); if (time_diff_sec(&now, &g_roaming_app.last_roamed_time) < g_roaming_app.config.backoff_time ) { - ESP_LOGD(ROAMING_TAG,"Ignoring request as time difference to last request is %ld",time_diff_sec(&now, &g_roaming_app.last_roamed_time)); + ESP_LOGD(ROAMING_TAG,"Ignoring request as time difference to last request is %ld",time_diff_sec(&now, &g_roaming_app.last_roamed_time)); goto free_bss; } #if NETWORK_ASSISTED_ROAMING_ENABLED @@ -492,7 +573,6 @@ void roaming_app_trigger_roam_internal_handler(void *ctx, void *data) } else { roaming_app_trigger_roam((struct cand_bss *)data); } - } static int wifi_post_roam_event(struct cand_bss *bss) @@ -529,7 +609,6 @@ void print_ap_records(struct scanned_ap_info *ap_info) } - #if PERIODIC_RRM_MONITORING static void periodic_rrm_request(struct timeval *now) { @@ -546,6 +625,31 @@ static void periodic_rrm_request(struct timeval *now) static bool candidate_security_match(wifi_ap_record_t candidate) { +#if CONFIG_ESP_WIFI_ROAMING_PREVENT_DOWNGRADE + u8 transition_disable = wpa_supplicant_get_transition_disable(); + if (transition_disable & TRANSITION_DISABLE_WPA3_PERSONAL) { + if (candidate.authmode == WIFI_AUTH_WPA2_PSK) { + return false; + } + } + if (transition_disable & TRANSITION_DISABLE_ENHANCED_OPEN) { + if (candidate.authmode == WIFI_AUTH_OPEN) { + return false; + } + } + if (transition_disable & TRANSITION_DISABLE_WPA3_ENTERPRISE) { + if (candidate.authmode == WIFI_AUTH_WPA2_ENTERPRISE) { + return false; + } + } +#if TODO // application doesn't have a way to know SAE-PK enabled AP atm + if (transition_disable & TRANSITION_DISABLE_SAE_PK) { + if (candidate.authmode == WIFI_AUTH_WPA3_PSK) { + return false; + } + } +#endif +#endif wifi_auth_mode_t curr_auth = g_roaming_app.current_bss.ap.authmode; wifi_auth_mode_t cand_auth = candidate.authmode; ESP_LOGV(ROAMING_TAG, "Cand authmode : %d, Current Authmode : %d", cand_auth, curr_auth); @@ -556,9 +660,6 @@ static bool candidate_security_match(wifi_ap_record_t candidate) wifi_config_t wifi_cfg = {0}; esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); if (wifi_cfg.sta.owe_enabled && OWE_COMPATIBLE(curr_auth, cand_auth)) { - /* - * OWE <--> Open allowed if threshold is Open - */ if (wifi_cfg.sta.threshold.authmode == WIFI_AUTH_OPEN) { ESP_LOGV(ROAMING_TAG, "transition between OWE and open permitted"); return true; @@ -568,7 +669,7 @@ static bool candidate_security_match(wifi_ap_record_t candidate) } } else if (wifi_cfg.sta.threshold.authmode > cand_auth) { /* If the authmode of the candidate AP is less than our threshold, it - * will fail during connection*/ + * will fail during connection */ ESP_LOGV(ROAMING_TAG, "Authmode threshold failure %d -> %d", wifi_cfg.sta.threshold.authmode, cand_auth); return false; } else if (PSK_COMPATIBLE(curr_auth, cand_auth)) { @@ -581,11 +682,45 @@ static bool candidate_security_match(wifi_ap_record_t candidate) return false; } -static bool candidate_profile_match(wifi_ap_record_t candidate) +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST +static void remove_expired_blacklist_entries(void) { - return candidate_security_match(candidate); + struct timeval now; + gettimeofday(&now, NULL); + int j = 0; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (time_diff_sec(&now, &g_roaming_app.bssid_blacklist[i].timestamp) <= CONFIG_ESP_WIFI_ROAMING_BLACKLIST_TIMEOUT) { + if (i != j) { + g_roaming_app.bssid_blacklist[j] = g_roaming_app.bssid_blacklist[i]; + } + j++; + } else { + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " removed from blacklist due to timeout", MAC2STR(g_roaming_app.bssid_blacklist[i].bssid)); + } + } + g_roaming_app.bssid_blacklist_count = j; } -/* Remember to always call this function with the ROAM_SCAN_RESULTS_LOCK */ +#endif + +static bool is_bssid_blacklisted(const uint8_t *bssid) +{ +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST + remove_expired_blacklist_entries(); + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + if (g_roaming_app.bssid_blacklist[i].failures >= CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES) { + return true; + } +#else + return true; +#endif + } + } +#endif + return false; +} + static void parse_scan_results_and_roam(void) { int8_t rssi_threshold = g_roaming_app.current_rssi_threshold; @@ -594,16 +729,18 @@ static void parse_scan_results_and_roam(void) int8_t rssi_diff = 0; uint8_t i; int8_t best_ap_index = -1; - wifi_ap_record_t ap_info; - roaming_app_get_ap_info(&ap_info); for (i = 0; i < g_roaming_app.scanned_aps.current_count; i++) { - rssi_diff = g_roaming_app.scanned_aps.ap_records[i].rssi - ap_info.rssi; + if (is_bssid_blacklisted(g_roaming_app.scanned_aps.ap_records[i].bssid)) { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " is blacklisted, skipping", MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid)); + continue; + } + rssi_diff = g_roaming_app.scanned_aps.ap_records[i].rssi - g_roaming_app.current_bss.ap.rssi; ESP_LOGD(ROAMING_TAG, "The difference between ("MACSTR", "MACSTR") with rssi (%d,%d) is : %d while the threshold is %d and the best rssi diff yet is %d, thecand_auth is %d", - MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid),MAC2STR(ap_info.bssid), - g_roaming_app.scanned_aps.ap_records[i].rssi, ap_info.rssi, + MAC2STR(g_roaming_app.scanned_aps.ap_records[i].bssid),MAC2STR(g_roaming_app.current_bss.ap.bssid), + g_roaming_app.scanned_aps.ap_records[i].rssi, g_roaming_app.current_bss.ap.rssi, rssi_diff, rssi_threshold, best_rssi_diff, g_roaming_app.scanned_aps.ap_records[i].authmode); - if ((memcmp(g_roaming_app.scanned_aps.ap_records[i].bssid, ap_info.bssid, ETH_ALEN) != 0) && - candidate_profile_match(g_roaming_app.scanned_aps.ap_records[i]) && rssi_diff > best_rssi_diff ) { + if ((memcmp(g_roaming_app.scanned_aps.ap_records[i].bssid, g_roaming_app.current_bss.ap.bssid, ETH_ALEN) != 0) && + candidate_security_match(g_roaming_app.scanned_aps.ap_records[i]) && rssi_diff > best_rssi_diff ) { best_rssi_diff = rssi_diff; best_ap_index = i; } @@ -632,44 +769,41 @@ static void parse_scan_results_and_roam(void) static void scan_done_event_handler(void *arg, ETS_STATUS status) { if (status == ETS_OK) { - ROAM_SCAN_RESULTS_LOCK(); ESP_LOGD(ROAMING_TAG, "Scan Done properly"); g_roaming_app.scanned_aps.current_count = MAX_CANDIDATE_COUNT; esp_wifi_scan_get_ap_records(&g_roaming_app.scanned_aps.current_count, g_roaming_app.scanned_aps.ap_records); print_ap_records(&g_roaming_app.scanned_aps); parse_scan_results_and_roam(); - ROAM_SCAN_RESULTS_UNLOCK(); } else { ESP_LOGD(ROAMING_TAG, "Scan Done with error %d ", status); } - ROAM_SCAN_RESULTS_LOCK(); g_roaming_app.scan_ongoing = false; - ROAM_SCAN_RESULTS_UNLOCK(); } -static void conduct_scan(void) +static bool conduct_scan(void) { - /* Update scan time in global structure */ gettimeofday(&g_roaming_app.scanned_aps.time, NULL); - /* Issue scan */ os_memset(&g_roaming_app.scanned_aps, 0, sizeof(struct scanned_ap_info)); + /* Issue scan */ if (esp_wifi_promiscuous_scan_start(&g_roaming_app.config.scan_config, scan_done_event_handler) < 0) { ESP_LOGE(ROAMING_TAG, "failed to issue scan"); - return; + return false; } ESP_LOGI(ROAMING_TAG, "Issued Scan"); + return true; } static void determine_best_ap(int8_t rssi_threshold) { struct timeval now; gettimeofday(&now, NULL); - ROAM_SCAN_RESULTS_LOCK(); /* If the scan results are recent enough or a scan is already ongoing we should not trigger a new scan */ if (!g_roaming_app.scan_ongoing) { g_roaming_app.scan_ongoing = true; g_roaming_app.current_rssi_threshold = rssi_threshold; if (time_diff_sec(&now,&g_roaming_app.scanned_aps.time) > SCAN_RESULTS_USABILITY_WINDOW) { - conduct_scan(); + if (!conduct_scan()) { + g_roaming_app.scan_ongoing = false; + } } else { parse_scan_results_and_roam(); g_roaming_app.scan_ongoing = false; @@ -677,7 +811,6 @@ static void determine_best_ap(int8_t rssi_threshold) } else if(rssi_threshold < g_roaming_app.current_rssi_threshold) { g_roaming_app.current_rssi_threshold = rssi_threshold; } - ROAM_SCAN_RESULTS_UNLOCK(); } #if PERIODIC_SCAN_MONITORING static void periodic_scan_roam(struct timeval *now) @@ -780,6 +913,7 @@ static int8_t parse_scan_chan_list(void) { int8_t ret = 0; char *scan_chan_string = NULL; + char *scan_chan_string_p = NULL; if (validate_scan_chan_list(SCAN_PREFERRED_CHAN_LIST) == false) { ESP_LOGE(ROAMING_TAG, "scan chan list validation failed."); ret = -1; @@ -793,22 +927,27 @@ static int8_t parse_scan_chan_list(void) } strlcpy(scan_chan_string, SCAN_PREFERRED_CHAN_LIST, strlen(SCAN_PREFERRED_CHAN_LIST) + 1); char* token; - token = strsep(&scan_chan_string, ","); + scan_chan_string_p = scan_chan_string; + token = strsep(&scan_chan_string_p, ","); g_roaming_app.config.scan_config.channel_bitmap.ghz_2_channels = 0; + g_roaming_app.config.scan_config.channel_bitmap.ghz_5_channels = 0; while (token != NULL) { uint8_t channel = atoi(token); /* Check if the number is within the required range */ if (channel >= 1 && channel <= 14) { - /* Check if the number is already present in the array */ g_roaming_app.config.scan_config.channel_bitmap.ghz_2_channels |= (1 << channel); +#if CONFIG_SOC_WIFI_SUPPORT_5G + } else if (channel >= 36 && channel <= 177) { + g_roaming_app.config.scan_config.channel_bitmap.ghz_5_channels |= CHANNEL_TO_BIT(channel); +#endif } else { ESP_LOGE(ROAMING_TAG, "Channel out of range: %d", channel); ret = -1; goto cleanup; } - token = strsep(&scan_chan_string, ","); + token = strsep(&scan_chan_string_p, ","); } cleanup: @@ -818,7 +957,6 @@ cleanup: return ret; } - static esp_err_t init_config_params(void) { g_roaming_app.config.backoff_time = ROAMING_BACKOFF_TIME; @@ -828,9 +966,11 @@ static esp_err_t init_config_params(void) g_roaming_app.config.rssi_threshold_reduction_offset = RSSI_THRESHOLD_REDUCTION_OFFSET; g_roaming_app.config.scan_monitor = PERIODIC_SCAN_MONITORING; +#if PERIODIC_SCAN_MONITORING g_roaming_app.config.scan_interval = SCAN_MONITOR_INTERVAL; g_roaming_app.config.scan_rssi_threshold = SCAN_MONITOR_RSSI_THRESHOLD; g_roaming_app.config.scan_rssi_diff = SCAN_ROAM_RSSI_DIFF; +#endif /* PERIODIC_SCAN_MONITORING */ g_roaming_app.config.legacy_roam_enabled = LEGACY_ROAM_ENABLED; g_roaming_app.config.btm_retry_cnt = BSS_TM_RETRY_COUNT; @@ -846,9 +986,11 @@ static esp_err_t init_config_params(void) g_roaming_app.config.backoff_time, g_roaming_app.config.low_rssi_roam_trigger, g_roaming_app.config.low_rssi_threshold, g_roaming_app.config.rssi_threshold_reduction_offset); +#if PERIODIC_SCAN_MONITORING ESP_LOGD(ROAMING_TAG, "scan_monitor=%d scan_interval=%d scan_rssi_threshold=%d scan_rssi_diff=%d", g_roaming_app.config.scan_monitor, g_roaming_app.config.scan_interval, g_roaming_app.config.scan_rssi_threshold, g_roaming_app.config.scan_rssi_diff); +#endif /* PERIODIC_SCAN_MONITORING */ ESP_LOGD(ROAMING_TAG, "legacy_roam_enabled=%d, btm_retry_cnt=%d btm_roaming_enabled=%d", g_roaming_app.config.legacy_roam_enabled, @@ -864,14 +1006,6 @@ static esp_err_t init_config_params(void) static esp_err_t init_scan_config(void) { - if (!scan_results_lock) { - scan_results_lock = os_recursive_mutex_create(); - if (!scan_results_lock) { - ESP_LOGE(ROAMING_TAG, "%s: failed to create scan results lock", __func__); - return ESP_FAIL; - } - } - if (strcmp(DEFAULT_PREFERRED_SCAN_CHAN_LIST, SCAN_PREFERRED_CHAN_LIST)) { ESP_ERROR_CHECK(parse_scan_chan_list()); } @@ -895,6 +1029,7 @@ void roam_init_app(void) ESP_LOGE(ROAMING_TAG, "No roaming method enabled. Roaming app cannot be initialized"); return; #endif + memset(&g_roaming_app, 0, sizeof(g_roaming_app)); #if LOW_RSSI_ROAMING_ENABLED ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, &roaming_app_rssi_low_handler, NULL)); @@ -926,23 +1061,107 @@ void roam_deinit_app(void) #if PERIODIC_SCAN_MONITORING g_roaming_app.periodic_scan_active = false; + eloop_cancel_timeout(roaming_app_periodic_scan_internal_handler, NULL, NULL); #endif /*PERIODIC_SCAN_MONITORING*/ #if PERIODIC_RRM_MONITORING ESP_ERROR_CHECK(esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_NEIGHBOR_REP, &roaming_app_neighbor_report_recv_handler)); /* Disabling the periodic scan and RRM events */ g_roaming_app.periodic_rrm_active = false; - if (neighbor_list_lock) { - os_mutex_delete(neighbor_list_lock); - neighbor_list_lock = NULL; + eloop_cancel_timeout(roaming_app_periodic_rrm_internal_handler, NULL, NULL); + if (g_roaming_app.btm_neighbor_list) { + os_free(g_roaming_app.btm_neighbor_list); + g_roaming_app.btm_neighbor_list = NULL; } #endif /*PERIODIC_RRM_MONITORING*/ - if (scan_results_lock) { - os_mutex_delete(scan_results_lock); - scan_results_lock = NULL; - } } +#if CONFIG_ESP_WIFI_ROAMING_BSSID_BLACKLIST +static void roaming_app_blacklist_add_handler(void *ctx, void *data) +{ + uint8_t *bssid = data; + if (g_roaming_app.bssid_blacklist_count >= CONFIG_ESP_WIFI_ROAMING_MAX_CANDIDATES) { + ESP_LOGE(ROAMING_TAG, "Blacklist is full"); + os_free(bssid); + return; + } + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " already in blacklist", MAC2STR(bssid)); + os_free(bssid); + return; // Already blacklisted + } + } + memcpy(g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].bssid, bssid, ETH_ALEN); +#if CONFIG_ESP_WIFI_ROAMING_AUTO_BLACKLISTING + g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].failures = CONFIG_ESP_WIFI_ROAMING_MAX_CONN_FAILURES; +#endif + gettimeofday(&g_roaming_app.bssid_blacklist[g_roaming_app.bssid_blacklist_count].timestamp, NULL); + g_roaming_app.bssid_blacklist_count++; + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " added to blacklist", MAC2STR(bssid)); + os_free(bssid); +} + +esp_err_t esp_wifi_blacklist_add(const uint8_t *bssid) +{ + if (!bssid) { + return ESP_ERR_INVALID_ARG; + } + uint8_t *bssid_copy = os_malloc(ETH_ALEN); + if (!bssid_copy) { + return ESP_ERR_NO_MEM; + } + memcpy(bssid_copy, bssid, ETH_ALEN); + if (eloop_register_timeout(0, 0, roaming_app_blacklist_add_handler, NULL, bssid_copy) != 0) { + os_free(bssid_copy); + return ESP_FAIL; + } + return ESP_OK; +} + +static void roaming_app_blacklist_remove_handler(void *ctx, void *data) +{ + uint8_t *bssid = data; + int found_index = -1; + for (int i = 0; i < g_roaming_app.bssid_blacklist_count; i++) { + if (memcmp(g_roaming_app.bssid_blacklist[i].bssid, bssid, ETH_ALEN) == 0) { + found_index = i; + break; + } + } + + if (found_index != -1) { + // Shift elements to fill the gap + int remaining_entries = g_roaming_app.bssid_blacklist_count - found_index - 1; + if (remaining_entries > 0) { + memmove(&g_roaming_app.bssid_blacklist[found_index], &g_roaming_app.bssid_blacklist[found_index + 1], remaining_entries * sizeof(struct blacklist_entry)); + } + g_roaming_app.bssid_blacklist_count--; + ESP_LOGI(ROAMING_TAG, "BSSID " MACSTR " removed from blacklist", MAC2STR(bssid)); + } else { + ESP_LOGD(ROAMING_TAG, "BSSID " MACSTR " not found in blacklist", MAC2STR(bssid)); + } + os_free(bssid); +} + +esp_err_t esp_wifi_blacklist_remove(const uint8_t *bssid) +{ + if (!bssid) { + return ESP_ERR_INVALID_ARG; + } + uint8_t *bssid_copy = os_malloc(ETH_ALEN); + if (!bssid_copy) { + return ESP_ERR_NO_MEM; + } + memcpy(bssid_copy, bssid, ETH_ALEN); + if (eloop_register_timeout(0, 0, roaming_app_blacklist_remove_handler, NULL, bssid_copy) != 0) { + os_free(bssid_copy); + return ESP_FAIL; + } + return ESP_OK; +} +#endif + /* No need for this to be done in pptask ctx */ esp_err_t roam_get_config_params(struct roam_config *config) { @@ -962,9 +1181,11 @@ static int update_config_params(void *data) g_roaming_app.config.backoff_time, g_roaming_app.config.low_rssi_roam_trigger, g_roaming_app.config.low_rssi_threshold, g_roaming_app.config.rssi_threshold_reduction_offset); +#if PERIODIC_SCAN_MONITORING ESP_LOGI(ROAMING_TAG, "scan_monitor=%d scan_interval=%d scan_rssi_threshold=%d scan_rssi_diff=%d", g_roaming_app.config.scan_monitor, g_roaming_app.config.scan_interval, g_roaming_app.config.scan_rssi_threshold, g_roaming_app.config.scan_rssi_diff); +#endif ESP_LOGI(ROAMING_TAG, "legacy_roam_enabled=%d, btm_retry_cnt=%d btm_roaming_enabled=%d", g_roaming_app.config.legacy_roam_enabled, diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index b066ee51c8b..0c680e383b5 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -245,6 +245,7 @@ idf_component_register(SRCS "${srcs}" "${esp_srcs}" "${tls_src}" "${roaming_src} INCLUDE_DIRS include port/include esp_supplicant/include PRIV_INCLUDE_DIRS src src/utils esp_supplicant/src src/crypto ../esp_wifi/wifi_apps/roaming_app/include + ../esp_wifi/wifi_apps/roaming_app/src LDFRAGMENTS ${linker_fragments} PRIV_REQUIRES mbedtls esp_timer esp_wifi) diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_common.c b/components/wpa_supplicant/esp_supplicant/src/esp_common.c index f2b02dbdd32..91e08191e98 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_common.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_common.c @@ -23,6 +23,8 @@ #include "rsn_supp/wpa_i.h" #include "rsn_supp/wpa.h" #include "esp_private/wifi.h" +#include "esp_wifi_types_generic.h" +#include "esp_roaming.h" /* Utility Functions */ esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6]) @@ -628,6 +630,9 @@ void wpa_supplicant_connect(struct wpa_supplicant *wpa_s, config->sta.channel = bss->channel; /* supplicant connect will only be called in case of bss transition(roaming) */ esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + esp_wifi_roaming_set_current_bssid(bss->bssid); +#endif esp_wifi_set_config(WIFI_IF_STA, config); os_free(config); esp_wifi_connect(); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index d3c93604f21..ff2e1c25c5e 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -31,6 +31,7 @@ #include "esp_eap_client.h" #include "esp_common_i.h" #include "esp_owe_i.h" +#include "esp_roaming.h" #include "esp_wps.h" #include "esp_wps_i.h" @@ -140,6 +141,9 @@ bool wpa_attach(void) ret = (esp_wifi_register_eapol_txdonecb_internal(eapol_txcb) == ESP_OK); } esp_set_scan_ie(); +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + roam_init_app(); +#endif return ret; } @@ -192,6 +196,9 @@ void wpa_ap_get_peer_spp_msg(void *sm_data, bool *spp_cap, bool *spp_req) bool wpa_deattach(void) { struct wpa_sm *sm = &gWpaSm; +#if CONFIG_ESP_WIFI_ENABLE_ROAMING_APP + roam_deinit_app(); +#endif esp_wpa3_free_sae_data(); #ifdef CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT if (sm->wpa_sm_eap_disable) { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c index 948f2713978..42cbbe92d89 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.c @@ -189,4 +189,9 @@ void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code) { /*check if need clear internal state and data value*/ } + +u8 wpa_supplicant_get_transition_disable(void) +{ + return wpa_sm_get_transition_disable(&gWpaSm); +} #endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h index 48ff0a6379d..1a1d57993b1 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpas_glue.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,8 @@ #ifndef WPAS_GLUE_H #define WPAS_GLUE_H +#include "rsn_supp/wpa_i.h" + u8 *wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos); @@ -35,4 +37,6 @@ void wpa_supplicant_transition_disable(struct wpa_sm *sm, u8 bitmap); int hostapd_send_eapol(const u8 *source, const u8 *sta_addr, const u8 *data, size_t data_len); + +u8 wpa_supplicant_get_transition_disable(void); #endif /* WPAS_GLUE_H */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 5165ddd9d6e..c1c21d91296 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -1340,6 +1340,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ie.transition_disable) { wpa_supplicant_transition_disable(sm, ie.transition_disable[0]); + sm->transition_disable = ie.transition_disable[0]; } if (sm->key_install && sm->key_info & WPA_KEY_INFO_INSTALL && sm->use_ext_key_id) { @@ -1357,6 +1358,11 @@ failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } +u8 wpa_sm_get_transition_disable(struct wpa_sm *sm) +{ + return sm->transition_disable; +} + static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) { int keylen; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 03cca337a5d..36fa6aa880c 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -9,6 +9,8 @@ #ifndef WPA_I_H #define WPA_I_H +#include "common/defs.h" + extern struct wpa_sm gWpaSm; #define DEFAULT_EAPOL_VERSION 1 @@ -86,6 +88,7 @@ struct wpa_sm { struct wpa_gtk_data gd; //used for calllback save param u16 key_info; //used for txcallback param u16 txcb_flags; + u8 transition_disable; bool ap_notify_completed_rsne; wifi_pmf_config_t pmf_cfg; u8 eapol1_count; @@ -207,6 +210,8 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); +u8 wpa_sm_get_transition_disable(struct wpa_sm *sm); + int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk); #endif /* WPA_I_H */