Merge branch 'feature/softap_fixes_for_ceritification_v5.2' into 'release/v5.2'

WiFi: fixes for issues discovered during SoftAP ceritification (v5.2)

See merge request espressif/esp-idf!36531
This commit is contained in:
Jiang Jiang Jian
2025-04-07 20:51:04 +08:00
25 changed files with 360 additions and 368 deletions

View File

@@ -540,9 +540,37 @@ menu "Wi-Fi"
and on the radio environment. Current implementation adds beacon report, and on the radio environment. Current implementation adds beacon report,
link measurement, neighbor report. link measurement, neighbor report.
config ESP_WIFI_RRM_SUPPORT
bool "Enable 802.11k APIs Support"
depends on ESP_WIFI_11KV_SUPPORT
default y
help
Select this option to enable 802.11k APIs(RRM support).
Only APIs which are helpful for network assisted roaming
are supported for now.
Enable this option with RRM enabled in sta config
to make device ready for network assisted roaming.
RRM: Radio measurements enable STAs to understand the radio environment,
it enables STAs to observe and gather data on radio link performance
and on the radio environment. Current implementation adds beacon report,
link measurement, neighbor report.
config ESP_WIFI_WNM_SUPPORT
bool "Enable 802.11v APIs Support"
depends on ESP_WIFI_11KV_SUPPORT
default y
help
Select this option to enable 802.11v APIs(BTM support).
Only APIs which are helpful for network assisted roaming
are supported for now.
Enable this option with BTM enabled in sta config
to make device ready for network assisted roaming.
BTM: BSS transition management enables an AP to request a station to transition
to a specific AP, or to indicate to a station a set of preferred APs.
config ESP_WIFI_SCAN_CACHE config ESP_WIFI_SCAN_CACHE
bool "Keep scan results in cache" bool "Keep scan results in cache"
depends on ESP_WIFI_11KV_SUPPORT depends on ESP_WIFI_RRM_SUPPORT
default n default n
help help
Keep scan results in cache, if not enabled, those Keep scan results in cache, if not enabled, those
@@ -551,6 +579,8 @@ menu "Wi-Fi"
config ESP_WIFI_MBO_SUPPORT config ESP_WIFI_MBO_SUPPORT
bool "Enable Multi Band Operation Certification Support" bool "Enable Multi Band Operation Certification Support"
default n default n
select ESP_WIFI_RRM_SUPPORT
select ESP_WIFI_WNM_SUPPORT
select ESP_WIFI_11KV_SUPPORT select ESP_WIFI_11KV_SUPPORT
select ESP_WIFI_SCAN_CACHE select ESP_WIFI_SCAN_CACHE
help help

View File

@@ -305,12 +305,13 @@ typedef struct {
uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */ uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */
uint8_t max_connection; /**< Max number of stations allowed to connect in */ uint8_t max_connection; /**< Max number of stations allowed to connect in */
uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */ uint16_t beacon_interval; /**< Beacon interval which should be multiples of 100. Unit: TU(time unit, 1 TU = 1024 us). Range: 100 ~ 60000. Default value: 100 */
uint8_t csa_count; /**< Channel Switch Announcement Count. Notify the station that the channel will switch after the csa_count beacon intervals. Range: 1 ~ 30. Default value: 3 */ uint8_t csa_count; /**< Channel Switch Announcement Count. Notify the station that the channel will switch after the csa_count beacon intervals. Default value: 3 */
uint8_t dtim_period; /**< Dtim period of soft-AP. Range: 1 ~ 10. Default value: 1 */ uint8_t dtim_period; /**< Dtim period of soft-AP. Range: 1 ~ 10. Default value: 1 */
wifi_cipher_type_t pairwise_cipher; /**< Pairwise cipher of SoftAP, group cipher will be derived using this. Cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */ wifi_cipher_type_t pairwise_cipher; /**< Pairwise cipher of SoftAP, group cipher will be derived using this. Cipher values are valid starting from WIFI_CIPHER_TYPE_TKIP, enum values before that will be considered as invalid and default cipher suites(TKIP+CCMP) will be used. Valid cipher suites in softAP mode are WIFI_CIPHER_TYPE_TKIP, WIFI_CIPHER_TYPE_CCMP and WIFI_CIPHER_TYPE_TKIP_CCMP. */
bool ftm_responder; /**< Enable FTM Responder mode */ bool ftm_responder; /**< Enable FTM Responder mode */
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */ wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame */
wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */ wifi_sae_pwe_method_t sae_pwe_h2e; /**< Configuration for SAE PWE derivation method */
uint8_t transition_disable; /**< Whether to enable transition disable feature */
} wifi_ap_config_t; } wifi_ap_config_t;
#define SAE_H2E_IDENTIFIER_LEN 32 #define SAE_H2E_IDENTIFIER_LEN 32

View File

@@ -174,8 +174,11 @@ endif()
if(CONFIG_ESP_WIFI_11KV_SUPPORT OR CONFIG_ESP_WIFI_11R_SUPPORT) if(CONFIG_ESP_WIFI_11KV_SUPPORT OR CONFIG_ESP_WIFI_11R_SUPPORT)
set(roaming_src set(roaming_src
"src/common/ieee802_11_common.c") "src/common/ieee802_11_common.c")
if(CONFIG_ESP_WIFI_11KV_SUPPORT) if(CONFIG_ESP_WIFI_RRM_SUPPORT)
set(roaming_src ${roaming_src} "src/common/rrm.c" "src/common/wnm_sta.c") set(roaming_src ${roaming_src} "src/common/rrm.c")
endif()
if(CONFIG_ESP_WIFI_WNM_SUPPORT)
set(roaming_src ${roaming_src} "src/common/wnm_sta.c")
endif() endif()
if(CONFIG_ESP_WIFI_11R_SUPPORT) if(CONFIG_ESP_WIFI_11R_SUPPORT)
set(roaming_src ${roaming_src} "src/rsn_supp/wpa_ft.c") set(roaming_src ${roaming_src} "src/rsn_supp/wpa_ft.c")
@@ -283,7 +286,13 @@ if(CONFIG_ESP_WIFI_DPP_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_DPP) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_DPP)
endif() endif()
if(CONFIG_ESP_WIFI_11KV_SUPPORT) if(CONFIG_ESP_WIFI_11KV_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUPPLICANT_TASK CONFIG_WNM CONFIG_RRM CONFIG_IEEE80211KV) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211KV)
endif()
if(CONFIG_ESP_WIFI_RRM_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_RRM)
endif()
if(CONFIG_ESP_WIFI_WNM_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WNM)
endif() endif()
if(CONFIG_ESP_WIFI_11R_SUPPORT) if(CONFIG_ESP_WIFI_11R_SUPPORT)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211R) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_IEEE80211R)

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -1151,6 +1151,10 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
int secret_key = 0; int secret_key = 0;
mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh; mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh;
if (!ctx) {
wpa_printf(MSG_ERROR, "ECDH Context is NULL");
return 0;
}
mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy; mbedtls_entropy_context entropy;
@@ -1205,7 +1209,7 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
/* Setup ECDH context from EC key */ /* Setup ECDH context from EC key */
/* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */ /* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */
if (ctx != NULL && peer != NULL) { if (peer != NULL) {
mbedtls_ecp_copy( ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->MBEDTLS_PRIVATE(Q) ); mbedtls_ecp_copy( ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->MBEDTLS_PRIVATE(Q) );
#ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT #ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT
ctx->MBEDTLS_PRIVATE(var) = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; ctx->MBEDTLS_PRIVATE(var) = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,43 +35,8 @@ esp_err_t esp_supplicant_str_to_mac(const char *str, uint8_t dest[6])
} }
struct wpa_supplicant g_wpa_supp; struct wpa_supplicant g_wpa_supp;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
#ifdef CONFIG_SUPPLICANT_TASK #ifdef CONFIG_RRM
static void *s_supplicant_task_hdl = NULL;
static void *s_supplicant_evt_queue = NULL;
static void *s_supplicant_api_lock = NULL;
static bool s_supplicant_task_init_done;
#define SUPPLICANT_API_LOCK() os_mutex_lock(s_supplicant_api_lock)
#define SUPPLICANT_API_UNLOCK() os_mutex_unlock(s_supplicant_api_lock)
#define SUPPLICANT_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD)
static int handle_action_frm(u8 *frame, size_t len,
u8 *sender, int8_t rssi, u8 channel)
{
struct ieee_mgmt_frame *frm = os_malloc(sizeof(struct ieee_mgmt_frame) + len);
if (!frm) {
wpa_printf(MSG_ERROR, "memory allocation failed");
return -1;
}
os_memcpy(frm->sender, sender, ETH_ALEN);
frm->len = len;
frm->channel = channel;
frm->rssi = rssi;
os_memcpy(frm->payload, frame, len);
if (esp_supplicant_post_evt(SIG_SUPPLICANT_RX_ACTION, (u32)frm) != 0) {
os_free(frm);
return -1;
}
return 0;
}
#endif /* CONFIG_SUPPLICANT_TASK */
#if defined(CONFIG_IEEE80211KV)
static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender, static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
u8 *payload, size_t len, int8_t rssi) u8 *payload, size_t len, int8_t rssi)
{ {
@@ -88,9 +53,12 @@ static void handle_rrm_frame(struct wpa_supplicant *wpa_s, u8 *sender,
payload + 1, len - 1, rssi); payload + 1, len - 1, rssi);
} }
} }
#endif /* CONFIG_RRM */
#if defined(CONFIG_IEEE80211KV)
static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel) static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 channel)
{ {
#if defined(CONFIG_RRM) || defined(CONFIG_WNM)
u8 category; u8 category;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_supplicant *wpa_s = &g_wpa_supp;
@@ -103,69 +71,29 @@ static int mgmt_rx_action(u8 *frame, size_t len, u8 *sender, int8_t rssi, u8 cha
category = *frame++; category = *frame++;
len--; len--;
#if defined(CONFIG_WNM)
if (category == WLAN_ACTION_WNM) { if (category == WLAN_ACTION_WNM) {
ieee802_11_rx_wnm_action(wpa_s, sender, frame, len); ieee802_11_rx_wnm_action(wpa_s, sender, frame, len);
} else if (category == WLAN_ACTION_RADIO_MEASUREMENT) { }
#endif /* CONFIG_WNM */
#if defined(CONFIG_RRM)
if (category == WLAN_ACTION_RADIO_MEASUREMENT) {
handle_rrm_frame(wpa_s, sender, frame, len, rssi); handle_rrm_frame(wpa_s, sender, frame, len, rssi);
} }
#endif /* CONFIG_RRM */
#endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) */
return 0; return 0;
} }
#endif /* defined(CONFIG_IEEE80211KV) */
#ifdef CONFIG_SUPPLICANT_TASK #if defined(CONFIG_WNM)
static void btm_rrm_task(void *pvParameters) static void clear_bssid_flag_and_channel(struct wpa_supplicant *wpa_s)
{
supplicant_event_t evt;
bool task_del = false;
while(1) {
if (os_queue_recv(s_supplicant_evt_queue, &evt, OS_BLOCK) != TRUE)
continue;
/* event validation failed */
if (evt.id >= SIG_SUPPLICANT_MAX) {
continue;
}
switch (evt.id) {
case SIG_SUPPLICANT_RX_ACTION:
{
struct ieee_mgmt_frame *frm = (struct ieee_mgmt_frame *)evt.data;
mgmt_rx_action(frm->payload, frm->len, frm->sender, frm->rssi, frm->channel);
os_free(frm);
break;
}
case SIG_SUPPLICANT_SCAN_DONE:
esp_supplicant_handle_scan_done_evt();
break;
case SIG_SUPPLICANT_DEL_TASK:
task_del = true;
break;
default:
break;
}
if (task_del)
break;
}
os_queue_delete(s_supplicant_evt_queue);
s_supplicant_evt_queue = NULL;
/* At this point, we completed */
os_task_delete(NULL);
}
#endif /* CONFIG_SUPPLICANT_TASK */
static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
{ {
wifi_config_t *config; wifi_config_t *config;
/* Reset only if btm is enabled */ /* Reset only if btm is enabled */
if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA) == false) if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA) == false) {
return; return;
}
config = os_zalloc(sizeof(wifi_config_t)); config = os_zalloc(sizeof(wifi_config_t));
@@ -175,30 +103,38 @@ static void clear_bssid_flag(struct wpa_supplicant *wpa_s)
} }
esp_wifi_get_config(WIFI_IF_STA, config); esp_wifi_get_config(WIFI_IF_STA, config);
if (config->sta.bssid_set) { if (config->sta.bssid_set || config->sta.channel) {
config->sta.channel = 0;
config->sta.bssid_set = 0; config->sta.bssid_set = 0;
esp_wifi_set_config(WIFI_IF_STA, config); esp_wifi_set_config(WIFI_IF_STA, config);
} }
os_free(config); os_free(config);
wpa_printf(MSG_DEBUG, "cleared bssid flag"); wpa_printf(MSG_DEBUG, "cleared bssid flag");
} }
#endif /* CONFIG_WNM */
#endif /* CONFIG_IEEE80211KV */
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
static void register_mgmt_frames(struct wpa_supplicant *wpa_s) static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
{ {
wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION); wpa_s->type &= ~(1 << WLAN_FC_STYPE_ACTION);
/* subtype is defined only for action frame */ /* subtype is defined only for action frame */
wpa_s->subtype = 0; wpa_s->subtype = 0;
#ifdef CONFIG_IEEE80211KV #ifdef CONFIG_RRM
/* current supported features in supplicant: rrm and btm */ /* current supported features in supplicant: rrm and btm */
if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) if (esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) {
wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT; wpa_s->subtype = 1 << WLAN_ACTION_RADIO_MEASUREMENT;
if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) }
#endif /* CONFIG_RRM */
#ifdef CONFIG_WNM
if (esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) {
wpa_s->subtype |= 1 << WLAN_ACTION_WNM; wpa_s->subtype |= 1 << WLAN_ACTION_WNM;
}
if (wpa_s->subtype) #endif /* CONFIG_WNM */
if (wpa_s->subtype) {
wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION; wpa_s->type |= 1 << WLAN_FC_STYPE_ACTION;
#endif /* CONFIG_IEEE80211KV */ }
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
/* register auth/assoc frames if FT is enabled */ /* register auth/assoc frames if FT is enabled */
@@ -209,6 +145,7 @@ static void register_mgmt_frames(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
} }
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
static int handle_auth_frame(u8 *frame, size_t len, static int handle_auth_frame(u8 *frame, size_t len,
@@ -240,8 +177,20 @@ static int handle_assoc_frame(u8 *frame, size_t len,
} }
return 0; return 0;
} }
void wpa_sta_clear_ft_auth_ie(void)
{
struct wpa_sm *sm = &gWpaSm;
wpa_printf(MSG_DEBUG, "Clearing all FT IE parameters and keys");
/* Reset FT parameters */
wpa_sm_set_ft_params(sm, NULL, 0);
esp_wifi_unset_appie_internal(WIFI_APPIE_RAM_STA_AUTH);
sm->ft_reassoc_completed = 0;
sm->ft_protocol = 0;
/* Clear pmk and ptk */
wpa_sm_drop_sa(sm);
}
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
void esp_supplicant_unset_all_appie(void) void esp_supplicant_unset_all_appie(void)
{ {
@@ -257,7 +206,7 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
int ret = 0; int ret = 0;
switch (type) { switch (type) {
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211KV) #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
case WLAN_FC_STYPE_BEACON: case WLAN_FC_STYPE_BEACON:
case WLAN_FC_STYPE_PROBE_RESP: case WLAN_FC_STYPE_PROBE_RESP:
ret = esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf); ret = esp_handle_beacon_probe(type, frame, len, sender, rssi, channel, current_tsf);
@@ -270,18 +219,14 @@ static int ieee80211_handle_rx_frm(u8 type, u8 *frame, size_t len, u8 *sender,
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
case WLAN_FC_STYPE_ASSOC_RESP: case WLAN_FC_STYPE_ASSOC_RESP:
case WLAN_FC_STYPE_REASSOC_RESP: case WLAN_FC_STYPE_REASSOC_RESP:
wpa_sm_notify_assoc(&gWpaSm, sender);
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
ret = handle_assoc_frame(frame, len, sender, rssi, channel); ret = handle_assoc_frame(frame, len, sender, rssi, channel);
#endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_IEEE80211R */
wpa_sm_notify_assoc(&gWpaSm, sender);
break; break;
#if defined(CONFIG_IEEE80211KV) #if defined(CONFIG_IEEE80211KV)
case WLAN_FC_STYPE_ACTION: case WLAN_FC_STYPE_ACTION:
#ifdef CONFIG_SUPPLICANT_TASK mgmt_rx_action(frame, len, sender, rssi, channel);
ret = handle_action_frm(frame, len, sender, rssi, channel);
#else /* CONFIG_SUPPLICANT_TASK */
ret = mgmt_rx_action(frame, len, sender, rssi, channel);
#endif /* CONFIG_SUPPLICANT_TASK */
break; break;
#endif /* defined(CONFIG_IEEE80211KV) */ #endif /* defined(CONFIG_IEEE80211KV) */
default: default:
@@ -326,36 +271,10 @@ int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
int ret = 0; int ret = 0;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
#ifdef CONFIG_SUPPLICANT_TASK #if defined(CONFIG_RRM)
if (!s_supplicant_api_lock) {
s_supplicant_api_lock = os_recursive_mutex_create();
}
if (!s_supplicant_api_lock) {
wpa_printf(MSG_ERROR, "%s: failed to create Supplicant API lock", __func__);
ret = -1;
goto err;
}
s_supplicant_evt_queue = os_queue_create(3, sizeof(supplicant_event_t));
if (!s_supplicant_evt_queue) {
wpa_printf(MSG_ERROR, "%s: failed to create Supplicant event queue", __func__);
ret = -1;
goto err;
}
ret = os_task_create(btm_rrm_task, "btm_rrm_t", SUPPLICANT_TASK_STACK_SIZE, NULL, 2, &s_supplicant_task_hdl);
if (ret != TRUE) {
wpa_printf(MSG_ERROR, "btm: failed to create task");
ret = -1;
goto err;
}
s_supplicant_task_init_done = true;
#endif /* CONFIG_SUPPLICANT_TASK */
#ifdef CONFIG_IEEE80211KV
wpas_rrm_reset(wpa_s); wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s); wpas_clear_beacon_rep_data(wpa_s);
#endif /* CONFIG_IEEE80211KV */ #endif /* defined(CONFIG_RRM) */
esp_scan_init(wpa_s); esp_scan_init(wpa_s);
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
@@ -385,37 +304,15 @@ void esp_supplicant_common_deinit(void)
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) #if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
esp_scan_deinit(wpa_s); esp_scan_deinit(wpa_s);
#ifdef CONFIG_IEEE80211KV #if defined(CONFIG_RRM)
wpas_rrm_reset(wpa_s); wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s); wpas_clear_beacon_rep_data(wpa_s);
#endif /* CONFIG_IEEE80211KV */ #endif /* defined(CONFIG_RRM) */
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
if (wpa_s->type) { if (wpa_s->type) {
wpa_s->type = 0; wpa_s->type = 0;
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
} }
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R)
#ifdef CONFIG_SUPPLICANT_TASK
/* We have failed to create task, delete queue and exit */
if (!s_supplicant_task_hdl) {
if (s_supplicant_evt_queue) {
os_queue_delete(s_supplicant_evt_queue);
s_supplicant_evt_queue = NULL;
}
if (s_supplicant_api_lock) {
os_mutex_delete(s_supplicant_api_lock);
s_supplicant_api_lock = NULL;
}
} else if (esp_supplicant_post_evt(SIG_SUPPLICANT_DEL_TASK, 0) != 0) {
/* failed to post delete event, just delete event queue and exit */
if (s_supplicant_evt_queue) {
os_queue_delete(s_supplicant_evt_queue);
s_supplicant_evt_queue = NULL;
}
}
s_supplicant_task_init_done = false;
#endif /* CONFIG_SUPPLICANT_TASK */
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
} }
void supplicant_sta_conn_handler(uint8_t *bssid) void supplicant_sta_conn_handler(uint8_t *bssid)
@@ -435,28 +332,37 @@ void supplicant_sta_conn_handler(uint8_t *bssid)
wpa_bss_flush(wpa_s); wpa_bss_flush(wpa_s);
/* Register for mgmt frames */ /* Register for mgmt frames */
register_mgmt_frames(wpa_s); register_mgmt_frames(wpa_s);
#if defined(CONFIG_WNM)
/* clear set bssid flag */ /* clear set bssid flag */
clear_bssid_flag(wpa_s); clear_bssid_flag_and_channel(wpa_s);
#endif /* CONFIG_WNM */
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
} }
void supplicant_sta_disconn_handler(void) void supplicant_sta_disconn_handler(uint8_t reason_code)
{ {
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) #if defined(CONFIG_IEEE80211KV)
struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_supplicant *wpa_s = &g_wpa_supp;
#ifdef CONFIG_IEEE80211KV #if defined(CONFIG_RRM)
wpas_rrm_reset(wpa_s); wpas_rrm_reset(wpa_s);
wpas_clear_beacon_rep_data(wpa_s); wpas_clear_beacon_rep_data(wpa_s);
#endif /* CONFIG_IEEE80211KV */ #endif /* defined(CONFIG_RRM) */
#if defined(CONFIG_WNM)
/* Not clearing in case of roaming disconnect as BTM induced connection
* itself sets a specific bssid and channel to connect to before disconnection.
* Subsequent connections or disconnections will clear this flag */
if (reason_code != WIFI_REASON_ROAMING) {
clear_bssid_flag_and_channel(wpa_s);
}
#endif /* CONFIG_WNM */
if (wpa_s->current_bss) { if (wpa_s->current_bss) {
wpa_s->current_bss = NULL; wpa_s->current_bss = NULL;
} }
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #endif /* defined(CONFIG_IEEE80211KV) */
} }
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) #if defined(CONFIG_RRM)
#ifdef CONFIG_IEEE80211KV
bool esp_rrm_is_rrm_supported_connection(void) bool esp_rrm_is_rrm_supported_connection(void)
{ {
struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_supplicant *wpa_s = &g_wpa_supp;
@@ -500,6 +406,33 @@ int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
return wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx); return wpas_rrm_send_neighbor_rep_request(wpa_s, &wpa_ssid, 0, 0, cb, cb_ctx);
} }
static size_t get_rm_enabled_ie(uint8_t *ie, size_t len)
{
uint8_t rrm_ie[7] = {0};
uint8_t rrm_ie_len = 5;
uint8_t *pos = rrm_ie;
if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) {
return 0;
}
*pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
*pos++ = rrm_ie_len;
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
*pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
#ifdef SCAN_CACHE_SUPPORTED
WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
#endif /* SCAN_CACHE_SUPPORTED */
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
os_memcpy(ie, rrm_ie, sizeof(rrm_ie));
return rrm_ie_len + 2;
}
#endif /* defined(CONFIG_RRM) */
#if defined(CONFIG_WNM)
bool esp_wnm_is_btm_supported_connection(void) bool esp_wnm_is_btm_supported_connection(void)
{ {
struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_supplicant *wpa_s = &g_wpa_supp;
@@ -535,6 +468,37 @@ int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, btm_candidates, cand_list); return wnm_send_bss_transition_mgmt_query(wpa_s, query_reason, btm_candidates, cand_list);
} }
static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len)
{
uint8_t ext_caps_ie[5] = {0};
uint8_t ext_caps_ie_len = 3;
uint8_t *pos = ext_caps_ie;
wifi_ioctl_config_t cfg = {0};
esp_err_t err = 0;
if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) {
return 0;
}
*pos++ = WLAN_EID_EXT_CAPAB;
*pos++ = ext_caps_ie_len;
err = esp_wifi_internal_ioctl(WIFI_IOCTL_GET_STA_HT2040_COEX, &cfg);
if (err == ESP_OK && cfg.data.ht2040_coex.enable) {
*pos++ |= BIT(WLAN_EXT_CAPAB_20_40_COEX);
} else {
*pos++ = 0;
}
*pos ++ = 0;
#define CAPAB_BSS_TRANSITION BIT(3)
*pos |= CAPAB_BSS_TRANSITION;
#undef CAPAB_BSS_TRANSITION
os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie));
return ext_caps_ie_len + 2;
}
#endif /* defined(CONFIG_WNM) */
#ifdef CONFIG_MBO #ifdef CONFIG_MBO
int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan) int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
{ {
@@ -542,55 +506,7 @@ int esp_mbo_update_non_pref_chan(struct non_pref_chan_s *non_pref_chan)
return ret; return ret;
} }
#endif /* CONFIG_MBO */
void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, char *ssid)
{
wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
if (!config) {
wpa_printf(MSG_ERROR, "failed to allocate memory");
return;
}
esp_wifi_get_config(WIFI_IF_STA, config);
/* We only support roaming in same ESS, therefore only bssid setting is needed */
os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN);
config->sta.bssid_set = 1;
/* supplicant connect will only be called in case of bss transition(roaming) */
esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC);
esp_wifi_set_config(WIFI_IF_STA, config);
os_free(config);
esp_wifi_connect();
}
static size_t get_rm_enabled_ie(uint8_t *ie, size_t len)
{
uint8_t rrm_ie[7] = {0};
uint8_t rrm_ie_len = 5;
uint8_t *pos = rrm_ie;
if (!esp_wifi_is_rm_enabled_internal(WIFI_IF_STA)) {
return 0;
}
*pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
*pos++ = rrm_ie_len;
*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
*pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
#ifdef SCAN_CACHE_SUPPORTED
WLAN_RRM_CAPS_BEACON_REPORT_TABLE |
#endif /* SCAN_CACHE_SUPPORTED */
WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE;
os_memcpy(ie, rrm_ie, sizeof(rrm_ie));
return rrm_ie_len + 2;
}
#ifdef CONFIG_MBO
static size_t get_mbo_oce_scan_ie(uint8_t *ie, size_t len) static size_t get_mbo_oce_scan_ie(uint8_t *ie, size_t len)
{ {
uint8_t mbo_ie[32] = {0}; uint8_t mbo_ie[32] = {0};
@@ -647,41 +563,31 @@ static uint8_t get_operating_class_ie(uint8_t *ie, size_t len)
} }
#endif /* CONFIG_MBO */ #endif /* CONFIG_MBO */
static uint8_t get_extended_caps_ie(uint8_t *ie, size_t len) void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, char *ssid)
{ {
uint8_t ext_caps_ie[5] = {0}; wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
uint8_t ext_caps_ie_len = 3;
uint8_t *pos = ext_caps_ie;
wifi_ioctl_config_t cfg = {0};
esp_err_t err = 0;
if (!esp_wifi_is_btm_enabled_internal(WIFI_IF_STA)) { if (!config) {
return 0; wpa_printf(MSG_ERROR, "failed to allocate memory");
return;
} }
*pos++ = WLAN_EID_EXT_CAPAB; esp_wifi_get_config(WIFI_IF_STA, config);
*pos++ = ext_caps_ie_len; /* We only support roaming in same ESS, therefore only bssid setting is needed */
os_memcpy(config->sta.bssid, bss->bssid, ETH_ALEN);
err = esp_wifi_internal_ioctl(WIFI_IOCTL_GET_STA_HT2040_COEX, &cfg); config->sta.bssid_set = 1;
if (err == ESP_OK && cfg.data.ht2040_coex.enable) { config->sta.channel = bss->channel;
*pos++ |= BIT(WLAN_EXT_CAPAB_20_40_COEX); /* supplicant connect will only be called in case of bss transition(roaming) */
} else { esp_wifi_internal_issue_disconnect(WIFI_REASON_BSS_TRANSITION_DISASSOC);
*pos++ = 0; esp_wifi_set_config(WIFI_IF_STA, config);
} os_free(config);
*pos ++ = 0; esp_wifi_connect();
#define CAPAB_BSS_TRANSITION BIT(3)
*pos |= CAPAB_BSS_TRANSITION;
#undef CAPAB_BSS_TRANSITION
os_memcpy(ie, ext_caps_ie, sizeof(ext_caps_ie));
return ext_caps_ie_len + 2;
} }
#endif /* CONFIG_IEEE80211KV */ #if defined(CONFIG_WNM) || defined(CONFIG_MBO)
void esp_set_scan_ie(void) void esp_set_scan_ie(void)
{ {
#ifdef CONFIG_IEEE80211KV
#define SCAN_IE_LEN 64 #define SCAN_IE_LEN 64
uint8_t *ie, *pos; uint8_t *ie, *pos;
size_t len = SCAN_IE_LEN, ie_len; size_t len = SCAN_IE_LEN, ie_len;
@@ -692,20 +598,24 @@ void esp_set_scan_ie(void)
return; return;
} }
pos = ie; pos = ie;
#ifdef CONFIG_WNM
ie_len = get_extended_caps_ie(pos, len); ie_len = get_extended_caps_ie(pos, len);
pos += ie_len; pos += ie_len;
len -= ie_len; len -= ie_len;
#endif /* defined(CONFIG_WNM) */
#ifdef CONFIG_MBO #ifdef CONFIG_MBO
ie_len = get_mbo_oce_scan_ie(pos, len); ie_len = get_mbo_oce_scan_ie(pos, len);
pos += ie_len; pos += ie_len;
len -= ie_len; len -= ie_len;
#endif /* CONFIG_MBO */ #endif /* CONFIG_MBO */
if (SCAN_IE_LEN - len) {
esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ); esp_wifi_unset_appie_internal(WIFI_APPIE_PROBEREQ);
esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0); esp_wifi_set_appie_internal(WIFI_APPIE_PROBEREQ, ie, SCAN_IE_LEN - len, 0);
}
os_free(ie); os_free(ie);
#undef SCAN_IE_LEN #undef SCAN_IE_LEN
#endif /* CONFIG_IEEE80211KV */
} }
#endif /* defined(CONFIG_WNM) || defined(CONFIG_MBO) */
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len) static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len)
@@ -738,14 +648,11 @@ static size_t add_mdie(uint8_t *bssid, uint8_t *ie, size_t len)
return mdie_len; return mdie_len;
} }
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211R
int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md, int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md,
const u8 *ies, size_t ies_len, bool auth_ie) const u8 *ies, size_t ies_len, bool auth_ie)
{ {
wpa_printf(MSG_INFO, "Updating FT IEs (len=%d)", ies_len); wpa_printf(MSG_INFO, "Updating FT IEs (len=%d), auth_ie %d ", ies_len, auth_ie);
if (os_memcmp(sm->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN) != 0) { if (os_memcmp(sm->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN) != 0) {
return 0; return 0;
} }
@@ -811,57 +718,45 @@ int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
return ret; return ret;
} }
#ifdef CONFIG_SUPPLICANT_TASK #ifndef CONFIG_WNM
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data) void esp_set_scan_ie(void) { }
bool esp_wnm_is_btm_supported_connection(void)
{ {
supplicant_event_t evt; return false;
evt.id = evt_id;
evt.data = data;
/* Make sure lock exists before taking it */
SUPPLICANT_API_LOCK();
/* Make sure no event can be sent when deletion event is sent or task not initialized */
if (!s_supplicant_task_init_done) {
SUPPLICANT_API_UNLOCK();
return -1;
} }
if (os_queue_send(s_supplicant_evt_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
SUPPLICANT_API_UNLOCK();
return -1;
}
if (evt_id == SIG_SUPPLICANT_DEL_TASK) {
s_supplicant_task_init_done = false;
}
SUPPLICANT_API_UNLOCK();
return 0;
}
#endif /* CONFIG_SUPPLICANT_TASK */
#else /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
void *cb_ctx)
{
return -1;
}
int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason, int esp_wnm_send_bss_transition_mgmt_query(enum btm_query_reason query_reason,
const char *btm_candidates, const char *btm_candidates,
int cand_list) int cand_list)
{ {
return -1; return -1;
} }
#endif
void esp_set_scan_ie(void) { } #ifndef CONFIG_RRM
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ bool esp_rrm_is_rrm_supported_connection(void)
{
return false;
}
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) int esp_rrm_send_neighbor_report_request(void)
{
return -1;
}
int esp_rrm_send_neighbor_rep_request(neighbor_rep_request_cb cb,
void *cb_ctx)
{
return -1;
}
#endif
#if defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE)
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
{ {
#define ASSOC_IE_LEN 128 #define ASSOC_IE_LEN 128
uint8_t *ie, *pos; uint8_t *ie, *pos;
size_t len = ASSOC_IE_LEN; size_t len = ASSOC_IE_LEN;
#if defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) #if defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R)
size_t ie_len; size_t ie_len;
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */ #endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) */
ie = os_malloc(ASSOC_IE_LEN + ies_len); ie = os_malloc(ASSOC_IE_LEN + ies_len);
@@ -870,10 +765,11 @@ void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
return; return;
} }
pos = ie; pos = ie;
#ifdef CONFIG_IEEE80211KV #if defined(CONFIG_RRM)
ie_len = get_rm_enabled_ie(pos, len); ie_len = get_rm_enabled_ie(pos, len);
pos += ie_len; pos += ie_len;
len -= ie_len; len -= ie_len;
#endif /* defined(CONFIG_RRM) */
#ifdef CONFIG_MBO #ifdef CONFIG_MBO
ie_len = get_operating_class_ie(pos, len); ie_len = get_operating_class_ie(pos, len);
pos += ie_len; pos += ie_len;
@@ -882,7 +778,6 @@ void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
pos += ie_len; pos += ie_len;
len -= ie_len; len -= ie_len;
#endif /* CONFIG_MBO */ #endif /* CONFIG_MBO */
#endif /* CONFIG_IEEE80211KV */
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
if (mdie) { if (mdie) {
ie_len = add_mdie(bssid, pos, len); ie_len = add_mdie(bssid, pos, len);
@@ -901,4 +796,4 @@ void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie)
} }
#else #else
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { } void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool mdie) { }
#endif /* defined(CONFIG_IEEE80211KV) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */ #endif /* defined(CONFIG_RRM) || defined(CONFIG_IEEE80211R) || defined(CONFIG_WPA3_SAE) */

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,7 +12,7 @@
struct wpa_funcs; struct wpa_funcs;
extern struct wpa_supplicant g_wpa_supp; extern struct wpa_supplicant g_wpa_supp;
#ifdef CONFIG_IEEE80211KV #if defined(CONFIG_RRM) || defined(CONFIG_WNM)
struct ieee_mgmt_frame { struct ieee_mgmt_frame {
u8 sender[ETH_ALEN]; u8 sender[ETH_ALEN];
u8 channel; u8 channel;
@@ -21,30 +21,17 @@ struct ieee_mgmt_frame {
u8 payload[0]; u8 payload[0];
}; };
int esp_supplicant_post_evt(uint32_t evt_id, uint32_t data);
typedef struct {
uint32_t id;
uint32_t data;
} supplicant_event_t;
enum SIG_SUPPLICANT {
SIG_SUPPLICANT_RX_ACTION,
SIG_SUPPLICANT_SCAN_DONE,
SIG_SUPPLICANT_DEL_TASK,
SIG_SUPPLICANT_MAX,
};
void esp_get_tx_power(uint8_t *tx_power); void esp_get_tx_power(uint8_t *tx_power);
#ifdef CONFIG_MBO #ifdef CONFIG_MBO
bool mbo_bss_profile_match(u8 *bssid); bool mbo_bss_profile_match(u8 *bssid);
#endif #endif
#endif #endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) */
int esp_supplicant_common_init(struct wpa_funcs *wpa_cb); int esp_supplicant_common_init(struct wpa_funcs *wpa_cb);
void esp_supplicant_common_deinit(void); void esp_supplicant_common_deinit(void);
void esp_supplicant_unset_all_appie(void); void esp_supplicant_unset_all_appie(void);
void esp_set_scan_ie(void); void esp_set_scan_ie(void);
void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool add_mdie); void esp_set_assoc_ie(uint8_t *bssid, const u8 *ies, size_t ies_len, bool add_mdie);
void supplicant_sta_conn_handler(uint8_t* bssid); void supplicant_sta_conn_handler(uint8_t* bssid);
void supplicant_sta_disconn_handler(void); void supplicant_sta_disconn_handler(uint8_t reason_code);
#endif #endif
void wpa_sta_clear_ft_auth_ie(void);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -162,6 +162,19 @@ void *hostap_init(void)
os_memcpy(hapd->conf->ssid.wpa_passphrase, esp_wifi_ap_get_prof_password_internal(), strlen((char *)esp_wifi_ap_get_prof_password_internal())); os_memcpy(hapd->conf->ssid.wpa_passphrase, esp_wifi_ap_get_prof_password_internal(), strlen((char *)esp_wifi_ap_get_prof_password_internal()));
hapd->conf->ssid.wpa_passphrase[WIFI_PASSWORD_LEN_MAX - 1] = '\0'; hapd->conf->ssid.wpa_passphrase[WIFI_PASSWORD_LEN_MAX - 1] = '\0';
hapd->conf->max_num_sta = esp_wifi_ap_get_max_sta_conn(); hapd->conf->max_num_sta = esp_wifi_ap_get_max_sta_conn();
auth_conf->transition_disable = esp_wifi_ap_get_transition_disable_internal();
if (authmode != WIFI_AUTH_WPA3_PSK &&
authmode != WIFI_AUTH_WPA2_WPA3_PSK && auth_conf->transition_disable) {
auth_conf->transition_disable = 0;
wpa_printf(MSG_DEBUG, "overriding transition_disable config with 0 as authmode is not WPA3");
}
#ifdef CONFIG_SAE
auth_conf->sae_require_mfp = 1;
#endif /* CONFIG_SAE */
//TODO change it when AP support GCMP-PSK
auth_conf->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
hapd->conf->ap_max_inactivity = 5 * 60; hapd->conf->ap_max_inactivity = 5 * 60;
hostapd_setup_wpa_psk(hapd->conf); hostapd_setup_wpa_psk(hapd->conf);
@@ -348,7 +361,7 @@ uint8_t wpa_status_to_reason_code(int status)
} }
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len, uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason) bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason)
{ {
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal(); struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,16 +35,10 @@ static void scan_done_event_handler(void *arg, ETS_STATUS status)
wpa_s->type &= ~(1 << WLAN_FC_STYPE_BEACON) & ~(1 << WLAN_FC_STYPE_PROBE_RESP); wpa_s->type &= ~(1 << WLAN_FC_STYPE_BEACON) & ~(1 << WLAN_FC_STYPE_PROBE_RESP);
esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype); esp_wifi_register_mgmt_frame_internal(wpa_s->type, wpa_s->subtype);
} }
#ifdef CONFIG_SUPPLICANT_TASK
if (esp_supplicant_post_evt(SIG_SUPPLICANT_SCAN_DONE, 0) != 0) {
wpa_printf(MSG_ERROR, "Posting of scan done failed!");
}
#else
esp_supplicant_handle_scan_done_evt(); esp_supplicant_handle_scan_done_evt();
#endif /*CONFIG_SUPPLICANT_TASK*/
} }
#if defined(CONFIG_IEEE80211KV) #if defined(CONFIG_WNM)
static void handle_wnm_scan_done(struct wpa_supplicant *wpa_s) static void handle_wnm_scan_done(struct wpa_supplicant *wpa_s)
{ {
struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss); struct wpa_bss *bss = wpa_bss_get_next_bss(wpa_s, wpa_s->current_bss);
@@ -77,11 +71,14 @@ void esp_supplicant_handle_scan_done_evt(void)
struct wpa_supplicant *wpa_s = &g_wpa_supp; struct wpa_supplicant *wpa_s = &g_wpa_supp;
wpa_printf(MSG_INFO, "scan done received"); wpa_printf(MSG_INFO, "scan done received");
#if defined(CONFIG_IEEE80211KV) #if defined(CONFIG_RRM)
/* Check which module started this, call the respective function */ /* Check which module started this, call the respective function */
if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) { if (wpa_s->scan_reason == REASON_RRM_BEACON_REPORT) {
wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf); wpas_beacon_rep_scan_process(wpa_s, wpa_s->scan_start_tsf);
} else if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) { }
#endif
#if defined(CONFIG_WNM)
if (wpa_s->scan_reason == REASON_WNM_BSS_TRANS_REQ) {
handle_wnm_scan_done(wpa_s); handle_wnm_scan_done(wpa_s);
} }
#endif #endif

View File

@@ -127,7 +127,7 @@ struct wpa_funcs {
bool (*wpa_sta_in_4way_handshake)(void); bool (*wpa_sta_in_4way_handshake)(void);
void *(*wpa_ap_init)(void); void *(*wpa_ap_init)(void);
bool (*wpa_ap_deinit)(void *data); bool (*wpa_ap_deinit)(void *data);
bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u8 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); bool (*wpa_ap_join)(void **sm, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8* rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher);
bool (*wpa_ap_remove)(u8 *bssid); bool (*wpa_ap_remove)(u8 *bssid);
uint8_t *(*wpa_ap_get_wpa_ie)(uint8_t *len); uint8_t *(*wpa_ap_get_wpa_ie)(uint8_t *len);
bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len); bool (*wpa_ap_rx_eapol)(void *hapd_data, void *sm, u8 *data, size_t data_len);
@@ -303,5 +303,6 @@ bool esp_wifi_eb_tx_status_success_internal(void *eb);
uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid); uint8_t* esp_wifi_sta_get_rsnxe(u8 *bssid);
esp_err_t esp_wifi_sta_connect_internal(const uint8_t *bssid); esp_err_t esp_wifi_sta_connect_internal(const uint8_t *bssid);
void esp_wifi_enable_sae_pk_only_mode_internal(void); void esp_wifi_enable_sae_pk_only_mode_internal(void);
uint8_t esp_wifi_ap_get_transition_disable_internal(void);
#endif /* _ESP_WIFI_DRIVER_H_ */ #endif /* _ESP_WIFI_DRIVER_H_ */

View File

@@ -523,6 +523,11 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt)
goto done; goto done;
} }
if (ret == WLAN_STATUS_SUCCESS) { if (ret == WLAN_STATUS_SUCCESS) {
if (sta->sae_data && esp_send_sae_auth_reply(hapd, sta->addr, frm->bssid, WLAN_AUTH_SAE, 2,
WLAN_STATUS_SUCCESS, wpabuf_head(sta->sae_data), wpabuf_len(sta->sae_data)) != ESP_OK) {
ap_free_sta(hapd, sta);
goto done;
}
if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) { if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) {
ap_free_sta(hapd, sta); ap_free_sta(hapd, sta);
goto done; goto done;
@@ -534,6 +539,11 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt)
esp_wifi_ap_get_sta_aid(frm->bssid, &aid); esp_wifi_ap_get_sta_aid(frm->bssid, &aid);
if (aid == 0) { if (aid == 0) {
esp_wifi_ap_deauth_internal(frm->bssid, ret); esp_wifi_ap_deauth_internal(frm->bssid, ret);
} else {
if (sta && sta->sae_data) {
wpabuf_free(sta->sae_data);
sta->sae_data = NULL;
}
} }
} }
} }

View File

@@ -260,8 +260,14 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
case WIFI_REASON_ASSOC_FAIL: case WIFI_REASON_ASSOC_FAIL:
case WIFI_REASON_CONNECTION_FAIL: case WIFI_REASON_CONNECTION_FAIL:
case WIFI_REASON_HANDSHAKE_TIMEOUT: case WIFI_REASON_HANDSHAKE_TIMEOUT:
case WIFI_REASON_INVALID_MDE:
case WIFI_REASON_INVALID_FTE:
wpa_sta_clear_curr_pmksa(); wpa_sta_clear_curr_pmksa();
wpa_sm_notify_disassoc(&gWpaSm); wpa_sm_notify_disassoc(&gWpaSm);
#if defined(CONFIG_IEEE80211R)
/* clear all ft auth related IEs so that next will be open auth */
wpa_sta_clear_ft_auth_ie();
#endif
break; break;
default: default:
if (g_wpa_pmk_caching_disabled) { if (g_wpa_pmk_caching_disabled) {
@@ -280,7 +286,7 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
#endif /* CONFIG_OWE_STA */ #endif /* CONFIG_OWE_STA */
esp_wpa3_free_sae_data(); esp_wpa3_free_sae_data();
supplicant_sta_disconn_handler(); supplicant_sta_disconn_handler(reason_code);
} }
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
@@ -318,7 +324,7 @@ static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_i
} }
#endif #endif
static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u8 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher) static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u16 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher)
{ {
struct sta_info *sta_info = NULL; struct sta_info *sta_info = NULL;
struct hostapd_data *hapd = hostapd_get_hapd_data(); struct hostapd_data *hapd = hostapd_get_hapd_data();

View File

@@ -383,7 +383,7 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
struct sta_info; struct sta_info;
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len,uint8_t *rsnxe, uint8_t rsnxe_len, uint8_t wpa_ie_len, uint8_t *rsnxe, uint16_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason); bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason);
bool wpa_ap_remove(u8* bssid); bool wpa_ap_remove(u8* bssid);

