mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(wpa_supplicant): Fix concurrency issues between wpa3 and wifi task
This commit is contained in:
@@ -202,7 +202,6 @@ void *hostap_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
dl_list_init(&hapd->sae_commit_queue);
|
|
||||||
auth_conf->sae_require_mfp = 1;
|
auth_conf->sae_require_mfp = 1;
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
@@ -222,6 +221,17 @@ void *hostap_init(void)
|
|||||||
|
|
||||||
return (void *)hapd;
|
return (void *)hapd;
|
||||||
fail:
|
fail:
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (hapd->sta_list_lock) {
|
||||||
|
wpa3_hostap_auth_deinit();
|
||||||
|
if (g_wpa3_hostap_auth_api_lock &&
|
||||||
|
WPA3_HOSTAP_AUTH_API_LOCK() == pdTRUE) {
|
||||||
|
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
||||||
|
}
|
||||||
|
os_mutex_delete(hapd->sta_list_lock);
|
||||||
|
hapd->sta_list_lock = NULL;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
if (hapd->conf->ssid.wpa_passphrase != NULL) {
|
if (hapd->conf->ssid.wpa_passphrase != NULL) {
|
||||||
os_free(hapd->conf->ssid.wpa_passphrase);
|
os_free(hapd->conf->ssid.wpa_passphrase);
|
||||||
}
|
}
|
||||||
@@ -251,19 +261,21 @@ void hostapd_cleanup(struct hostapd_data *hapd)
|
|||||||
hapd->conf = NULL;
|
hapd->conf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hapd->sta_list_lock) {
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
|
|
||||||
struct hostapd_sae_commit_queue *q, *tmp;
|
struct hostapd_sae_commit_queue *q, *tmp;
|
||||||
|
|
||||||
if (!dl_list_empty(&hapd->sae_commit_queue)) {
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
dl_list_for_each_safe(q, tmp, &hapd->sae_commit_queue,
|
dl_list_for_each_safe(q, tmp, &hapd->sae_commit_queue,
|
||||||
struct hostapd_sae_commit_queue, list) {
|
struct hostapd_sae_commit_queue, list) {
|
||||||
dl_list_del(&q->list);
|
dl_list_del(&q->list);
|
||||||
os_free(q);
|
os_free(q);
|
||||||
}
|
}
|
||||||
}
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
os_mutex_delete(hapd->sta_list_lock);
|
||||||
|
hapd->sta_list_lock = NULL;
|
||||||
|
}
|
||||||
#ifdef CONFIG_WPS_REGISTRAR
|
#ifdef CONFIG_WPS_REGISTRAR
|
||||||
if (esp_wifi_get_wps_type_internal () != WPS_TYPE_DISABLE ||
|
if (esp_wifi_get_wps_type_internal () != WPS_TYPE_DISABLE ||
|
||||||
esp_wifi_get_wps_status_internal() != WPS_STATUS_DISABLE) {
|
esp_wifi_get_wps_status_internal() != WPS_STATUS_DISABLE) {
|
||||||
@@ -455,14 +467,31 @@ send_resp:
|
|||||||
#ifdef CONFIG_WPS_REGISTRAR
|
#ifdef CONFIG_WPS_REGISTRAR
|
||||||
static void ap_free_sta_timeout(void *ctx, void *data)
|
static void ap_free_sta_timeout(void *ctx, void *data)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = (struct hostapd_data *) ctx;
|
struct hostapd_data *hapd = (struct hostapd_data *)ctx;
|
||||||
u8 *addr = (u8 *) data;
|
u8 *addr = (u8 *)data;
|
||||||
struct sta_info *sta = ap_get_sta(hapd, addr);
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
sta = ap_get_sta_internal(hapd, addr);
|
||||||
if (sta) {
|
if (sta) {
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (sta->lock) {
|
||||||
|
if (os_semphr_take(sta->lock, 0)) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
} else {
|
||||||
|
sta->remove_pending = true;
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
|
} else {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
os_free(addr);
|
os_free(addr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -470,42 +499,51 @@ static void ap_free_sta_timeout(void *ctx, void *data)
|
|||||||
bool wpa_ap_remove(u8* bssid)
|
bool wpa_ap_remove(u8* bssid)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = hostapd_get_hapd_data();
|
struct hostapd_data *hapd = hostapd_get_hapd_data();
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
if (!hapd) {
|
if (!hapd) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct sta_info *sta = ap_get_sta(hapd, bssid);
|
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
sta = ap_get_sta_internal(hapd, bssid);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
|
||||||
if (sta->lock) {
|
|
||||||
if (os_semphr_take(sta->lock, 0)) {
|
|
||||||
ap_free_sta(hapd, sta);
|
|
||||||
} else {
|
|
||||||
sta->remove_pending = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SAE */
|
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_REGISTRAR
|
#ifdef CONFIG_WPS_REGISTRAR
|
||||||
wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status());
|
|
||||||
if (wps_get_status() == WPS_STATUS_PENDING) {
|
if (wps_get_status() == WPS_STATUS_PENDING) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
u8 *addr = os_malloc(ETH_ALEN);
|
u8 *addr = os_malloc(ETH_ALEN);
|
||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
os_memcpy(addr, sta->addr, ETH_ALEN);
|
os_memcpy(addr, bssid, ETH_ALEN);
|
||||||
if (eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr) != 0) {
|
if (eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr) != 0) {
|
||||||
os_free(addr);
|
os_free(addr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else
|
return true;
|
||||||
#endif
|
}
|
||||||
ap_free_sta(hapd, sta);
|
#endif /* CONFIG_WPS_REGISTRAR */
|
||||||
|
|
||||||
|
#ifdef CONFIG_SAE
|
||||||
|
if (sta->lock) {
|
||||||
|
if (os_semphr_take(sta->lock, 0)) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
} else {
|
||||||
|
sta->remove_pending = true;
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,11 @@ static esp_err_t wpa3_build_sae_confirm(void)
|
|||||||
|
|
||||||
void esp_wpa3_free_sae_data(void)
|
void esp_wpa3_free_sae_data(void)
|
||||||
{
|
{
|
||||||
|
if (g_sae_token) {
|
||||||
|
wpabuf_free(g_sae_token);
|
||||||
|
g_sae_token = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_sae_commit) {
|
if (g_sae_commit) {
|
||||||
wpabuf_free(g_sae_commit);
|
wpabuf_free(g_sae_commit);
|
||||||
g_sae_commit = NULL;
|
g_sae_commit = NULL;
|
||||||
@@ -433,13 +438,20 @@ int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data)
|
|||||||
wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found");
|
wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
if (evt.id == SIG_WPA3_RX_CONFIRM || evt.id == SIG_TASK_DEL) {
|
if (evt.id == SIG_WPA3_RX_CONFIRM) {
|
||||||
/* prioritising confirm for completing handshake for committed sta */
|
/* prioritising confirm for completing handshake for committed sta */
|
||||||
if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
|
if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
|
||||||
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
||||||
wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
|
wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
} else if (evt.id == SIG_TASK_DEL) {
|
||||||
|
/* wait for portMAX_DELAY as sometimes queue might be full */
|
||||||
|
if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY) != pdPASS) {
|
||||||
|
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
||||||
|
wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
|
if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
|
||||||
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
WPA3_HOSTAP_AUTH_API_UNLOCK();
|
||||||
@@ -460,17 +472,26 @@ static void wpa3_process_rx_commit(wpa3_hostap_auth_event_t *evt)
|
|||||||
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();
|
||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!hapd || !hapd->sta_list_lock) {
|
||||||
|
wpa_printf(MSG_ERROR, "hapd or sta_list_lock not initialized in %s", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
frm = dl_list_first(&hapd->sae_commit_queue,
|
frm = dl_list_first(&hapd->sae_commit_queue,
|
||||||
struct hostapd_sae_commit_queue, list);
|
struct hostapd_sae_commit_queue, list);
|
||||||
if (!frm) {
|
if (!frm) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dl_list_del(&frm->list);
|
dl_list_del(&frm->list);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "SAE: Process next available message from queue");
|
wpa_printf(MSG_DEBUG, "SAE: Process next available message from queue");
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, frm->bssid);
|
sta = ap_get_sta_internal(hapd, frm->bssid);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
sta = ap_sta_add(hapd, frm->bssid);
|
sta = ap_sta_add(hapd, frm->bssid);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
|
wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
|
||||||
@@ -480,17 +501,28 @@ static void wpa3_process_rx_commit(wpa3_hostap_auth_event_t *evt)
|
|||||||
0) != 0) {
|
0) != 0) {
|
||||||
wpa_printf(MSG_INFO, "esp_send_sae_auth_reply: send failed");
|
wpa_printf(MSG_INFO, "esp_send_sae_auth_reply: send failed");
|
||||||
}
|
}
|
||||||
goto free;
|
os_free(frm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
sta = ap_get_sta_internal(hapd, frm->bssid);
|
||||||
|
if (!sta) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
os_free(frm);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->lock && os_semphr_take(sta->lock, 0)) {
|
if (sta->lock && os_semphr_take(sta->lock, 0)) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
sta->sae_commit_processing = true;
|
sta->sae_commit_processing = true;
|
||||||
ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
|
ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
|
||||||
|
|
||||||
if (sta->remove_pending) {
|
if (sta->remove_pending) {
|
||||||
ap_free_sta(hapd, sta);
|
ap_free_sta(hapd, sta);
|
||||||
goto free;
|
os_free(frm);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
sta->sae_commit_processing = false;
|
sta->sae_commit_processing = false;
|
||||||
os_semphr_give(sta->lock);
|
os_semphr_give(sta->lock);
|
||||||
@@ -502,9 +534,11 @@ static void wpa3_process_rx_commit(wpa3_hostap_auth_event_t *evt)
|
|||||||
esp_wifi_ap_deauth_internal(frm->bssid, ret);
|
esp_wifi_ap_deauth_internal(frm->bssid, ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
os_free(frm);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
free:
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
os_free(frm);
|
os_free(frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,45 +548,70 @@ static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt)
|
|||||||
struct sta_info *sta = NULL;
|
struct sta_info *sta = NULL;
|
||||||
int ret = WLAN_STATUS_SUCCESS;
|
int ret = WLAN_STATUS_SUCCESS;
|
||||||
struct sae_hostap_confirm_data *frm = (struct sae_hostap_confirm_data *)evt->data;
|
struct sae_hostap_confirm_data *frm = (struct sae_hostap_confirm_data *)evt->data;
|
||||||
|
|
||||||
if (!frm) {
|
if (!frm) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sta = ap_get_sta(hapd, frm->bssid);
|
|
||||||
if (!sta) {
|
if (!hapd || !hapd->sta_list_lock) {
|
||||||
|
wpa_printf(MSG_ERROR, "hapd or sta_list_lock not initialized in %s", __func__);
|
||||||
os_free(frm);
|
os_free(frm);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta->lock && os_semphr_take(sta->lock, 0)) {
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
|
sta = ap_get_sta_internal(hapd, frm->bssid);
|
||||||
|
if (!sta) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
os_free(frm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (sta->remove_pending) {
|
if (!sta->lock) {
|
||||||
|
wpa_printf(MSG_DEBUG, "SAE: sta->lock is NULL for " MACSTR, MAC2STR(frm->bssid));
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
os_free(frm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (os_semphr_take(sta->lock, 0) != pdTRUE) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
os_free(frm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
|
ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
|
||||||
|
|
||||||
|
if (sta->remove_pending) {
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
ap_free_sta(hapd, sta);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (ret == WLAN_STATUS_SUCCESS) {
|
if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) {
|
||||||
if (sta->sae_data && esp_send_sae_auth_reply(hapd, sta->addr, frm->bssid, WLAN_AUTH_SAE, 2,
|
ap_free_sta(hapd, sta);
|
||||||
WLAN_STATUS_SUCCESS, wpabuf_head(sta->sae_data), wpabuf_len(sta->sae_data)) != ESP_OK) {
|
goto done;
|
||||||
ap_free_sta(hapd, sta);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) {
|
|
||||||
ap_free_sta(hapd, sta);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
os_semphr_give(sta->lock);
|
os_semphr_give(sta->lock);
|
||||||
if (ret != WLAN_STATUS_SUCCESS) {
|
} else {
|
||||||
uint16_t aid = 0;
|
uint16_t aid = 0;
|
||||||
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);
|
os_semphr_give(sta->lock);
|
||||||
} else {
|
esp_wifi_ap_deauth_internal(frm->bssid, ret);
|
||||||
if (sta && sta->sae_data) {
|
} else {
|
||||||
wpabuf_free(sta->sae_data);
|
if (sta->sae_data) {
|
||||||
sta->sae_data = NULL;
|
wpabuf_free(sta->sae_data);
|
||||||
}
|
sta->sae_data = NULL;
|
||||||
}
|
}
|
||||||
|
os_semphr_give(sta->lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
@@ -607,22 +666,33 @@ static void esp_wpa3_hostap_task(void *pvParameters)
|
|||||||
|
|
||||||
int wpa3_hostap_auth_init(void *data)
|
int wpa3_hostap_auth_init(void *data)
|
||||||
{
|
{
|
||||||
|
struct hostapd_data *hapd = (struct hostapd_data *)data;
|
||||||
if (g_wpa3_hostap_evt_queue) {
|
if (g_wpa3_hostap_evt_queue) {
|
||||||
wpa_printf(MSG_ERROR, "esp_wpa3_hostap_task has already been initialised");
|
wpa_printf(MSG_ERROR, "esp_wpa3_hostap_task has already been initialised");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hapd->sta_list_lock = os_mutex_create();
|
||||||
|
if (!hapd->sta_list_lock) {
|
||||||
|
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create sta_list_lock");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_wpa3_hostap_auth_api_lock == NULL) {
|
if (g_wpa3_hostap_auth_api_lock == NULL) {
|
||||||
g_wpa3_hostap_auth_api_lock = os_semphr_create(1, 1);
|
g_wpa3_hostap_auth_api_lock = os_semphr_create(1, 1);
|
||||||
if (!g_wpa3_hostap_auth_api_lock) {
|
if (!g_wpa3_hostap_auth_api_lock) {
|
||||||
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create WPA3 hostap auth API lock");
|
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create WPA3 hostap auth API lock");
|
||||||
|
os_mutex_delete(hapd->sta_list_lock);
|
||||||
|
hapd->sta_list_lock = NULL;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_wpa3_hostap_evt_queue = os_queue_create(10, sizeof(wpa3_hostap_auth_event_t));
|
g_wpa3_hostap_evt_queue = os_queue_create(10, sizeof(wpa3_hostap_auth_event_t));
|
||||||
if (!g_wpa3_hostap_evt_queue) {
|
if (!g_wpa3_hostap_evt_queue) {
|
||||||
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create queue");
|
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create queue");
|
||||||
|
os_mutex_delete(hapd->sta_list_lock);
|
||||||
|
hapd->sta_list_lock = NULL;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,9 +703,13 @@ int wpa3_hostap_auth_init(void *data)
|
|||||||
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create task");
|
wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create task");
|
||||||
os_queue_delete(g_wpa3_hostap_evt_queue);
|
os_queue_delete(g_wpa3_hostap_evt_queue);
|
||||||
g_wpa3_hostap_evt_queue = NULL;
|
g_wpa3_hostap_evt_queue = NULL;
|
||||||
|
os_mutex_delete(hapd->sta_list_lock);
|
||||||
|
hapd->sta_list_lock = NULL;
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl_list_init(&hapd->sae_commit_queue);
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,16 +729,25 @@ static int wpa3_hostap_handle_auth(u8 *buf, size_t len, u32 auth_transaction, u1
|
|||||||
if (!hapd) {
|
if (!hapd) {
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
struct sta_info *sta = ap_get_sta(hapd, bssid);
|
|
||||||
if (auth_transaction == SAE_MSG_COMMIT) {
|
if (auth_transaction == SAE_MSG_COMMIT) {
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
struct sta_info *sta = ap_get_sta_internal(hapd, bssid);
|
||||||
if (sta && sta->sae_commit_processing) {
|
if (sta && sta->sae_commit_processing) {
|
||||||
/* Ignore commit msg as we are already processing commit msg for this station */
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return auth_sae_queue(hapd, buf, len, bssid, status, auth_transaction);
|
return auth_sae_queue(hapd, buf, len, bssid, status, auth_transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sta && auth_transaction == SAE_MSG_CONFIRM) {
|
if (auth_transaction == SAE_MSG_CONFIRM) {
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
bool sta_exists = (ap_get_sta_internal(hapd, bssid) != NULL);
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
if (!sta_exists) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
struct sae_hostap_confirm_data *frm = os_malloc(sizeof(struct sae_hostap_confirm_data) + len);
|
struct sae_hostap_confirm_data *frm = os_malloc(sizeof(struct sae_hostap_confirm_data) + len);
|
||||||
if (!frm) {
|
if (!frm) {
|
||||||
wpa_printf(MSG_ERROR, "failed to allocate memory for confirm event");
|
wpa_printf(MSG_ERROR, "failed to allocate memory for confirm event");
|
||||||
|
|||||||
@@ -107,6 +107,10 @@ struct hostapd_data {
|
|||||||
struct sta_info *sta_hash[STA_HASH_SIZE];
|
struct sta_info *sta_hash[STA_HASH_SIZE];
|
||||||
int num_sta; /* number of entries in sta_list */
|
int num_sta; /* number of entries in sta_list */
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
void *sta_list_lock;
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
|
|
||||||
struct eapol_authenticator *eapol_auth;
|
struct eapol_authenticator *eapol_auth;
|
||||||
struct wpa_authenticator *wpa_auth;
|
struct wpa_authenticator *wpa_auth;
|
||||||
|
|
||||||
@@ -169,4 +173,21 @@ const struct hostapd_eap_user *
|
|||||||
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
|
||||||
size_t identity_len, int phase2);
|
size_t identity_len, int phase2);
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
#define HOSTAPD_STA_LIST_LOCK(hapd) \
|
||||||
|
do { \
|
||||||
|
if ((hapd) && (hapd)->sta_list_lock) \
|
||||||
|
os_mutex_lock((hapd)->sta_list_lock); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define HOSTAPD_STA_LIST_UNLOCK(hapd) \
|
||||||
|
do { \
|
||||||
|
if ((hapd) && (hapd)->sta_list_lock) \
|
||||||
|
os_mutex_unlock((hapd)->sta_list_lock); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define HOSTAPD_STA_LIST_LOCK(hapd) do { } while (0)
|
||||||
|
#define HOSTAPD_STA_LIST_UNLOCK(hapd) do { } while (0)
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
|
|
||||||
#endif /* HOSTAPD_H */
|
#endif /* HOSTAPD_H */
|
||||||
|
|||||||
@@ -203,6 +203,10 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
|
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
if (sta->sae &&
|
if (sta->sae &&
|
||||||
(sta->sae->state == SAE_COMMITTED ||
|
(sta->sae->state == SAE_COMMITTED ||
|
||||||
@@ -210,6 +214,9 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
|
|||||||
open++;
|
open++;
|
||||||
}
|
}
|
||||||
if (open >= hapd->conf->sae_anti_clogging_threshold) {
|
if (open >= hapd->conf->sae_anti_clogging_threshold) {
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,9 +226,16 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd)
|
|||||||
* potentially result in too many open sessions. */
|
* potentially result in too many open sessions. */
|
||||||
if (open + dl_list_len(&hapd->sae_commit_queue) >=
|
if (open + dl_list_len(&hapd->sae_commit_queue) >=
|
||||||
hapd->conf->sae_anti_clogging_threshold) {
|
hapd->conf->sae_anti_clogging_threshold) {
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -680,11 +694,23 @@ int auth_sae_queue(struct hostapd_data *hapd,
|
|||||||
struct hostapd_sae_commit_queue *q, *q2;
|
struct hostapd_sae_commit_queue *q, *q2;
|
||||||
unsigned int queue_len;
|
unsigned int queue_len;
|
||||||
|
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
if (!hapd->sta_list_lock) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"SAE: sta_list_lock not set (no WPA3 hostap path), drop from " MACSTR,
|
||||||
|
MAC2STR(bssid));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
queue_len = dl_list_len(&hapd->sae_commit_queue);
|
queue_len = dl_list_len(&hapd->sae_commit_queue);
|
||||||
if (queue_len >= hapd->conf->max_num_sta) {
|
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));
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,6 +719,9 @@ int auth_sae_queue(struct hostapd_data *hapd,
|
|||||||
queue_len);
|
queue_len);
|
||||||
q = os_zalloc(sizeof(*q) + len);
|
q = os_zalloc(sizeof(*q) + len);
|
||||||
if (!q) {
|
if (!q) {
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,11 +759,13 @@ queued:
|
|||||||
if (wpa3_hostap_post_evt(SIG_WPA3_RX_COMMIT, 0) != 0) {
|
if (wpa3_hostap_post_evt(SIG_WPA3_RX_COMMIT, 0) != 0) {
|
||||||
wpa_printf(MSG_ERROR, "failed to queue commit build event");
|
wpa_printf(MSG_ERROR, "failed to queue commit build event");
|
||||||
dl_list_del(&q->list);
|
dl_list_del(&q->list);
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
os_free(q);
|
os_free(q);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
#endif /* ESP_SUPPLICANT */
|
#endif /* ESP_SUPPLICANT */
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,17 +23,30 @@
|
|||||||
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
|
static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
|
||||||
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
|
void hostapd_wps_eap_completed(struct hostapd_data *hapd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAUTION: cb is invoked while HOSTAPD_STA_LIST_LOCK is held.
|
||||||
|
* The mutex is non-recursive (os_mutex_create), so cb must NEVER
|
||||||
|
* call ap_get_sta, ap_free_sta, ap_sta_add, or any other function
|
||||||
|
* that acquires HOSTAPD_STA_LIST_LOCK — doing so will deadlock.
|
||||||
|
* Use the lock-free variants (e.g. ap_get_sta_internal) if needed.
|
||||||
|
*/
|
||||||
int ap_for_each_sta(struct hostapd_data *hapd,
|
int ap_for_each_sta(struct hostapd_data *hapd,
|
||||||
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
void *ctx),
|
void *ctx),
|
||||||
void *ctx)
|
void *ctx)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
if (cb(hapd, sta, ctx))
|
if (cb(hapd, sta, ctx)) {
|
||||||
return 1;
|
ret = 1;
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -43,9 +56,11 @@ struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
|
|||||||
{
|
{
|
||||||
struct sta_info *s;
|
struct sta_info *s;
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
s = hapd->sta_hash[STA_HASH(sta)];
|
s = hapd->sta_hash[STA_HASH(sta)];
|
||||||
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
|
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
|
||||||
s = s->hnext;
|
s = s->hnext;
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +84,17 @@ static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
tmp->next = sta->next;
|
tmp->next = sta->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Caller MUST hold HOSTAPD_STA_LIST_LOCK (see sta_info.h). */
|
||||||
|
struct sta_info * ap_get_sta_internal(struct hostapd_data *hapd, const u8 *sta)
|
||||||
|
{
|
||||||
|
struct sta_info *s;
|
||||||
|
|
||||||
|
s = hapd->sta_hash[STA_HASH(sta)];
|
||||||
|
while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
|
||||||
|
s = s->hnext;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
|
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
{
|
{
|
||||||
@@ -100,10 +126,12 @@ static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
|
|
||||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
{
|
{
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
ap_sta_hash_del(hapd, sta);
|
ap_sta_hash_del(hapd, sta);
|
||||||
ap_sta_list_del(hapd, sta);
|
ap_sta_list_del(hapd, sta);
|
||||||
|
|
||||||
hapd->num_sta--;
|
hapd->num_sta--;
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
sae_clear_data(sta->sae);
|
sae_clear_data(sta->sae);
|
||||||
@@ -113,10 +141,12 @@ 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;
|
||||||
}
|
}
|
||||||
|
#ifdef ESP_SUPPLICANT
|
||||||
if (sta->sae_data) {
|
if (sta->sae_data) {
|
||||||
wpabuf_free(sta->sae_data);
|
wpabuf_free(sta->sae_data);
|
||||||
sta->sae_data = NULL;
|
sta->sae_data = NULL;
|
||||||
}
|
}
|
||||||
|
#endif /* ESP_SUPPLICANT */
|
||||||
#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
|
||||||
@@ -132,18 +162,28 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Called during teardown after WPA3 task is stopped, so sta->lock is always available. */
|
||||||
void hostapd_free_stas(struct hostapd_data *hapd)
|
void hostapd_free_stas(struct hostapd_data *hapd)
|
||||||
{
|
{
|
||||||
struct sta_info *sta, *prev;
|
struct sta_info *sta;
|
||||||
|
|
||||||
sta = hapd->sta_list;
|
while (1) {
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
while (sta) {
|
sta = hapd->sta_list;
|
||||||
prev = sta;
|
if (!sta) {
|
||||||
sta = sta->next;
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
|
break;
|
||||||
MAC2STR(prev->addr));
|
}
|
||||||
ap_free_sta(hapd, prev);
|
#ifdef CONFIG_SAE
|
||||||
|
if (sta->lock) {
|
||||||
|
os_semphr_take(sta->lock, OS_BLOCK);
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_SAE */
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
ap_free_sta(hapd, sta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,35 +192,48 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
|||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, addr);
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
if (sta)
|
sta = ap_get_sta_internal(hapd, addr);
|
||||||
|
if (sta) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return sta;
|
return sta;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, " New STA");
|
wpa_printf(MSG_DEBUG, " New STA");
|
||||||
if (hapd->num_sta >= hapd->conf->max_num_sta) {
|
if (hapd->num_sta >= hapd->conf->max_num_sta) {
|
||||||
/* FIX: might try to remove some old STAs first? */
|
|
||||||
wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
|
wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
|
||||||
hapd->num_sta, hapd->conf->max_num_sta);
|
hapd->num_sta, hapd->conf->max_num_sta);
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sta = os_zalloc(sizeof(struct sta_info));
|
sta = os_zalloc(sizeof(struct sta_info));
|
||||||
if (sta == NULL) {
|
if (sta == NULL) {
|
||||||
wpa_printf(MSG_ERROR, "malloc failed");
|
wpa_printf(MSG_ERROR, "malloc failed");
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize STA info data */
|
/* initialize STA info data */
|
||||||
os_memcpy(sta->addr, addr, ETH_ALEN);
|
os_memcpy(sta->addr, addr, ETH_ALEN);
|
||||||
sta->next = hapd->sta_list;
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
sta->sae_commit_processing = false;
|
sta->sae_commit_processing = false;
|
||||||
sta->remove_pending = false;
|
sta->remove_pending = false;
|
||||||
sta->lock = os_semphr_create(1, 1);
|
sta->lock = os_semphr_create(1, 1);
|
||||||
|
if (!sta->lock) {
|
||||||
|
wpa_printf(MSG_ERROR, "Failed to create sta->lock for " MACSTR,
|
||||||
|
MAC2STR(addr));
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
os_free(sta);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
|
sta->next = hapd->sta_list;
|
||||||
hapd->sta_list = sta;
|
hapd->sta_list = sta;
|
||||||
hapd->num_sta++;
|
hapd->num_sta++;
|
||||||
ap_sta_hash_add(hapd, sta);
|
ap_sta_hash_add(hapd, sta);
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
|
||||||
return sta;
|
return sta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ struct sta_info {
|
|||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
void *lock;
|
void *lock;
|
||||||
struct sae_data *sae;
|
struct sae_data *sae;
|
||||||
bool sae_commit_processing; /* halt queuing commit while we are
|
volatile bool sae_commit_processing; /* halt queuing commit while we are
|
||||||
* processing commit for that station */
|
* processing commit for that station */
|
||||||
bool remove_pending; /* Flag to indicate to free station when
|
volatile 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;
|
struct wpabuf *sae_data;
|
||||||
#endif /* CONFIG_SAE */
|
#endif /* CONFIG_SAE */
|
||||||
@@ -96,6 +96,8 @@ int ap_for_each_sta(struct hostapd_data *hapd,
|
|||||||
void *ctx),
|
void *ctx),
|
||||||
void *ctx);
|
void *ctx);
|
||||||
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
|
struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta);
|
||||||
|
/* Caller must hold HOSTAPD_STA_LIST_LOCK(hapd) for the duration of the lookup. */
|
||||||
|
struct sta_info * ap_get_sta_internal(struct hostapd_data *hapd, const u8 *sta);
|
||||||
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
|
void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
|
||||||
void hostapd_free_stas(struct hostapd_data *hapd);
|
void hostapd_free_stas(struct hostapd_data *hapd);
|
||||||
|
|||||||
@@ -210,10 +210,30 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr,
|
|||||||
return hostapd_send_eapol(wpa_auth->addr, addr, data, data_len);
|
return hostapd_send_eapol(wpa_auth->addr, addr, data, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAUTION: cb is invoked while HOSTAPD_STA_LIST_LOCK is held.
|
||||||
|
* The mutex is non-recursive, so cb must NEVER call any function
|
||||||
|
* that acquires HOSTAPD_STA_LIST_LOCK (e.g. ap_get_sta, ap_free_sta)
|
||||||
|
* — doing so will deadlock.
|
||||||
|
*/
|
||||||
int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
|
int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth,
|
||||||
int (*cb)(struct wpa_state_machine *sm, void *ctx),
|
int (*cb)(struct wpa_state_machine *sm, void *ctx),
|
||||||
void *cb_ctx)
|
void *cb_ctx)
|
||||||
{
|
{
|
||||||
|
struct hostapd_data *hapd = hostapd_get_hapd_data();
|
||||||
|
struct sta_info *sta;
|
||||||
|
|
||||||
|
if (hapd == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
HOSTAPD_STA_LIST_LOCK(hapd);
|
||||||
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
|
if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) {
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HOSTAPD_STA_LIST_UNLOCK(hapd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user