[PATCH 03/12] MLD STA: Add support to fetch per-link beacon WPA/RSN/RSNX IEs into wpa_sm
Veerendranath Jakkam
quic_vjakkam at quicinc.com
Wed Aug 24 22:53:02 PDT 2022
wpa_sm needs per-link beacon RSN and RSNX IEs for MLO KDE validation.
Thus, Add required APIs to parse and set AP link WPA/RSN/RSNX IEs to
wpa_sm.
Signed-off-by: Veerendranath Jakkam <quic_vjakkam at quicinc.com>
---
src/rsn_supp/wpa.c | 103 +++++++++++++-----
src/rsn_supp/wpa.h | 22 ++--
src/rsn_supp/wpa_i.h | 8 ++
tests/fuzzing/eapol-key-supp/eapol-key-supp.c | 2 +-
wpa_supplicant/events.c | 66 ++++++++---
wpa_supplicant/ibss_rsn.c | 4 +-
wpa_supplicant/wpa_supplicant.c | 19 ++--
wpa_supplicant/wpas_glue.c | 103 +++++++++++++++---
8 files changed, 247 insertions(+), 80 deletions(-)
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index a28d49225..f3965ca50 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -3716,6 +3716,7 @@ int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
/**
* wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @link_id: MLO link ID to set specific link or -1 to set default
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
@@ -3723,24 +3724,40 @@ int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
* Inform WPA state machine about the WPA IE used in Beacon / Probe Response
* frame.
*/
-int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
+int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len)
{
- if (sm == NULL)
+ u8 **ap_wpa_ie;
+ size_t *ap_wpa_ie_len;
+
+ if (!sm)
return -1;
- os_free(sm->ap_wpa_ie);
- if (ie == NULL || len == 0) {
+ if (link_id == -1) {
+ ap_wpa_ie = &sm->ap_wpa_ie;
+ ap_wpa_ie_len = &sm->ap_wpa_ie_len;
+ } else {
+ if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
+ return -1;
+
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
- "WPA: clearing AP WPA IE");
- sm->ap_wpa_ie = NULL;
- sm->ap_wpa_ie_len = 0;
+ "WPA: set AP WPA IE for link ID %d", link_id);
+ ap_wpa_ie = &sm->links[link_id].ap_wpa_ie;
+ ap_wpa_ie_len = &sm->links[link_id].ap_wpa_ie_len;
+ }
+
+ os_free(*ap_wpa_ie);
+ if (ie == NULL || len == 0) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP WPA IE");
+ *ap_wpa_ie = NULL;
+ *ap_wpa_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
- sm->ap_wpa_ie = os_memdup(ie, len);
- if (sm->ap_wpa_ie == NULL)
+ *ap_wpa_ie = os_memdup(ie, len);
+ if (*ap_wpa_ie == NULL)
return -1;
- sm->ap_wpa_ie_len = len;
+ *ap_wpa_ie_len = len;
}
return 0;
@@ -3750,6 +3767,7 @@ int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
/**
* wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @link_id: MLO link ID to set specific link or -1 to set default
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
@@ -3757,24 +3775,41 @@ int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
* Inform WPA state machine about the RSN IE used in Beacon / Probe Response
* frame.
*/
-int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
+int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len)
{
- if (sm == NULL)
+ u8 **ap_rsn_ie;
+ size_t *ap_rsn_ie_len;
+
+ if (!sm)
return -1;
- os_free(sm->ap_rsn_ie);
+ if (link_id == -1) {
+ ap_rsn_ie = &sm->ap_rsn_ie;
+ ap_rsn_ie_len = &sm->ap_rsn_ie_len;
+ } else {
+ if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
+ return -1;
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: set AP RSN IE for link ID %d", link_id);
+ ap_rsn_ie = &sm->links[link_id].ap_rsn_ie;
+ ap_rsn_ie_len = &sm->links[link_id].ap_rsn_ie_len;
+ }
+
+ os_free(*ap_rsn_ie);
if (ie == NULL || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: clearing AP RSN IE");
- sm->ap_rsn_ie = NULL;
- sm->ap_rsn_ie_len = 0;
+ *ap_rsn_ie = NULL;
+ *ap_rsn_ie_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
- sm->ap_rsn_ie = os_memdup(ie, len);
- if (sm->ap_rsn_ie == NULL)
+ *ap_rsn_ie = os_memdup(ie, len);
+ if (*ap_rsn_ie == NULL)
return -1;
- sm->ap_rsn_ie_len = len;
+ *ap_rsn_ie_len = len;
}
return 0;
@@ -3784,6 +3819,7 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
/**
* wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
* @sm: Pointer to WPA state machine data from wpa_sm_init()
+ * @link_id: MLO link ID to set specific link or -1 to set default
* @ie: Pointer to IE data (starting from id)
* @len: IE length
* Returns: 0 on success, -1 on failure
@@ -3791,23 +3827,40 @@ int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
* Inform WPA state machine about the RSNXE used in Beacon / Probe Response
* frame.
*/
-int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
+int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len)
{
+ u8 **ap_rsnxe;
+ size_t *ap_rsnxe_len;
+
if (!sm)
return -1;
- os_free(sm->ap_rsnxe);
+ if (link_id == -1) {
+ ap_rsnxe = &sm->ap_rsnxe;
+ ap_rsnxe_len = &sm->ap_rsnxe_len;
+ } else {
+ if (link_id < 0 || link_id >= MAX_NUM_MLD_LINKS)
+ return -1;
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: set AP RSNXE IE for link ID %d", link_id);
+ ap_rsnxe = &sm->links[link_id].ap_rsnxe;
+ ap_rsnxe_len = &sm->links[link_id].ap_rsnxe_len;
+ }
+
+ os_free(*ap_rsnxe);
if (!ie || len == 0) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
- sm->ap_rsnxe = NULL;
- sm->ap_rsnxe_len = 0;
+ *ap_rsnxe = NULL;
+ *ap_rsnxe_len = 0;
} else {
wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
- sm->ap_rsnxe = os_memdup(ie, len);
- if (!sm->ap_rsnxe)
+ *ap_rsnxe = os_memdup(ie, len);
+ if (*ap_rsnxe == NULL)
return -1;
- sm->ap_rsnxe_len = len;
+ *ap_rsnxe_len = len;
}
return 0;
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index e6eef0c99..a56802b0a 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -93,6 +93,7 @@ struct wpa_sm_ctx {
void (*transition_disable)(void *ctx, u8 bitmap);
void (*store_ptk)(void *ctx, u8 *addr, int cipher,
u32 life_time, const struct wpa_ptk *ptk);
+ int (*get_link_beacon_ie)(void *ctx, u8 link_id);
};
@@ -165,9 +166,12 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
size_t *rsnxe_len);
int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
-int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
-int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len);
-int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len);
+int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len);
+int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len);
+int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, int link_id, const u8 *ie,
+ size_t len);
int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen);
int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
@@ -299,20 +303,20 @@ static inline int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm,
return -1;
}
-static inline int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie,
- size_t len)
+static inline int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, int link_id,
+ const u8 *ie, size_t len)
{
return -1;
}
-static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie,
- size_t len)
+static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, int link_id,
+ const u8 *ie, size_t len)
{
return -1;
}
-static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie,
- size_t len)
+static inline int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, int link_id,
+ const u8 *ie, size_t len)
{
return -1;
}
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 62b85cb2e..8bf0f28d8 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -224,6 +224,8 @@ struct wpa_sm {
struct {
u8 addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
+ u8 *ap_wpa_ie, *ap_rsn_ie, *ap_rsnxe;
+ size_t ap_wpa_ie_len, ap_rsn_ie_len, ap_rsnxe_len;
} links[MAX_NUM_MLD_LINKS];
};
@@ -288,6 +290,12 @@ static inline int wpa_sm_get_beacon_ie(struct wpa_sm *sm)
return sm->ctx->get_beacon_ie(sm->ctx->ctx);
}
+static inline int wpa_sm_get_link_beacon_ie(struct wpa_sm *sm, u8 link_id)
+{
+ WPA_ASSERT(sm->ctx->get_link_beacon_ie);
+ return sm->ctx->get_link_beacon_ie(sm->ctx->ctx, link_id);
+}
+
static inline void wpa_sm_cancel_auth_timeout(struct wpa_sm *sm)
{
WPA_ASSERT(sm->ctx->cancel_auth_timeout);
diff --git a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
index 0c7189571..a86efd376 100644
--- a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
+++ b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c
@@ -168,7 +168,7 @@ static int supp_get_beacon_ie(void *ctx)
ie = wpa->wpa1 ? wpaie : rsne;
if (ie[0] == WLAN_EID_RSN)
return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]);
- return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]);
+ return wpa_sm_set_ap_wpa_ie(wpa->supp, -1, ie, 2 + ie[1]);
}
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index db4de316f..5f13d4674 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -3223,27 +3223,27 @@ no_pfs:
p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
wpa_found = 1;
- wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, -1, p, len);
}
if (!rsn_found &&
p[0] == WLAN_EID_RSN && p[1] >= 2) {
rsn_found = 1;
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, -1, p, len);
}
if (p[0] == WLAN_EID_RSNX && p[1] >= 1)
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, p, len);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, -1, p, len);
l -= len;
p += len;
}
if (!wpa_found && data->assoc_info.beacon_ies)
- wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, -1, NULL, 0);
if (!rsn_found && data->assoc_info.beacon_ies) {
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, -1, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, -1, NULL, 0);
}
if (wpa_found || rsn_found)
wpa_s->ap_ies_from_associnfo = 1;
@@ -3265,26 +3265,23 @@ no_pfs:
}
-static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
+static int wpa_supplicant_update_link_ie(struct wpa_supplicant *wpa_s,
+ int link_id, const struct wpa_bss *bss)
{
const u8 *bss_wpa = NULL, *bss_rsn = NULL, *bss_rsnx = NULL;
- if (!wpa_s->current_bss || !wpa_s->current_ssid)
+ if (!bss)
return -1;
- if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt))
- return 0;
-
- bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
- WPA_IE_VENDOR_TYPE);
- bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
- bss_rsnx = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSNX);
+ bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+ bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
- if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, link_id, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, link_id, bss_rsn,
bss_rsn ? 2 + bss_rsn[1] : 0) ||
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, link_id, bss_rsnx,
bss_rsnx ? 2 + bss_rsnx[1] : 0))
return -1;
@@ -3292,6 +3289,39 @@ static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
}
+static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
+{
+ int i;
+
+ if (!wpa_s->current_bss || !wpa_s->current_ssid)
+ return -1;
+
+ if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt))
+ return 0;
+
+ if (wpa_supplicant_update_link_ie(wpa_s, -1, wpa_s->current_bss))
+ return -1;
+
+ if (!wpa_s->valid_links)
+ return 0;
+
+ for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ if (!(wpa_s->valid_links & BIT(i))) {
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, i, NULL, 0);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, i, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, i, NULL, 0);
+ continue;
+ }
+
+ if (wpa_supplicant_update_link_ie(wpa_s, i,
+ wpa_s->links[i].bss))
+ return -1;
+ }
+
+ return 0;
+}
+
+
static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s,
union wpa_event_data *data)
{
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 874c2bf1d..459d7bd2d 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -117,8 +117,8 @@ static int supp_get_beacon_ie(void *ctx)
wpa_printf(MSG_DEBUG, "SUPP: %s", __func__);
/* TODO: get correct RSN IE */
- wpa_sm_set_ap_rsnxe(peer->supp, NULL, 0);
- return wpa_sm_set_ap_rsn_ie(peer->supp,
+ wpa_sm_set_ap_rsnxe(peer->supp, -1, NULL, 0);
+ return wpa_sm_set_ap_rsn_ie(peer->supp, -1,
(u8 *) "\x30\x14\x01\x00"
"\x00\x0f\xac\x04"
"\x01\x00\x00\x0f\xac\x04"
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index ba364324d..b0087328c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -400,9 +400,7 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
-#ifdef CONFIG_WEP
int i;
-#endif /* CONFIG_WEP */
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
@@ -410,9 +408,14 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
else
wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
- wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, -1, NULL, 0);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, -1, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, -1, NULL, 0);
+ for (int i = 0; i < MAX_NUM_MLD_LINKS; i++) {
+ wpa_sm_set_ap_wpa_ie(wpa_s->wpa, i, NULL, 0);
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, i, NULL, 0);
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, i, NULL, 0);
+ }
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
wpa_s->rsnxe_len = 0;
@@ -1505,11 +1508,11 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
!!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
if (bss || !wpa_s->ap_ies_from_associnfo) {
- if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, -1, bss_wpa,
bss_wpa ? 2 + bss_wpa[1] : 0) ||
- wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
+ wpa_sm_set_ap_rsn_ie(wpa_s->wpa, -1, bss_rsn,
bss_rsn ? 2 + bss_rsn[1] : 0) ||
- wpa_sm_set_ap_rsnxe(wpa_s->wpa, bss_rsnx,
+ wpa_sm_set_ap_rsnxe(wpa_s->wpa, -1, bss_rsnx,
bss_rsnx ? 2 + bss_rsnx[1] : 0))
return -1;
}
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index ccc72c4d6..2784fb096 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -390,15 +390,21 @@ static void wpa_supplicant_notify_eapol_done(void *ctx)
#ifndef CONFIG_NO_WPA
-static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
+struct beacon_ies {
+ const u8 *wpa_ie, *rsn_ie, *rsnxe;
+ size_t wpa_ie_len, rsn_ie_len, rsnxe_len;
+};
+
+
+static int wpa_get_bssid_beacon_ie(struct wpa_supplicant *wpa_s,
+ const u8 *bssid, struct beacon_ies *ies)
{
- int ret = 0;
struct wpa_bss *curr = NULL, *bss;
struct wpa_ssid *ssid = wpa_s->current_ssid;
const u8 *ie;
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
- if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
+ if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0)
continue;
if (ssid == NULL ||
((bss->ssid_len == ssid->ssid_len &&
@@ -416,23 +422,42 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_OWE */
}
- if (curr) {
- ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
- if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
- ret = -1;
+ if (!curr)
+ return -1;
- ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
- if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
- ret = -1;
+ ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
+ ies->wpa_ie = ie;
+ ies->wpa_ie_len = ie ? 2 + ie[1] : 0;
- ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
- if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
- ret = -1;
- } else {
- ret = -1;
- }
+ ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
+ ies->rsn_ie = ie;
+ ies->rsn_ie_len = ie ? 2 + ie[1] : 0;
- return ret;
+ ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX);
+ ies->rsnxe = ie;
+ ies->rsnxe_len = ie ? 2 + ie[1] : 0;
+
+ return 0;
+}
+
+
+static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
+{
+ struct beacon_ies ies;
+
+ if (wpa_get_bssid_beacon_ie(wpa_s, wpa_s->bssid, &ies))
+ return -1;
+
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, -1, ies.wpa_ie, ies.wpa_ie_len))
+ return -1;
+
+ if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, -1, ies.rsn_ie, ies.rsn_ie_len))
+ return -1;
+
+ if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, -1, ies.rsnxe, ies.rsnxe_len))
+ return -1;
+
+ return 0;
}
@@ -452,6 +477,49 @@ static int wpa_supplicant_get_beacon_ie(void *ctx)
}
+static int wpa_get_link_beacon_ie(struct wpa_supplicant *wpa_s, u8 link_id)
+{
+ struct beacon_ies ies;
+
+ if (!(wpa_s->valid_links & BIT(link_id)))
+ return -1;
+
+
+ if (wpa_get_bssid_beacon_ie(wpa_s, wpa_s->links[link_id].bssid, &ies))
+ return -1;
+
+ if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, link_id, ies.wpa_ie,
+ ies.wpa_ie_len))
+ return -1;
+
+ if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, link_id, ies.rsn_ie,
+ ies.rsn_ie_len))
+ return -1;
+
+ if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, link_id, ies.rsnxe, ies.rsnxe_len))
+ return -1;
+
+ return 0;
+}
+
+
+static int wpa_supplicant_get_link_beacon_ie(void *ctx, u8 link_id)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ if (wpa_get_link_beacon_ie(wpa_s, link_id) == 0) {
+ return 0;
+ }
+
+ /* No WPA/RSN IE found in the cached scan results. Try to get updated
+ * scan results from the driver. */
+ if (wpa_supplicant_update_scan_results(wpa_s) < 0)
+ return -1;
+
+ return wpa_get_link_beacon_ie(wpa_s, link_id);
+}
+
+
+
static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
const void *data, u16 data_len,
size_t *msg_len, void **data_pos)
@@ -1412,6 +1480,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
ctx->get_bssid = wpa_supplicant_get_bssid;
ctx->ether_send = _wpa_ether_send;
ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
+ ctx->get_link_beacon_ie = wpa_supplicant_get_link_beacon_ie;
ctx->alloc_eapol = _wpa_alloc_eapol;
ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
ctx->add_pmkid = wpa_supplicant_add_pmkid;
--
2.25.1
More information about the Hostap
mailing list