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@xxxxxxxxxxx> --- 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap