@@ -83,7 +83,8 @@ static void pasn_fils_auth_resp(struct hostapd_data *hapd,
static void handle_auth(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int rssi, int from_queue);
-
+static int add_associated_sta(struct hostapd_data *hapd,
+ struct sta_info *sta, int reassoc);
u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
{
@@ -3785,7 +3786,8 @@ static bool check_sa_query(struct hostapd_data *hapd, struct sta_info *sta,
static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ies, size_t ies_len,
- struct ieee802_11_elems *elems, int reassoc)
+ struct ieee802_11_elems *elems, int reassoc,
+ bool link)
{
int resp;
const u8 *wpa_ie;
@@ -3887,6 +3889,14 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
elems->eht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
+
+ if (!link) {
+ resp = hostapd_process_ml_assoc_req(hapd,
+ elems,
+ sta);
+ if (resp != WLAN_STATUS_SUCCESS)
+ return resp;
+ }
}
#endif /* CONFIG_IEEE80211BE */
@@ -4246,7 +4256,253 @@ static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
- return __check_assoc_ies(hapd, sta, ies, ies_len, &elems, reassoc);
+ return __check_assoc_ies(hapd, sta, ies, ies_len, &elems, reassoc,
+ false);
+}
+
+
+#ifdef CONFIG_IEEE80211BE
+
+static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
+ u16 status_code,
+ u8 *buf, size_t buflen)
+{
+ u8 *p = buf;
+
+ /* capability info */
+ WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
+ p += 2;
+
+ /* status code */
+ WPA_PUT_LE16(p, status_code);
+ p += 2;
+
+ if (status_code != WLAN_STATUS_SUCCESS)
+ goto out;
+
+ /* AID is not included */
+ p = hostapd_eid_supp_rates(hapd, p);
+ p = hostapd_eid_ext_supp_rates(hapd, p);
+ p = hostapd_eid_rm_enabled_capab(hapd, p, buf + buflen - p);
+ p = hostapd_eid_ht_capabilities(hapd, p);
+ p = hostapd_eid_ht_operation(hapd, p);
+
+ if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
+ p = hostapd_eid_vht_capabilities(hapd, p, 0);
+ p = hostapd_eid_vht_operation(hapd, p);
+ }
+
+ if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
+ p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
+ p = hostapd_eid_he_operation(hapd, p);
+ p = hostapd_eid_spatial_reuse(hapd, p);
+ p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
+ p = hostapd_eid_he_6ghz_band_cap(hapd, p);
+ if (hapd->iconf->ieee80211be && !hapd->conf->disable_11be) {
+ p = hostapd_eid_eht_capab(hapd, p, IEEE80211_MODE_AP);
+ p = hostapd_eid_eht_operation(hapd, p);
+ }
+ }
+
+ p = hostapd_eid_ext_capab(hapd, p, false);
+ p = hostapd_eid_mbo(hapd, p, buf + buflen - p);
+ p = hostapd_eid_wmm(hapd, p);
+
+ if (hapd->conf->assocresp_elements &&
+ (size_t)(buf + buflen - p) >=
+ wpabuf_len(hapd->conf->assocresp_elements)) {
+ os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
+ wpabuf_len(hapd->conf->assocresp_elements));
+ p += wpabuf_len(hapd->conf->assocresp_elements);
+ }
+
+out:
+ return p - buf;
+}
+
+
+static void ieee80211_ml_process_link(struct hostapd_data *hapd,
+ struct sta_info *origin_sta,
+ struct mld_link_info *link,
+ const u8 *ies, size_t ies_len,
+ int reassoc)
+{
+ struct ieee802_11_elems elems;
+ struct wpabuf *mlbuf = NULL;
+ struct sta_info *sta = NULL;
+ u16 status = WLAN_STATUS_SUCCESS;
+
+ wpa_printf(MSG_INFO, "MLD: link: link_id=%u, peer=" MACSTR,
+ hapd->mld_link_id, MAC2STR(link->peer_addr));
+
+ if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG, "MLD: link: failed parsing");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto out;
+ }
+
+ sta = ap_get_sta(hapd, origin_sta->addr);
+ if (sta) {
+ wpa_printf(MSG_INFO, "MLD: link: station already exists");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ sta = NULL;
+ goto out;
+ }
+
+ sta = ap_sta_add(hapd, origin_sta->addr);
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "MLD: link: ap_sta_add() failed");
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto out;
+ }
+
+ mlbuf = ieee802_11_defrag_mle(&elems, MULTI_LINK_CONTROL_TYPE_BASIC);
+
+ if (!mlbuf)
+ goto out;
+
+ if (ParseOK != ieee802_11_parse_link_assoc_req(ies, ies_len, &elems,
+ mlbuf,
+ hapd->mld_link_id,
+ true)) {
+ wpa_printf(MSG_DEBUG, "MLD: link: assoc_req parse failed");
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+ goto out;
+ }
+
+ sta->flags |= origin_sta->flags | WLAN_STA_ASSOC_REQ_OK;
+ status = __check_assoc_ies(hapd, sta, NULL, 0, &elems, reassoc, true);
+ if (status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "MLD: link: element check failed");
+ goto out;
+ }
+
+ sta->mld_info.mld_sta = true;
+ sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
+
+ os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
+
+ /*
+ * Get the AID from the station on which the association was preformed,
+ * and mark it as used.
+ */
+ sta->aid = origin_sta->aid;
+ hapd->sta_aid[(sta->aid - 1) / 32] |= BIT((sta->aid - 1) % 32);
+ sta->listen_interval = origin_sta->listen_interval;
+ update_ht_state(hapd, sta);
+
+ /* WPA authenticator should always be the one on the original station */
+ wpa_auth_sta_deinit(sta->wpa_sm);
+ sta->wpa_sm = NULL;
+
+ /*
+ * Do not initialize the EAPOL state machine.
+ * TODO: maybe it is needed?
+ */
+ sta->eapol_sm = NULL;
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: link=%u, association OK (aid=%u)",
+ hapd->mld_link_id, sta->aid);
+
+ /*
+ * Get RSN and RSNXE elements for the current BSS as they are required
+ * by the authenticator
+ */
+ link->rsne = hostapd_wpa_ie(hapd, WLAN_EID_RSN);
+ link->rsnxe = hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
+
+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC_REQ_OK;
+
+ /* TODO: What other processing is required? */
+
+ if (add_associated_sta(hapd, sta, reassoc))
+ status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+out:
+ wpabuf_free(mlbuf);
+ link->status = status;
+
+ wpa_printf(MSG_DEBUG, "MLD: link: status=%u", status);
+ if (sta && status != WLAN_STATUS_SUCCESS)
+ ap_free_sta(hapd, sta);
+
+ link->resp_sta_profile_len =
+ ieee80211_ml_build_assoc_resp(hapd, link->status,
+ link->resp_sta_profile,
+ sizeof(link->resp_sta_profile));
+}
+
+static bool hostapd_is_mld_ap(struct hostapd_data *hapd)
+{
+ if (!hapd->conf->mld_ap)
+ return false;
+
+ if (!hapd->iface || !hapd->iface->interfaces ||
+ hapd->iface->interfaces->count <= 1)
+ return false;
+
+ return true;
+}
+
+#endif /* CONFIG_IEEE80211BE */
+
+static void hostapd_process_assoc_ml_info(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ const u8 *ies, size_t ies_len,
+ int reassoc)
+{
+#ifdef CONFIG_IEEE80211BE
+ u8 i, j;
+
+ if (!hostapd_is_mld_ap(hapd))
+ return;
+
+ /*
+ * This is not really needed, but make the interaction with the WPA
+ * authenticator more consistent
+ */
+ sta->mld_info.links[hapd->mld_link_id].rsne =
+ hostapd_wpa_ie(hapd, WLAN_EID_RSN);
+ sta->mld_info.links[hapd->mld_link_id].rsnxe =
+ hostapd_wpa_ie(hapd, WLAN_EID_RSNX);
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ struct hostapd_iface *iface = NULL;
+ struct mld_link_info *link = &sta->mld_info.links[i];
+
+ if (!link->valid)
+ continue;
+
+ for (j = 0; j < hapd->iface->interfaces->count; j++) {
+ iface = hapd->iface->interfaces->iface[j];
+
+ if (hapd->iface == iface)
+ continue;
+
+ if (iface->bss[0]->conf->mld_ap &&
+ hapd->conf->mld_id == iface->bss[0]->conf->mld_id &&
+ i == iface->bss[0]->mld_link_id)
+ break;
+ }
+
+ if (!iface || j == hapd->iface->interfaces->count) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: no link match for link_id=%u",
+ i);
+
+ link->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ link->resp_sta_profile_len =
+ ieee80211_ml_build_assoc_resp(hapd,
+ link->status,
+ link->resp_sta_profile,
+ sizeof(link->resp_sta_profile));
+ } else {
+ ieee80211_ml_process_link(iface->bss[0],
+ sta, link,
+ ies, ies_len, reassoc);
+ }
+ }
+#endif /* CONFIG_IEEE80211BE */
}
@@ -5174,6 +5430,9 @@ static void handle_assoc(struct hostapd_data *hapd,
* issues with processing other non-Data Class 3 frames during this
* window.
*/
+ if (resp == WLAN_STATUS_SUCCESS)
+ hostapd_process_assoc_ml_info(hapd, sta, pos, left, reassoc);
+
if (resp == WLAN_STATUS_SUCCESS && sta &&
add_associated_sta(hapd, sta, reassoc))
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
@@ -19,6 +19,7 @@ struct ieee80211_mgmt;
struct radius_sta;
enum ieee80211_op_mode;
enum oper_chan_width;
+struct ieee802_11_elems;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
struct hostapd_frame_info *fi);
@@ -90,6 +91,9 @@ struct wpabuf *hostapd_ml_auth_resp(struct hostapd_data *hapd);
const u8 *hostapd_process_ml_auth(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt,
size_t len);
+u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
+ struct ieee802_11_elems *elems,
+ struct sta_info *sta);
int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta);
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab);
@@ -809,3 +809,295 @@ const u8 *hostapd_process_ml_auth(struct hostapd_data *hapd,
return get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
}
+
+
+static int hostapd_mld_validate_assoc_info(struct hostapd_data *hapd,
+ struct mld_info *info)
+{
+ u8 i, link_id;
+
+ if (!info->mld_sta) {
+ wpa_printf(MSG_DEBUG, "MLD: not an MLD station");
+ return 0;
+ }
+
+ /*
+ * Iterate over the link negotiated in the association request and
+ * validate that they are indeed valid links in the local MLD AP.
+ * While at it, also update the local address for the links in the
+ * mld_info, so it could be easily available for later flows, e.g., for
+ * the WPA authenticator etc.
+ */
+ for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
+ struct hostapd_data *other_hapd;
+
+ if (!info->links[link_id].valid)
+ continue;
+
+ for (i = 0; i < hapd->iface->interfaces->count; i++) {
+ other_hapd = hapd->iface->interfaces->iface[i]->bss[0];
+
+ if (hapd == other_hapd)
+ continue;
+
+ if (other_hapd->conf->mld_ap &&
+ other_hapd->conf->mld_id == hapd->conf->mld_id &&
+ link_id == other_hapd->mld_link_id)
+ break;
+ }
+
+ if (i == hapd->iface->interfaces->count &&
+ link_id != hapd->mld_link_id) {
+ wpa_printf(MSG_DEBUG, "MLD: invalid link ID=%u",
+ link_id);
+ return -1;
+ }
+
+ if (i < hapd->iface->interfaces->count)
+ os_memcpy(info->links[link_id].local_addr,
+ other_hapd->own_addr,
+ ETH_ALEN);
+ }
+
+ return 0;
+}
+
+
+u16 hostapd_process_ml_assoc_req(struct hostapd_data *hapd,
+ struct ieee802_11_elems *elems,
+ struct sta_info *sta)
+{
+ struct wpabuf *mlbuf = ieee802_11_defrag_mle(elems,
+ MULTI_LINK_CONTROL_TYPE_BASIC);
+ struct ieee80211_eht_ml *ml;
+ struct eht_ml_basic_common_info *common_info;
+ size_t ml_len, common_info_len;
+ struct mld_link_info *link_info;
+ struct mld_info *info = &sta->mld_info;
+ u8 *pos;
+ int ret = -1;
+ u16 ml_control;
+
+ if (!mlbuf)
+ return WLAN_STATUS_SUCCESS;
+
+ ml = (struct ieee80211_eht_ml *)wpabuf_head(mlbuf);
+ ml_len = wpabuf_len(mlbuf);
+
+ ml_control = le_to_host16(ml->ml_control);
+ if ((ml_control & MULTI_LINK_CONTROL_TYPE_MASK) != MULTI_LINK_CONTROL_TYPE_BASIC) {
+ wpa_printf(MSG_DEBUG, "MLD: Invalid ML type=%u",
+ ml_control & MULTI_LINK_CONTROL_TYPE_MASK);
+ goto out;
+ }
+
+ /* common info length and MLD address must always be present */
+ common_info_len = 7;
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
+ wpa_printf(MSG_DEBUG, "MLD: link ID info not expected");
+ goto out;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
+ wpa_printf(MSG_DEBUG, "MLD: BSS params change not expected");
+ goto out;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
+ wpa_printf(MSG_DEBUG, "MLD: sync delay not expected");
+ goto out;
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
+ common_info_len += 2;
+ } else {
+ wpa_printf(MSG_DEBUG, "MLD: EML capabilities not present");
+ }
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
+ common_info_len += 2;
+
+ } else {
+ wpa_printf(MSG_DEBUG, "MLD: MLD capabilities not present");
+ goto out;
+ }
+
+ wpa_printf(MSG_DEBUG, "MLD: expected_common_info_len=%lu",
+ common_info_len);
+
+ if (sizeof(*ml) + common_info_len > ml_len) {
+ wpa_printf(MSG_DEBUG, "MLD: not enough bytes for common info");
+ goto out;
+ }
+
+ common_info = (struct eht_ml_basic_common_info *)ml->variable;
+
+ /* common information length includes the length octet */
+ if (common_info->len != common_info_len) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: invalid common info len=%u", common_info->len);
+ goto out;
+ }
+
+ pos = common_info->variable;
+
+ if (ml_control & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
+ info->common_info.eml_capa = WPA_GET_LE16(pos);
+ pos += 2;
+ } else {
+ info->common_info.eml_capa = 0;
+ }
+
+ info->common_info.mld_capa = WPA_GET_LE16(pos);
+ pos += 2;
+
+ wpa_printf(MSG_DEBUG,
+ "MLD: addr=" MACSTR ", eml=0x%x, mld=0x%x",
+ MAC2STR(info->common_info.mld_addr),
+ info->common_info.eml_capa, info->common_info.mld_capa);
+
+
+ /* get the MLD Address */
+ if (os_memcmp(info->common_info.mld_addr, common_info->mld_addr,
+ ETH_ALEN)) {
+ wpa_printf(MSG_DEBUG, "MLD: MLD address mismatch with auth");
+ goto out;
+ }
+
+ info->links[hapd->mld_link_id].valid = true;
+
+ /* parse the link info field */
+ ml_len -= (sizeof(*ml) + common_info_len);
+
+ while (ml_len > 2) {
+ size_t sub_elem_len = *(pos + 1);
+ size_t sta_info_len;
+ u16 control;
+
+ wpa_printf(MSG_DEBUG, "MLD: sub element len=%zu",
+ sub_elem_len);
+
+ if (2 + sub_elem_len > ml_len) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: invalid link info len: %zu %zu",
+ 2 + sub_elem_len, ml_len);
+ goto out;
+ }
+
+ if (*pos == WLAN_EID_VENDOR_SPECIFIC) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: skip vendor specific subelement");
+
+ pos += 2 + sub_elem_len;
+ ml_len -= 2 + sub_elem_len;
+ continue;
+ } else if (*pos != 0) {
+ wpa_printf(MSG_DEBUG, "MLD: invalid subelement ID=%u",
+ *pos);
+ goto out;
+ }
+
+ /* skip the subelement ID and the length */
+ pos += 2;
+ ml_len -= 2;
+
+ /* get the station control field */
+ control = WPA_GET_LE16(pos);
+ link_info = &info->links[control & EHT_PER_STA_CTRL_LINK_ID_MSK];
+ pos += 2;
+ ml_len -= 2;
+
+ if (!(control & EHT_PER_STA_CTRL_COMPLETE_PROFILE_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: per STA complete profile expected");
+ goto out;
+ }
+
+ if (!(control & EHT_PER_STA_CTRL_MAC_ADDR_PRESENT_MSK)) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: per STA MAC address not present");
+ goto out;
+ }
+
+ if ((control & (EHT_PER_STA_CTRL_BEACON_INTERVAL_PRESENT_MSK |
+ EHT_PER_STA_CTRL_DTIM_INFO_PRESENT_MSK))) {
+ wpa_printf(MSG_DEBUG,
+ "MLD: beacon/DTIM interval not expected");
+ goto out;
+ }
+
+ /* the length octet and the MAC address must be present */
+ sta_info_len = 1 + ETH_ALEN;
+
+ if (control & EHT_PER_STA_CTRL_NSTR_LINK_PAIR_PRESENT_MSK) {
+ if (control & EHT_PER_STA_CTRL_NSTR_BM_SIZE_MSK)
+ link_info->nstr_bitmap_len = 2;
+ else
+ link_info->nstr_bitmap_len = 1;
+ }
+
+ sta_info_len += link_info->nstr_bitmap_len;
+
+ if (sta_info_len > ml_len || sta_info_len != (*pos)) {
+ wpa_printf(MSG_DEBUG, "MLD: invalid sta info len");
+ goto out;
+ }
+
+ /* skip the length */
+ pos++;
+ ml_len--;
+
+ /* get the link address */
+ os_memcpy(link_info->peer_addr, pos, ETH_ALEN);
+ wpa_printf(MSG_DEBUG,
+ "MLD: assoc: link id=%u, addr=" MACSTR,
+ control & EHT_PER_STA_CTRL_LINK_ID_MSK,
+ MAC2STR(link_info->peer_addr));
+
+ pos += ETH_ALEN;
+ ml_len -= ETH_ALEN;
+
+ /* get the NSTR bitmap */
+ if (link_info->nstr_bitmap_len) {
+ os_memcpy(link_info->nstr_bitmap, pos,
+ link_info->nstr_bitmap_len);
+ pos += link_info->nstr_bitmap_len;
+ ml_len -= link_info->nstr_bitmap_len;
+ }
+
+ sub_elem_len -= sta_info_len + 2;
+
+ wpa_printf(MSG_DEBUG, "MLD: STA profile len=%zu",
+ sub_elem_len);
+
+ if (sub_elem_len > 2)
+ link_info->capability = WPA_GET_LE16(pos);
+
+ pos += sub_elem_len;
+ ml_len -= sub_elem_len;
+
+ wpa_printf(MSG_DEBUG,
+ "link ctrl=0x%x, " MACSTR ", nstr bm len=%lu",
+ control, MAC2STR(link_info->peer_addr),
+ link_info->nstr_bitmap_len);
+
+ link_info->valid = true;
+ }
+
+ if (ml_len) {
+ wpa_printf(MSG_DEBUG, "MLD: %zu bytes left after parsing. fail",
+ ml_len);
+ goto out;
+ }
+
+ ret = hostapd_mld_validate_assoc_info(hapd, info);
+out:
+ wpabuf_free(mlbuf);
+ if (ret) {
+ os_memset(info, 0, sizeof(*info));
+ return WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+ return WLAN_STATUS_SUCCESS;
+}
@@ -298,7 +298,15 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
sae_clear_retransmit_timer(hapd, sta);
ieee802_1x_free_station(hapd, sta);
+
+#ifdef CONFIG_IEEE80211BE
+ if (!hapd->conf->mld_ap || !sta->mld_info.mld_sta ||
+ hapd->mld_link_id == sta->mld_assoc_link_id)
+ wpa_auth_sta_deinit(sta->wpa_sm);
+#else
wpa_auth_sta_deinit(sta->wpa_sm);
+#endif /* CONFIG_IEEE80211BE */
+
rsn_preauth_free_station(hapd, sta);
#ifndef CONFIG_NO_RADIUS
if (hapd->radius)
@@ -863,7 +871,14 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
ap_handle_timer, hapd, sta);
accounting_sta_stop(hapd, sta);
ieee802_1x_free_station(hapd, sta);
+#ifdef CONFIG_IEEE80211BE
+ if (!hapd->conf->mld_ap ||
+ hapd->mld_link_id == sta->mld_assoc_link_id)
+ wpa_auth_sta_deinit(sta->wpa_sm);
+#else
wpa_auth_sta_deinit(sta->wpa_sm);
+#endif /* CONFIG_IEEE80211BE */
+
sta->wpa_sm = NULL;
sta->disassoc_reason = reason;