View File

@@ -178,14 +178,18 @@ static int auth_sae_send_confirm(struct hostapd_data *hapd,
#ifdef ESP_SUPPLICANT #ifdef ESP_SUPPLICANT
if (sta->remove_pending) { if (sta->remove_pending) {
reply_res = -1; reply_res = -1;
wpabuf_free(data);
} else { } else {
reply_res = esp_send_sae_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2, if (sta->sae_data)
WLAN_STATUS_SUCCESS, wpabuf_head(data), wpabuf_free(sta->sae_data);
wpabuf_len(data)); sta->sae_data = data;
reply_res = 0;
/* confirm is sent in later stage when all the required processing for a sta is done*/
} }
#else
wpabuf_free(data);
#endif /* ESP_SUPPLICANT */ #endif /* ESP_SUPPLICANT */
wpabuf_free(data);
return reply_res; return reply_res;
} }
@@ -675,7 +679,7 @@ int auth_sae_queue(struct hostapd_data *hapd,
unsigned int queue_len; unsigned int queue_len;
queue_len = dl_list_len(&hapd->sae_commit_queue); queue_len = dl_list_len(&hapd->sae_commit_queue);
if (queue_len >= 5) { if (queue_len >= hapd->conf->max_num_sta) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"SAE: No more room in message queue - drop the new frame from " "SAE: No more room in message queue - drop the new frame from "
MACSTR, MAC2STR(bssid)); MACSTR, MAC2STR(bssid));

View File

@@ -113,6 +113,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
os_mutex_delete(sta->lock); os_mutex_delete(sta->lock);
sta->lock = NULL; sta->lock = NULL;
} }
if (sta->sae_data) {
wpabuf_free(sta->sae_data);
sta->sae_data = NULL;
}
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
wpa_auth_sta_deinit(sta->wpa_sm); wpa_auth_sta_deinit(sta->wpa_sm);
#ifdef CONFIG_WPS_REGISTRAR #ifdef CONFIG_WPS_REGISTRAR

View File

@@ -66,6 +66,7 @@ struct sta_info {
* processing commit for that station */ * processing commit for that station */
bool remove_pending; /* Flag to indicate to free station when bool remove_pending; /* Flag to indicate to free station when
* whose mutex is taken by task */ * whose mutex is taken by task */
struct wpabuf *sae_data;
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
#endif /* ESP_SUPPLICANT */ #endif /* ESP_SUPPLICANT */

View File

@@ -1875,6 +1875,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
} }
kde_len = wpa_ie_len + ieee80211w_kde_len(sm); kde_len = wpa_ie_len + ieee80211w_kde_len(sm);
if (sm->wpa_auth->conf.transition_disable)
kde_len += 2 + RSN_SELECTOR_LEN + 1;
if (gtk) if (gtk)
kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len;
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
@@ -1911,6 +1915,9 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
} }
pos = ieee80211w_kde_add(sm, pos); pos = ieee80211w_kde_add(sm, pos);
if (sm->wpa_auth->conf.transition_disable)
pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE,
&sm->wpa_auth->conf.transition_disable, 1, NULL, 0);
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
int res; int res;

