@@ -6644,7 +6644,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
wpa_auth_sta_ft_tk_already_set(sta->wpa_sm),
wpa_auth_sta_fils_tk_already_set(sta->wpa_sm));
- if (!mld_link_sta && !sta->added_unassoc &&
+ if (!ap_sta_is_mld(hapd, sta) && !sta->added_unassoc &&
(!(sta->flags & WLAN_STA_AUTHORIZED) ||
(reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
(!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
@@ -7601,6 +7601,74 @@ static void handle_assoc(struct hostapd_data *hapd,
}
#endif /* CONFIG_FILS */
+ if ((sta->flags & WLAN_STA_MFP) &&
+ sta->sa_query_timed_out &&
+ sta->mld_info.mld_sta) {
+ struct ieee802_11_elems elems;
+ u8 mld_addr[ETH_ALEN] = {0};
+ /*
+ * Clean up the existing STA info
+ * allowing association with new sta info based on
+ * the association request after the SA Query timeout.
+ */
+ wpa_auth_sta_deinit(sta->wpa_sm);
+ sta->wpa_sm = NULL;
+ clear_wpa_sm_for_each_partner_link(hapd, sta);
+ ap_sta_remove_link_sta(hapd, sta);
+ hostapd_drv_sta_remove(hapd, sta->addr);
+ sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED);
+ ap_sta_set_sa_query_timeout(hapd, sta, 0);
+
+ if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG, "Failed to parse elements");
+ goto fail;
+ }
+
+ os_memset(&sta->mld_info, 0x00, sizeof(sta->mld_info));
+
+ if (!hostapd_process_ml_assoc_req_addr(hapd,
+ elems.basic_mle,
+ elems.basic_mle_len,
+ mld_addr)) {
+ u8 link_id = hapd->mld_link_id;
+
+ sta->mld_info.mld_sta = true;
+ sta->mld_assoc_link_id = link_id;
+
+ os_memcpy(sta->mld_info.common_info.mld_addr, mld_addr,
+ ETH_ALEN);
+ os_memcpy(sta->mld_info.links[link_id].peer_addr,
+ mgmt->sa, ETH_ALEN);
+ os_memcpy(sta->mld_info.links[link_id].local_addr,
+ hapd->own_addr, ETH_ALEN);
+ }
+
+ wpa_printf(MSG_DEBUG, "Allowing association of STA "
+ MACSTR " after timed out SA Query procedure",
+ MAC2STR(sta->addr));
+ if (hostapd_sta_add(hapd, sta->addr, 0, 0,
+ sta->supported_rates,
+ sta->supported_rates_len,
+ 0, NULL, NULL, NULL, 0, NULL, 0,
+ NULL, 0, NULL,
+ sta->flags, 0, 0, 0, 0,
+ mgmt->sa, 0,
+ 0, 0)) {
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
+ HOSTAPD_LEVEL_NOTICE,
+ "Could not add STA to kernel driver");
+ goto fail;
+ }
+ /*
+ * The station has been added to the driver.
+ * When sending the (Re)Association response frame,
+ * reset the no_sta flag and send the response to sta->addr
+ * instead of the source address.
+ */
+ no_sta = false;
+ dst = sta->addr;
+ }
+
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
* is used */
resp = check_assoc_ies(hapd, sta, pos, left,
@@ -2070,8 +2070,8 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211BE
-static void ap_sta_remove_link_sta(struct hostapd_data *hapd,
- struct sta_info *sta)
+void ap_sta_remove_link_sta(struct hostapd_data *hapd,
+ struct sta_info *sta)
{
struct hostapd_data *tmp_hapd;
@@ -469,6 +469,8 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
unsigned timeout);
int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
+void ap_sta_remove_link_sta(struct hostapd_data *hapd,
+ struct sta_info *sta);
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);