[RFC PATCH v1 02/13] FT: Update target AP MLO state before response processing
Jeff Hansen
x at jeffhansen.com
Fri Sep 11 12:20:01 PDT 2026
Populate the WPA state machine with the target AP MLD and per-link
security elements before processing an over-the-air FT response.
Preserve the non-AP MLD link addresses assigned by the driver while
replacing AP-specific state.
Signed-off-by: Jeff Hansen <x at jeffhansen.com>
---
src/rsn_supp/wpa.c | 23 ++++++++++++++++++
src/rsn_supp/wpa.h | 12 ++++++++++
wpa_supplicant/sme.c | 56 +++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 90 insertions(+), 1 deletion(-)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 155bcba11..6aff72b91 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -5077,6 +5077,29 @@ int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
}
+#ifdef CONFIG_IEEE80211BE
+int wpa_sm_set_ft_mlo_params(struct wpa_sm *sm,
+ const struct wpa_sm_mlo *mlo)
+{
+ u8 addr[MAX_NUM_MLD_LINKS][ETH_ALEN];
+ int i, ret;
+
+ if (!sm)
+ return -1;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
+ os_memcpy(addr[i], sm->mlo.links[i].addr, ETH_ALEN);
+
+ ret = wpa_sm_set_mlo_params(sm, mlo);
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
+ os_memcpy(sm->mlo.links[i].addr, addr[i], ETH_ALEN);
+
+ return ret;
+}
+#endif /* CONFIG_IEEE80211BE */
+
+
/**
* wpa_sm_set_own_addr - Set own MAC address
* @sm: Pointer to WPA state machine data from wpa_sm_init()
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 4983903da..0cc5a8007 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -294,6 +294,10 @@ bool wpa_eppke_is_completed(struct wpa_sm *sm);
bool wpa_eap_over_auth_frame_is_completed(struct wpa_sm *sm);
void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm);
int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo);
+#ifdef CONFIG_IEEE80211BE
+int wpa_sm_set_ft_mlo_params(struct wpa_sm *sm,
+ const struct wpa_sm_mlo *mlo);
+#endif /* CONFIG_IEEE80211BE */
void wpa_sm_set_driver_bss_selection(struct wpa_sm *sm,
bool driver_bss_selection);
bool wpa_sm_uses_spp_amsdu(struct wpa_sm *sm);
@@ -567,6 +571,14 @@ static inline int wpa_sm_set_mlo_params(struct wpa_sm *sm,
return 0;
}
+#ifdef CONFIG_IEEE80211BE
+static inline int wpa_sm_set_ft_mlo_params(
+ struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
+{
+ return 0;
+}
+#endif /* CONFIG_IEEE80211BE */
+
static inline void wpa_sm_set_driver_bss_selection(struct wpa_sm *sm,
bool driver_bss_selection)
{
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index f4c649eed..0c226aa31 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1137,6 +1137,55 @@ static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
}
+#if defined(CONFIG_IEEE80211R) && defined(CONFIG_IEEE80211BE)
+static int wpas_sme_set_ft_mlo_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_sm_mlo mlo;
+ int i;
+
+ if (!wpa_s->valid_links)
+ return 0;
+
+ os_memset(&mlo, 0, sizeof(mlo));
+ os_memcpy(mlo.ap_mld_addr, wpa_s->ap_mld_addr, ETH_ALEN);
+ mlo.assoc_link_id = wpa_s->mlo_assoc_link_id;
+ mlo.valid_links = wpa_s->valid_links;
+ mlo.req_links = wpa_s->valid_links;
+
+ for_each_link(mlo.req_links, i) {
+ struct wpa_bss *bss = wpa_s->links[i].bss;
+ const u8 *ie;
+
+ if (!bss)
+ return -1;
+
+ os_memcpy(mlo.links[i].bssid, wpa_s->links[i].bssid,
+ ETH_ALEN);
+ ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ mlo.links[i].ap_rsne = (u8 *) ie;
+ mlo.links[i].ap_rsne_len = ie ? 2 + ie[1] : 0;
+ ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+ mlo.links[i].ap_rsnxe = (u8 *) ie;
+ mlo.links[i].ap_rsnxe_len = ie ? 2 + ie[1] : 0;
+ ie = wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_IE_VENDOR_TYPE);
+ mlo.links[i].ap_rsnoe = (u8 *) ie;
+ mlo.links[i].ap_rsnoe_len = ie ? 2 + ie[1] : 0;
+ ie = wpa_bss_get_vendor_ie(
+ bss, RSNE_OVERRIDE_2_IE_VENDOR_TYPE);
+ mlo.links[i].ap_rsno2e = (u8 *) ie;
+ mlo.links[i].ap_rsno2e_len = ie ? 2 + ie[1] : 0;
+ ie = wpa_bss_get_vendor_ie(
+ bss, RSNXE_OVERRIDE_IE_VENDOR_TYPE);
+ mlo.links[i].ap_rsnxoe = (u8 *) ie;
+ mlo.links[i].ap_rsnxoe_len = ie ? 2 + ie[1] : 0;
+ }
+
+ return wpa_sm_set_ft_mlo_params(wpa_s->wpa, &mlo);
+}
+#endif /* CONFIG_IEEE80211R && CONFIG_IEEE80211BE */
+
+
static void sme_add_assoc_req_ie(struct wpa_supplicant *wpa_s,
const struct wpabuf *buf)
{
@@ -4393,12 +4442,17 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
if (data->auth.auth_type == WLAN_AUTH_FT) {
const u8 *ric_ies = NULL;
size_t ric_ies_len = 0;
+ int ret = 0;
if (wpa_s->ric_ies) {
ric_ies = wpabuf_head(wpa_s->ric_ies);
ric_ies_len = wpabuf_len(wpa_s->ric_ies);
}
- if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
+#ifdef CONFIG_IEEE80211BE
+ ret = wpas_sme_set_ft_mlo_params(wpa_s);
+#endif /* CONFIG_IEEE80211BE */
+ if (ret < 0 ||
+ wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
data->auth.ies_len, 0,
data->auth.peer,
ric_ies, ric_ies_len) < 0) {
--
2.53.0
More information about the Hostap
mailing list