View File

@@ -144,6 +144,10 @@ struct wpa_auth_config {
#ifdef CONFIG_IEEE80211W #ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w; enum mfp_options ieee80211w;
#endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_IEEE80211W */
int group_mgmt_cipher;
#ifdef CONFIG_SAE
int sae_require_mfp;
#endif /* CONFIG_SAE */
#ifdef CONFIG_IEEE80211R #ifdef CONFIG_IEEE80211R
#define SSID_LEN 32 #define SSID_LEN 32
u8 ssid[SSID_LEN]; u8 ssid[SSID_LEN];
@@ -163,6 +167,7 @@ struct wpa_auth_config {
int ap_mlme; int ap_mlme;
enum sae_pwe sae_pwe; enum sae_pwe sae_pwe;
struct rsn_sppamsdu_sup spp_sup; struct rsn_sppamsdu_sup spp_sup;
u8 transition_disable;
}; };
typedef enum { typedef enum {

View File

@@ -388,6 +388,7 @@ u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len,
return pos; return pos;
} }
enum wpa_validate_result enum wpa_validate_result
wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm, struct wpa_state_machine *sm,
@@ -563,13 +564,25 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_MGMT_FRAME_PROTECTION_VIOLATION; return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
} }
if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
{
wpa_printf(MSG_DEBUG, "Unsupported management group " wpa_printf(MSG_DEBUG, "Unsupported management group "
"cipher %d", data.mgmt_group_cipher); "cipher %d", data.mgmt_group_cipher);
return WPA_INVALID_MGMT_GROUP_CIPHER; return WPA_INVALID_MGMT_GROUP_CIPHER;
} }
} }
#ifdef CONFIG_SAE
if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL &&
wpa_auth->conf.sae_require_mfp &&
wpa_key_mgmt_sae(sm->wpa_key_mgmt) &&
!(data.capabilities & WPA_CAPABILITY_MFPC)) {
wpa_printf(MSG_DEBUG,
"Management frame protection required with SAE, but client did not enable it");
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
}
#endif /* CONFIG_SAE */
if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
!(data.capabilities & WPA_CAPABILITY_MFPC)) !(data.capabilities & WPA_CAPABILITY_MFPC))
sm->mgmt_frame_prot = 0; sm->mgmt_frame_prot = 0;

