[RFC 28/30] wpa_supplicant: Track SMD preparations per target AP MLD
Ilan Peer
ilan.peer at intel.com
Wed Oct 21 06:43:46 PDT 2026
Move the SMD Transition state into a heap allocated object kept in a per
interface list and looked up by the target AP MLD address, instead of a
single instance embedded in struct wpa_supplicant. This also removes the
reliance on wpa_s->ap_mld_addr, which already holds the target AP MLD
address while a transition is pending.
This allows to support multiple preparations. While this is mostly
intended for testing do not make it a testing feature as overhead
is minimal.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
wpa_supplicant/smd.c | 296 +++++++++++++++++++-----------
wpa_supplicant/sme.c | 9 +-
wpa_supplicant/wpa_supplicant.c | 3 +
wpa_supplicant/wpa_supplicant_i.h | 8 +-
4 files changed, 204 insertions(+), 112 deletions(-)
diff --git a/wpa_supplicant/smd.c b/wpa_supplicant/smd.c
index a919fbbfba1c..186e586cafe9 100644
--- a/wpa_supplicant/smd.c
+++ b/wpa_supplicant/smd.c
@@ -19,47 +19,106 @@
#include "rsn_supp/wpa.h"
#include "crypto/sha512.h"
-static void wpas_smd_reset(struct wpa_supplicant *wpa_s)
+static struct smd_info * wpas_smd_get(struct wpa_supplicant *wpa_s,
+ const u8 *ap_mld_addr)
{
- wpa_printf(MSG_DEBUG, "SMD: Reset SMD state");
+ struct smd_info *smd;
- crypto_ecdh_deinit(wpa_s->smd.ecdh);
- wpabuf_free(wpa_s->smd.dhss);
- os_memset(&wpa_s->smd, 0, sizeof(wpa_s->smd));
+ dl_list_for_each(smd, &wpa_s->smd_list, struct smd_info, list) {
+ if (ether_addr_equal(smd->target_ap_mld_addr, ap_mld_addr))
+ return smd;
+ }
+
+ return NULL;
+}
+
+
+static void wpas_smd_free(struct smd_info *smd)
+{
+ wpa_printf(MSG_DEBUG, "SMD: Release the state for AP MLD " MACSTR,
+ MAC2STR(smd->target_ap_mld_addr));
+
+ dl_list_del(&smd->list);
+ crypto_ecdh_deinit(smd->ecdh);
+ wpabuf_free(smd->dhss);
+ os_free(smd);
+}
+
+
+static struct smd_info * wpas_smd_add(struct wpa_supplicant *wpa_s,
+ const u8 *ap_mld_addr)
+{
+ struct smd_info *smd = wpas_smd_get(wpa_s, ap_mld_addr);
+
+ if (smd)
+ wpas_smd_free(smd);
+
+ smd = os_zalloc(sizeof(*smd));
+ if (!smd)
+ return NULL;
+
+ os_memcpy(smd->target_ap_mld_addr, ap_mld_addr, ETH_ALEN);
+ dl_list_add(&wpa_s->smd_list, &smd->list);
+
+ return smd;
}
-static void wpas_smd_abandon(struct wpa_supplicant *wpa_s, bool local_only)
+static unsigned int wpas_smd_num_prepared(struct wpa_supplicant *wpa_s,
+ const u8 *ap_mld_addr)
{
- if (wpa_s->smd.state != SMD_STATE_NONE) {
- wpa_drv_st_abandon(wpa_s, wpa_s->smd.target_ap_mld_addr,
- local_only);
+ struct smd_info *smd;
+ unsigned int num = 0;
- wpas_connect_work_done(wpa_s);
+ dl_list_for_each(smd, &wpa_s->smd_list, struct smd_info, list) {
+ if (!ether_addr_equal(smd->target_ap_mld_addr, ap_mld_addr))
+ num++;
}
- wpas_smd_reset(wpa_s);
+ return num;
}
-void wpas_smd_deinit(struct wpa_supplicant *wpa_s)
+static void wpas_smd_abandon(struct wpa_supplicant *wpa_s,
+ struct smd_info *smd, bool local_only)
{
- wpa_printf(MSG_DEBUG, "SMD: Deinit SMD state");
+ if (smd->state != SMD_STATE_NONE)
+ wpa_drv_st_abandon(wpa_s, smd->target_ap_mld_addr, local_only);
+
+ wpas_smd_free(smd);
+}
+
+/*
+ * wpas_smd_fail - Abandon a transition that the station itself could not
+ * complete due to local error/failure.
+ *
+ * @wpa_s: Pointer to the wpa_supplicant structure
+ * @smd: Pointer to the smd_info structure representing the SMD state to abandon
+ */
+static void wpas_smd_fail(struct wpa_supplicant *wpa_s, struct smd_info *smd)
+{
#ifdef CONFIG_TESTING_OPTIONS
wpa_s->smd_st_manual_execute = false;
#endif /* CONFIG_TESTING_OPTIONS */
- wpas_smd_abandon(wpa_s, false);
+ wpas_smd_abandon(wpa_s, smd, false);
}
-void wpas_smd_disconnected(struct wpa_supplicant *wpa_s)
+void wpas_smd_deinit(struct wpa_supplicant *wpa_s)
{
- if (wpa_s->smd.state == SMD_STATE_NONE)
- return;
+ struct smd_info *smd, *tmp;
+
+ dl_list_for_each_safe(smd, tmp, &wpa_s->smd_list, struct smd_info,
+ list)
+ wpas_smd_free(smd);
+}
- wpas_smd_reset(wpa_s);
+
+void wpas_smd_disconnected(struct wpa_supplicant *wpa_s)
+{
+ wpas_smd_deinit(wpa_s);
}
@@ -90,6 +149,7 @@ int wpas_smd_st_start(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
struct st_prepare_params params;
struct wpabuf *pubkey_buf = NULL, *elems = NULL;
size_t elems_len = 0;
+ struct smd_info *smd;
bool first_link = true;
u8 i;
int ret = -1;
@@ -115,40 +175,48 @@ int wpas_smd_st_start(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
return -1;
}
- wpas_smd_reset(wpa_s);
+ /*
+ * The current AP MLD indicates how many target AP MLDs may be in the
+ * prepared state at any given time.
+ */
+ if (wpa_s->current_bss &&
+ wpas_smd_num_prepared(wpa_s, wpa_s->ap_mld_addr) >=
+ wpa_s->current_bss->smd_max_prep_targets) {
+ wpa_printf(MSG_DEBUG,
+ "SMD: Maximum number of prepared target AP MLDs (%u) reached",
+ wpa_s->current_bss->smd_max_prep_targets);
+ return -1;
+ }
+
+ smd = wpas_smd_add(wpa_s, wpa_s->ap_mld_addr);
+ if (!smd)
+ return -1;
os_memset(¶ms, 0, sizeof(params));
- params.target_ap_mld_addr = wpa_s->ap_mld_addr;
+ params.target_ap_mld_addr = smd->target_ap_mld_addr;
params.valid_links = wpa_s->valid_links;
- /*
- * Remember the target AP MLD address: wpa_s->ap_mld_addr still refers
- * to the current AP MLD until the transition completes, so we can't use
- * it later (e.g. when abandoning).
- */
- os_memcpy(wpa_s->smd.target_ap_mld_addr, wpa_s->ap_mld_addr, ETH_ALEN);
-
- wpa_s->smd.smd_per_ap_mld_ptk_mode = bss->smd_per_ap_mld_ptk_mode;
+ smd->smd_per_ap_mld_ptk_mode = bss->smd_per_ap_mld_ptk_mode;
/* Setup information for per-AP PTK mode */
if (bss->smd_per_ap_mld_ptk_mode &&
!wpas_smd_test_fail(wpa_s, SMD_TEST_ST_FAIL_NO_PTK_PARAMS)) {
- if (random_get_bytes(wpa_s->smd.snonce, WPA_NONCE_LEN) < 0) {
+ if (random_get_bytes(smd->snonce, WPA_NONCE_LEN) < 0) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to generate SNonce");
goto fail;
}
- wpa_s->smd.dh_group = 19;
- wpa_s->smd.ecdh = crypto_ecdh_init(wpa_s->smd.dh_group);
- if (!wpa_s->smd.ecdh) {
+ smd->dh_group = 19;
+ smd->ecdh = crypto_ecdh_init(smd->dh_group);
+ if (!smd->ecdh) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to init ECDH group %d",
- wpa_s->smd.dh_group);
+ smd->dh_group);
goto fail;
}
- pubkey_buf = crypto_ecdh_get_pubkey(wpa_s->smd.ecdh, 0);
+ pubkey_buf = crypto_ecdh_get_pubkey(smd->ecdh, 0);
if (!pubkey_buf) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to get ECDH pubkey");
@@ -163,12 +231,6 @@ int wpas_smd_st_start(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
goto fail;
}
- /* Add the Nonce Element */
- wpabuf_put_u8(elems, WLAN_EID_EXTENSION);
- wpabuf_put_u8(elems, 1 + WPA_NONCE_LEN);
- wpabuf_put_u8(elems, WLAN_EID_EXT_NONCE);
- wpabuf_put_data(elems, wpa_s->smd.snonce, WPA_NONCE_LEN);
-
/* Add the DH Parameter Element */
wpabuf_put_u8(elems, WLAN_EID_EXTENSION);
wpabuf_put_u8(elems, 1 + 2 + wpabuf_len(pubkey_buf));
@@ -179,6 +241,12 @@ int wpas_smd_st_start(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
20 : 19);
wpabuf_put_buf(elems, pubkey_buf);
+ /* Add the Nonce Element */
+ wpabuf_put_u8(elems, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(elems, 1 + WPA_NONCE_LEN);
+ wpabuf_put_u8(elems, WLAN_EID_EXT_NONCE);
+ wpabuf_put_data(elems, smd->snonce, WPA_NONCE_LEN);
+
params.ies = wpabuf_head(elems);
params.ies_len = wpabuf_len(elems);
}
@@ -214,15 +282,16 @@ fail:
wpabuf_free(elems);
wpabuf_free(pubkey_buf);
if (ret < 0)
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
else
- wpa_s->smd.state = SMD_STATE_PREPARE_REQUESTED;
+ smd->state = SMD_STATE_PREPARE_REQUESTED;
return ret;
}
-static int wpas_smd_st_execute(struct wpa_supplicant *wpa_s)
+static int wpas_smd_st_execute(struct wpa_supplicant *wpa_s,
+ struct smd_info *smd)
{
struct st_execute_params params;
int ret;
@@ -231,11 +300,11 @@ static int wpas_smd_st_execute(struct wpa_supplicant *wpa_s)
os_memset(¶ms, 0, sizeof(params));
os_memset(&mic_elem, 0, sizeof(mic_elem));
- params.target_ap_mld_addr = wpa_s->ap_mld_addr;
+ params.target_ap_mld_addr = smd->target_ap_mld_addr;
wpa_printf(MSG_DEBUG, "SMD: Starting ST execution");
- if (wpa_s->smd.smd_per_ap_mld_ptk_mode) {
+ if (smd->smd_per_ap_mld_ptk_mode) {
int ret;
/*
@@ -243,24 +312,25 @@ static int wpas_smd_st_execute(struct wpa_supplicant *wpa_s)
* protected with the newly derived per-AP MLD PTK, so install
* it to the driver before requesting ST execution.
*/
- if (wpa_sm_smd_install_tptk(wpa_s->wpa, wpa_s->ap_mld_addr)) {
+ if (wpa_sm_smd_install_tptk(wpa_s->wpa,
+ smd->target_ap_mld_addr)) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to install per-AP MLD PTK");
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
return -1;
}
ret = wpa_sm_smd_calc_mic(wpa_s->wpa,
- wpa_s->ap_mld_addr,
- wpa_s->smd.snonce,
- wpa_s->smd.anonce,
+ smd->target_ap_mld_addr,
+ smd->snonce,
+ smd->anonce,
false,
mic_elem + 2);
if (ret <= 0) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to calc ST execute MIC");
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
return -1;
}
@@ -280,11 +350,11 @@ static int wpas_smd_st_execute(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "SMD: ST Execute returned %d", ret);
if (!ret) {
- wpa_s->smd.state = SMD_STATE_EXECUTE_REQUESTED;
+ smd->state = SMD_STATE_EXECUTE_REQUESTED;
return 0;
}
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
return ret;
}
@@ -295,6 +365,7 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
{
struct ieee80211_mgmt *mgmt;
struct ieee802_11_elems elems;
+ struct smd_info *smd;
size_t len = info->resp_frame_len;
const u8 *pos;
u16 status;
@@ -302,17 +373,11 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "SMD: ST Prep Status (ap_mld=" MACSTR ")",
MAC2STR(info->ap_mld_addr));
- if (wpa_s->smd.state != SMD_STATE_PREPARE_REQUESTED) {
- wpa_printf(MSG_DEBUG,
- "SMD: ST Prep Status without ST Prepare");
- return;
- }
-
- if (os_memcmp(wpa_s->ap_mld_addr, info->ap_mld_addr, ETH_ALEN) != 0) {
+ smd = wpas_smd_get(wpa_s, info->ap_mld_addr);
+ if (!smd || smd->state != SMD_STATE_PREPARE_REQUESTED) {
wpa_printf(MSG_DEBUG,
- "SMD: ST Prep Status for unexpected AP MLD (expected=" MACSTR ", received=" MACSTR ")",
- MAC2STR(wpa_s->ap_mld_addr),
- MAC2STR(info->ap_mld_addr));
+ "SMD: ST Prep Status without ST Prepare (ap_mld="
+ MACSTR ")", MAC2STR(info->ap_mld_addr));
return;
}
@@ -373,7 +438,7 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
goto fail;
}
- if (wpa_s->smd.smd_per_ap_mld_ptk_mode) {
+ if (smd->smd_per_ap_mld_ptk_mode) {
u8 mic[SHA512_MAC_LEN];
int mic_len;
u16 group;
@@ -389,38 +454,38 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
}
group = WPA_GET_LE16(elems.owe_dh);
- if (group != wpa_s->smd.dh_group) {
+ if (group != smd->dh_group) {
wpa_msg(wpa_s, MSG_DEBUG,
"SMD: DH group mismatch (AP=%u, local=%u)",
- group, wpa_s->smd.dh_group);
+ group, smd->dh_group);
goto fail;
}
- wpa_s->smd.dhss =
- crypto_ecdh_set_peerkey(wpa_s->smd.ecdh, 0,
+ smd->dhss =
+ crypto_ecdh_set_peerkey(smd->ecdh, 0,
elems.owe_dh + 2,
elems.owe_dh_len - 2);
- if (!wpa_s->smd.dhss) {
+ if (!smd->dhss) {
wpa_printf(MSG_DEBUG,
"SMD: Failed to set peer ECDH pubkey");
goto fail;
}
- os_memcpy(wpa_s->smd.anonce, elems.nonce, WPA_NONCE_LEN);
+ os_memcpy(smd->anonce, elems.nonce, WPA_NONCE_LEN);
if (wpa_sm_smd_derive_ptk(wpa_s->wpa, info->ap_mld_addr,
- wpa_s->smd.snonce,
- wpa_s->smd.anonce,
- wpabuf_head(wpa_s->smd.dhss),
- wpabuf_len(wpa_s->smd.dhss))) {
+ smd->snonce,
+ smd->anonce,
+ wpabuf_head(smd->dhss),
+ wpabuf_len(smd->dhss))) {
wpa_printf(MSG_DEBUG, "SMD: Failed to derive PTK");
goto fail;
}
mic_len = wpa_sm_smd_calc_mic(wpa_s->wpa,
info->ap_mld_addr,
- wpa_s->smd.snonce,
- wpa_s->smd.anonce,
+ smd->snonce,
+ smd->anonce,
true, mic);
if (mic_len < 0 || os_memcmp(mic, elems.mic, mic_len)) {
@@ -439,7 +504,7 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_s->smd_st_manual_execute) {
wpa_s->smd_st_manual_execute = false;
- wpa_s->smd.state = SMD_STATE_PREPARE_DONE;
+ smd->state = SMD_STATE_PREPARE_DONE;
wpa_printf(MSG_DEBUG,
"SMD: TEST: Waiting for ST_EXECUTE command");
wpa_msg(wpa_s, MSG_INFO,
@@ -449,11 +514,11 @@ void wpas_smd_st_prep_status(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_TESTING_OPTIONS */
- wpas_smd_st_execute(wpa_s);
+ wpas_smd_st_execute(wpa_s, smd);
return;
fail:
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
}
@@ -462,6 +527,7 @@ void wpas_smd_st_exec_status(struct wpa_supplicant *wpa_s,
{
struct ieee80211_mgmt *mgmt;
struct ieee802_11_elems elems;
+ struct smd_info *smd;
size_t len = info->resp_frame_len;
const u8 *pos;
u16 status;
@@ -470,17 +536,11 @@ void wpas_smd_st_exec_status(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG, "SMD: ST Exec Status (ap_mld=" MACSTR ")",
MAC2STR(info->ap_mld_addr));
- if (wpa_s->smd.state != SMD_STATE_EXECUTE_REQUESTED) {
+ smd = wpas_smd_get(wpa_s, info->ap_mld_addr);
+ if (!smd || smd->state != SMD_STATE_EXECUTE_REQUESTED) {
wpa_printf(MSG_DEBUG,
- "SMD: ST Exec Status without ST Execute");
- return;
- }
-
- if (os_memcmp(wpa_s->ap_mld_addr, info->ap_mld_addr, ETH_ALEN) != 0) {
- wpa_printf(MSG_DEBUG,
- "SMD: ST Exec Status for unexpected AP MLD (expected=" MACSTR ", received=" MACSTR ")",
- MAC2STR(wpa_s->ap_mld_addr),
- MAC2STR(info->ap_mld_addr));
+ "SMD: ST Exec Status without ST Execute (ap_mld="
+ MACSTR ")", MAC2STR(info->ap_mld_addr));
return;
}
@@ -529,7 +589,13 @@ void wpas_smd_st_exec_status(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG,
"SMD: ST Exec failed, response frame status %u (ap_mld=" MACSTR ")",
status, MAC2STR(info->ap_mld_addr));
- goto fail;
+ /*
+ * The driver stays connected if the current AP MLD rejected it
+ * (IEEE P802.11bn/D2.0, 37.16.7.5), and disconnects if the
+ * target AP MLD did, since it already switched to it.
+ */
+ wpas_smd_fail(wpa_s, smd);
+ return;
}
len -= 2;
@@ -576,7 +642,7 @@ void wpas_smd_st_exec_status(struct wpa_supplicant *wpa_s,
}
/* Set the new PTK before setting the group keys */
- if (wpa_s->smd.smd_per_ap_mld_ptk_mode &&
+ if (smd->smd_per_ap_mld_ptk_mode &&
wpa_sm_smd_set_tptk_to_ptk(wpa_s->wpa)) {
wpa_printf(MSG_DEBUG, "SMD: Failed to set TPTK as PTK");
goto fail;
@@ -596,11 +662,11 @@ void wpas_smd_st_exec_status(struct wpa_supplicant *wpa_s,
"SMD: ST Exec succeeded, waiting for ST Done (ap_mld=" MACSTR ")",
MAC2STR(info->ap_mld_addr));
- wpa_s->smd.state = SMD_STATE_EXECUTION_DONE;
+ smd->state = SMD_STATE_EXECUTION_DONE;
return;
fail:
- wpas_smd_deinit(wpa_s);
+ wpas_smd_fail(wpa_s, smd);
/*
* The association with the current AP MLD is already gone and the
@@ -615,13 +681,15 @@ fail:
void wpas_smd_st_done(struct wpa_supplicant *wpa_s,
struct st_done_info *info)
{
+ struct smd_info *smd;
int i;
wpa_printf(MSG_DEBUG, "SMD: ST Done (ap_mld=" MACSTR
" valid_links=0x%04x)",
MAC2STR(info->ap_mld_addr), info->valid_links);
- if (wpa_s->smd.state != SMD_STATE_EXECUTION_DONE) {
+ smd = wpas_smd_get(wpa_s, info->ap_mld_addr);
+ if (!smd || smd->state != SMD_STATE_EXECUTION_DONE) {
wpa_printf(MSG_DEBUG,
"SMD: ST Done without a pending SMD Transition");
return;
@@ -638,17 +706,26 @@ void wpas_smd_st_done(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SMD_TRANSITION_DONE "ap_mld=" MACSTR,
MAC2STR(info->ap_mld_addr));
- wpas_smd_reset(wpa_s);
+ /*
+ * A completed SMD Transition invalidates the preparations with the
+ * other target AP MLDs as well. The driver has already released them,
+ * so drop them locally without requesting an abandonment.
+ */
+ wpas_smd_deinit(wpa_s);
}
void wpas_smd_st_abandoned(struct wpa_supplicant *wpa_s,
struct st_abandoned_info *info)
{
+ struct smd_info *smd;
+
wpa_printf(MSG_DEBUG, "SMD: ST Abandoned (ap_mld=" MACSTR ")",
MAC2STR(info->ap_mld_addr));
- wpas_smd_reset(wpa_s);
+ smd = wpas_smd_get(wpa_s, info->ap_mld_addr);
+ if (smd)
+ wpas_smd_free(smd);
/* Assume that this is followed by a disconnection event */
}
@@ -705,30 +782,37 @@ int wpas_smd_st_prepare_req(struct wpa_supplicant *wpa_s,
int wpas_smd_st_execute_req(struct wpa_supplicant *wpa_s)
{
- if (wpa_s->smd.state != SMD_STATE_PREPARE_DONE) {
- wpa_printf(MSG_DEBUG,
- "SMD: No prepared SMD Transition to execute (state=%d)",
- wpa_s->smd.state);
- return -1;
+ struct smd_info *smd;
+
+ dl_list_for_each(smd, &wpa_s->smd_list, struct smd_info, list) {
+ if (smd->state == SMD_STATE_PREPARE_DONE)
+ return wpas_smd_st_execute(wpa_s, smd);
}
- return wpas_smd_st_execute(wpa_s);
+ wpa_printf(MSG_DEBUG, "SMD: No prepared SMD Transition to execute");
+
+ return -1;
}
int wpas_smd_st_abandon_req(struct wpa_supplicant *wpa_s, bool local_only)
{
- if (wpa_s->smd.state == SMD_STATE_NONE) {
+ struct smd_info *smd;
+
+ if (dl_list_empty(&wpa_s->smd_list)) {
wpa_printf(MSG_DEBUG,
"SMD: No ongoing SMD Transition to abandon");
return -1;
}
+ smd = dl_list_first(&wpa_s->smd_list, struct smd_info, list);
+
wpa_printf(MSG_DEBUG,
- "SMD: Abandon the SMD Transition (local_only=%d)",
- local_only);
+ "SMD: Abandon the SMD Transition to AP MLD " MACSTR
+ " (local_only=%d)",
+ MAC2STR(smd->target_ap_mld_addr), local_only);
- wpas_smd_abandon(wpa_s, local_only);
+ wpas_smd_abandon(wpa_s, smd, local_only);
return 0;
}
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index dbb291b6583a..7b5be1f266a9 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1955,8 +1955,13 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
MAC2STR(bss->smd_id));
if (wpas_smd_st_start(wpa_s, bss, ssid) == 0) {
- wpa_printf(MSG_DEBUG,
- "SMD: Started SMD ST");
+ wpa_printf(MSG_DEBUG, "SMD: Started SMD ST");
+
+ /*
+ * The connection radio work is not relevant as the
+ * connection with the current AP is maintained
+ */
+ wpas_connect_work_done(wpa_s);
return;
}
}
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index e0ae06a4adcc..f1c429607d35 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -709,6 +709,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wpa_bss_deinit(wpa_s);
+ wpas_smd_deinit(wpa_s);
+
wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
wpa_supplicant_cancel_scan(wpa_s);
wpa_supplicant_cancel_auth_timeout(wpa_s);
@@ -7480,6 +7482,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
dl_list_init(&wpa_s->bss_tmp_disallowed);
dl_list_init(&wpa_s->fils_hlp_req);
+ dl_list_init(&wpa_s->smd_list);
#ifdef CONFIG_TESTING_OPTIONS
dl_list_init(&wpa_s->drv_signal_override);
wpa_s->test_assoc_comeback_type = -1;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index e313d4d35deb..b9ab205cb9d1 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -775,17 +775,17 @@ enum smd_state {
/**
* struct smd_info - Data for SMD (Simultaneous Multi-Link Device) operations
+ * @list: List entry in wpa_s->smd_list
* @snonce: SNonce for per-AP PTK mode
* @anonce: ANonce for per-AP PTK mode
* @dh_group: DH group for per-AP PTK mode
* @ecdh: ECDH context for per-AP PTK mode
* @dhss: DH shared secret for per-AP PTK mode
* @state: Current SMD state machine state
- * @target_ap_mld_addr: Target AP MLD address of the ongoing transition; kept
- * here because wpa_s->ap_mld_addr still points at the current AP MLD until
- * the transition completes
+ * @target_ap_mld_addr: Target AP MLD address of this preparation
*/
struct smd_info {
+ struct dl_list list;
u8 snonce[WPA_NONCE_LEN];
u8 anonce[WPA_NONCE_LEN];
u16 dh_group;
@@ -1892,7 +1892,7 @@ struct wpa_supplicant {
*/
u8 pr_responder_src_addr[ETH_ALEN];
- struct smd_info smd;
+ struct dl_list smd_list;
};
--
2.55.0
More information about the Hostap
mailing list