wpa_printf(MSG_DEBUG, "MLD: link: status=%u", status);
if (status != WLAN_STATUS_SUCCESS) {
wpa_release_link_auth_ref(origin_sta->wpa_sm,
- hapd->mld_link_id);
+ hapd->mld_link_id, true);
if (sta)
ap_free_sta(hapd, sta);
return -1;
/* Release group references in case non-association link STA is removed
* before association link STA */
if (hostapd_sta_is_link_sta(hapd, sta))
- wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id);
+ wpa_release_link_auth_ref(sta->wpa_sm, hapd->mld_link_id,
+ false);
#else /* CONFIG_IEEE80211BE */
wpa_auth_sta_deinit(sta->wpa_sm);
#endif /* CONFIG_IEEE80211BE */
#ifdef CONFIG_IEEE80211BE
-void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id)
+void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id,
+ bool rejected)
{
struct wpa_authenticator *wpa_auth;
struct mld_link *link;
link = &sm->mld_links[link_id];
if (link->valid) {
link->valid = false;
+ link->rejected = rejected;
wpa_auth = link->wpa_auth;
if (wpa_auth) {
link->wpa_auth = NULL;
wpa_group_put(wpa_auth, wpa_auth->group);
}
- sm->n_mld_affiliated_links--;
}
}
return -1;
}
+ /* Skip rejected links although the non-AP MLD will send them in
+ * M2 of the initial 4-way handshake. */
+ if (sm->mld_links[i].rejected) {
+ n_links++;
+ continue;
+ }
if (!sm->mld_links[i].valid || i == sm->mld_assoc_link_id) {
wpa_printf(MSG_DEBUG,
"RSN: MLD: Invalid link ID=%u", i);
struct wpa_get_link_auth_ctx ctx;
sm_link->valid = link->valid;
+ sm_link->rejected = false;
if (!link->valid)
continue;
bool mgmt_frame_prot, bool beacon_prot,
bool rekey);
-void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id);
+void wpa_release_link_auth_ref(struct wpa_state_machine *sm, u8 link_id,
+ bool rejected);
#define for_each_sm_auth(sm, link_id) \
for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) \
struct mld_link {
bool valid;
+ bool rejected;
u8 peer_addr[ETH_ALEN];
struct wpa_authenticator *wpa_auth;