View File

@@ -268,7 +268,7 @@ static int ieee802_11_parse_extension(struct wpa_supplicant *wpa_s, const struct
*/ */
int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len) int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t len)
{ {
#if defined(CONFIG_RRM) || defined(CONFIG_SAE_PK) #if defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK)
const struct element *elem; const struct element *elem;
u8 unknown = 0; u8 unknown = 0;
@@ -297,7 +297,7 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t
} }
break; break;
#endif /*CONFIG_SAE_PK*/ #endif /*CONFIG_SAE_PK*/
#ifdef CONFIG_RRM #ifdef CONFIG_WNM
case WLAN_EID_EXT_CAPAB: case WLAN_EID_EXT_CAPAB:
/* extended caps can go beyond 8 octacts but we aren't using them now */ /* extended caps can go beyond 8 octacts but we aren't using them now */
os_memcpy(wpa_s->extend_caps, pos, 5); os_memcpy(wpa_s->extend_caps, pos, 5);
@@ -311,7 +311,7 @@ int ieee802_11_parse_elems(struct wpa_supplicant *wpa_s, const u8 *start, size_t
if (unknown) if (unknown)
return -1; return -1;
#endif /* defined(CONFIG_RRM) || defined(CONFIG_SAE_PK) */ #endif /* defined(CONFIG_RRM) || defined(CONFIG_WNM) || defined(CONFIG_SAE_PK) */
return 0; return 0;
} }

View File

@@ -2718,8 +2718,6 @@ struct wpa_sm * get_wpa_sm(void)
int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len) int wpa_sm_set_ap_rsnxe(const u8 *ie, size_t len)
{ {
struct wpa_sm *sm = &gWpaSm; struct wpa_sm *sm = &gWpaSm;
if (!sm)
return -1;
os_free(sm->ap_rsnxe); os_free(sm->ap_rsnxe);
if (!ie || len == 0) { if (!ie || len == 0) {

View File

@@ -0,0 +1 @@
CONFIG_ESP_WIFI_11R_SUPPORT=y

View File

@@ -0,0 +1,2 @@
CONFIG_ESP_WIFI_11KV_SUPPORT=y
CONFIG_ESP_WIFI_RRM_SUPPORT=y

View File

@@ -0,0 +1,2 @@
CONFIG_ESP_WIFI_11KV_SUPPORT=y
CONFIG_ESP_WIFI_WNM_SUPPORT=y

View File

@@ -2,3 +2,5 @@ CONFIG_ESP_WIFI_11KV_SUPPORT=y
CONFIG_ESP_WIFI_SCAN_CACHE=y CONFIG_ESP_WIFI_SCAN_CACHE=y
CONFIG_ESP_WIFI_MBO_SUPPORT=y CONFIG_ESP_WIFI_MBO_SUPPORT=y
CONFIG_ESP_WIFI_11R_SUPPORT=y CONFIG_ESP_WIFI_11R_SUPPORT=y
CONFIG_ESP_WIFI_RRM_SUPPORT=y
CONFIG_ESP_WIFI_WNM_SUPPORT=y