#endif /* CONFIG_IEEE80211AX */
};
+
+static void hostapd_free_probe_resp_params(struct probe_resp_params *params)
+{
+#ifdef CONFIG_IEEE80211BE
+ if (!params)
+ return;
+ ap_sta_free_sta_profile(params->mld_info);
+ os_free(params->mld_info);
+ params->mld_info = NULL;
+#endif /* CONFIG_IEEE80211BE */
+}
+
+
static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
struct probe_resp_params *params)
{
size_t buflen;
u8 mld_link_id = link->mld_link_id;
u8 *epos;
+ u8 buf[EHT_ML_MAX_STA_PROF_LEN];
/*
* Set mld_ap iff the ML probe request explicitly
buflen = MAX_PROBERESP_LEN;
buflen += hostapd_probe_resp_elems_len(link, &sta_info_params);
- if (buflen > sizeof(link_info->resp_sta_profile)) {
+ if (buflen > EHT_ML_MAX_STA_PROF_LEN) {
wpa_printf(MSG_DEBUG,
"MLD: Not including link %d in ML probe response (%zu bytes is too long)",
mld_link_id, buflen);
* various other things.
*/
link_info->valid = true;
- epos = link_info->resp_sta_profile;
+ epos = buf;
/* Capabilities is the only fixed parameter */
- WPA_PUT_LE16(link_info->resp_sta_profile,
- hostapd_own_capab_info(hapd));
+ WPA_PUT_LE16(epos, hostapd_own_capab_info(hapd));
+ epos += 2;
epos = hostapd_probe_resp_fill_elems(
- link, &sta_info_params,
- link_info->resp_sta_profile + 2,
- sizeof(link_info->resp_sta_profile) - 2);
- link_info->resp_sta_profile_len =
- epos - link_info->resp_sta_profile;
+ link, &sta_info_params, epos,
+ EHT_ML_MAX_STA_PROF_LEN - 2);
+ link_info->resp_sta_profile_len = epos - buf;
+ os_free(link_info->resp_sta_profile);
+ link_info->resp_sta_profile = os_memdup(
+ buf, link_info->resp_sta_profile_len);
+ if (!link_info->resp_sta_profile)
+ link_info->resp_sta_profile_len = 0;
os_memcpy(link_info->local_addr, link->own_addr, ETH_ALEN);
wpa_printf(MSG_DEBUG,
return;
fail:
- os_free(params->mld_info);
+ hostapd_free_probe_resp_params(params);
params->mld_ap = NULL;
params->mld_info = NULL;
}
hostapd_gen_probe_resp(hapd, ¶ms);
- os_free(params.mld_info);
+ hostapd_free_probe_resp_params(¶ms);
if (!params.resp)
return;
#ifdef CONFIG_IEEE80211BE
if (auth_transaction == 1) {
+ ap_sta_free_sta_profile(&sta->mld_info);
os_memset(&sta->mld_info, 0, sizeof(sta->mld_info));
if (mld_sta) {
#ifdef CONFIG_IEEE80211BE
-static size_t ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
- u16 status_code,
- u8 *buf, size_t buflen)
+static void ieee80211_ml_build_assoc_resp(struct hostapd_data *hapd,
+ struct mld_link_info *link)
{
+ u8 buf[EHT_ML_MAX_STA_PROF_LEN];
u8 *p = buf;
+ size_t buflen = sizeof(buf);
/* Capability Info */
WPA_PUT_LE16(p, hostapd_own_capab_info(hapd));
p += 2;
/* Status Code */
- WPA_PUT_LE16(p, status_code);
+ WPA_PUT_LE16(p, link->status);
p += 2;
- if (status_code != WLAN_STATUS_SUCCESS)
- return p - buf;
+ if (link->status != WLAN_STATUS_SUCCESS)
+ goto out;
/* AID is not included */
p = hostapd_eid_supp_rates(hapd, p);
p += wpabuf_len(hapd->conf->assocresp_elements);
}
- return p - buf;
+out:
+ os_free(link->resp_sta_profile);
+ link->resp_sta_profile = os_memdup(buf, p - buf);
+ link->resp_sta_profile_len = link->resp_sta_profile ? p - buf : 0;
}
struct wpabuf *mlbuf = NULL;
struct sta_info *sta = NULL;
u16 status = WLAN_STATUS_SUCCESS;
+ int i;
wpa_printf(MSG_DEBUG, "MLD: link: link_id=%u, peer=" MACSTR,
hapd->mld_link_id, MAC2STR(link->peer_addr));
sta->mld_assoc_link_id = origin_sta->mld_assoc_link_id;
os_memcpy(&sta->mld_info, &origin_sta->mld_info, sizeof(sta->mld_info));
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ struct mld_link_info *li = &sta->mld_info.links[i];
+
+ li->resp_sta_profile = NULL;
+ li->resp_sta_profile_len = 0;
+ }
/*
* Get the AID from the station on which the association was performed,
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));
+ ieee80211_ml_build_assoc_resp(hapd, link);
}
"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));
+ ieee80211_ml_build_assoc_resp(hapd, link);
} else if (tx_link_status != WLAN_STATUS_SUCCESS) {
/* TX link rejected the connection */
link->status = WLAN_STATUS_DENIED_TX_LINK_NOT_ACCEPTED;
- link->resp_sta_profile_len =
- ieee80211_ml_build_assoc_resp(
- hapd, link->status,
- link->resp_sta_profile,
- sizeof(link->resp_sta_profile));
+ ieee80211_ml_build_assoc_resp(hapd, link);
} else {
ieee80211_ml_process_link(iface->bss[0], sta, link,
ies, ies_len, reassoc);
/* BSS Parameters Change Count */
wpabuf_put_u8(buf, hapd->eht_mld_bss_param_change);
+ if (!link->resp_sta_profile)
+ continue;
+
/* Fragment the sub element if needed */
if (total_len <= 255) {
wpabuf_put_data(buf, link->resp_sta_profile,
eid = hostapd_eid_eht_basic_ml_common(hapd, eid, &info->mld_info,
false);
+ ap_sta_free_sta_profile(&info->mld_info);
return hostapd_eid_eht_reconf_ml(hapd, eid);
}
#ifdef CONFIG_INTERWORKING
if (sta->gas_dialog) {
int i;
+
for (i = 0; i < GAS_DIALOG_MAX; i++)
gas_serv_dialog_clear(&sta->gas_dialog[i]);
os_free(sta->gas_dialog);
os_free(sta->ifname_wds);
+#ifdef CONFIG_IEEE80211BE
+ ap_sta_free_sta_profile(&sta->mld_info);
+#endif /* CONFIG_IEEE80211BE */
+
#ifdef CONFIG_TESTING_OPTIONS
os_free(sta->sae_postponed_commit);
forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
sta->added_unassoc = 1;
return 0;
}
+
+
+#ifdef CONFIG_IEEE80211BE
+void ap_sta_free_sta_profile(struct mld_info *info)
+{
+ int i;
+
+ if (!info)
+ return;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ os_free(info->links[i].resp_sta_profile);
+ info->links[i].resp_sta_profile = NULL;
+ }
+}
+#endif /* CONFIG_IEEE80211BE */
u16 status;
size_t resp_sta_profile_len;
- u8 resp_sta_profile[EHT_ML_MAX_STA_PROF_LEN];
+ u8 *resp_sta_profile;
const u8 *rsne, *rsnxe;
} links[MAX_NUM_MLD_LINKS];
#endif /* CONFIG_IEEE80211BE */
}
+void ap_sta_free_sta_profile(struct mld_info *info);
+
#endif /* STA_INFO_H */