From: Veerendranath Jakkam Date: Thu, 3 Nov 2022 08:08:45 +0000 (+0530) Subject: MLD STA: Set MLO connection info to wpa_sm X-Git-Tag: hostap_2_11~1561 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=472a0b8d6069b9730041d0109942661b3f13ca0b;p=thirdparty%2Fhostap.git MLD STA: Set MLO connection info to wpa_sm Update the following MLO connection information to wpa_sm: - AP MLD address and link ID of the (re)association link. - Bitmap of requested links and accepted links - Own link address for each requested link - AP link address, RSNE and RSNXE for each requested link Signed-off-by: Veerendranath Jakkam --- diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 3a9d03bda..ea32858d0 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -37,6 +37,27 @@ static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static void wpa_hexdump_link(int level, u8 link_id, const char *title, + const void *buf, size_t len) +{ + char *link_title = NULL; + + if (link_id >= MAX_NUM_MLD_LINKS) + goto out; + + link_title = os_malloc(os_strlen(title) + 20); + if (!link_title) + goto out; + + os_snprintf(link_title, os_strlen(title) + 20, "MLO link[%u]: %s", + link_id, title); + +out: + wpa_hexdump(level, link_title ? link_title : title, buf, len); + os_free(link_title); +} + + /** * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() @@ -3006,6 +3027,8 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) */ void wpa_sm_deinit(struct wpa_sm *sm) { + int i; + if (sm == NULL) return; pmksa_cache_deinit(sm->pmksa); @@ -3016,6 +3039,10 @@ void wpa_sm_deinit(struct wpa_sm *sm) os_free(sm->ap_wpa_ie); os_free(sm->ap_rsn_ie); os_free(sm->ap_rsnxe); + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + os_free(sm->mlo.links[i].ap_rsne); + os_free(sm->mlo.links[i].ap_rsnxe); + } wpa_sm_drop_sa(sm); os_free(sm->ctx); #ifdef CONFIG_IEEE80211R @@ -3304,6 +3331,81 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) } +int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo) +{ + int i; + + if (!sm) + return -1; + + os_memcpy(sm->mlo.ap_mld_addr, mlo->ap_mld_addr, ETH_ALEN); + sm->mlo.assoc_link_id = mlo->assoc_link_id; + sm->mlo.valid_links = mlo->valid_links; + sm->mlo.req_links = mlo->req_links; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + const u8 *ie; + size_t len; + + if (sm->mlo.req_links & BIT(i)) { + if (!mlo->links[i].ap_rsne || + mlo->links[i].ap_rsne_len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: No RSNE for AP MLO link %d with BSSID " + MACSTR, + i, MAC2STR(mlo->links[i].bssid)); + return -1; + + } + os_memcpy(sm->mlo.links[i].addr, mlo->links[i].addr, + ETH_ALEN); + os_memcpy(sm->mlo.links[i].bssid, mlo->links[i].bssid, + ETH_ALEN); + } + + ie = mlo->links[i].ap_rsne; + len = mlo->links[i].ap_rsne_len; + os_free(sm->mlo.links[i].ap_rsne); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Clearing MLO link[%u] AP RSNE", i); + sm->mlo.links[i].ap_rsne = NULL; + sm->mlo.links[i].ap_rsne_len = 0; + } else { + wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE", + ie, len); + sm->mlo.links[i].ap_rsne = os_memdup(ie, len); + if (!sm->mlo.links[i].ap_rsne) { + sm->mlo.links[i].ap_rsne_len = 0; + return -1; + } + sm->mlo.links[i].ap_rsne_len = len; + } + + ie = mlo->links[i].ap_rsnxe; + len = mlo->links[i].ap_rsnxe_len; + os_free(sm->mlo.links[i].ap_rsnxe); + if (!ie || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Clearing MLO link[%u] AP RSNXE", i); + sm->mlo.links[i].ap_rsnxe = NULL; + sm->mlo.links[i].ap_rsnxe_len = 0; + } else { + wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie, + len); + sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len); + if (!sm->mlo.links[i].ap_rsnxe) { + sm->mlo.links[i].ap_rsnxe_len = 0; + return -1; + } + sm->mlo.links[i].ap_rsnxe_len = len; + } + } + + return 0; +} + + /** * 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 cbeab435c..5c4e3e59c 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -145,6 +145,21 @@ struct rsn_supp_config { bool force_kdk_derivation; }; +struct wpa_sm_link { + u8 addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 *ap_rsne, *ap_rsnxe; + size_t ap_rsne_len, ap_rsnxe_len; +}; + +struct wpa_sm_mlo { + u8 ap_mld_addr[ETH_ALEN]; + u8 assoc_link_id; + u16 valid_links; /* bitmap of accepted links */ + u16 req_links; /* bitmap of requested links */ + struct wpa_sm_link links[MAX_NUM_MLD_LINKS]; +}; + #ifndef CONFIG_NO_WPA struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx); @@ -224,6 +239,7 @@ void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kek, size_t ptk_kek_len); int wpa_fils_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); #else /* CONFIG_NO_WPA */ @@ -438,6 +454,12 @@ static inline void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm) { } +static inline int wpa_sm_set_mlo_params(struct wpa_sm *sm, + const struct wpa_sm_mlo *mlo) +{ + return 0; +} + #endif /* CONFIG_NO_WPA */ #ifdef CONFIG_IEEE80211R diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 3811c3bc4..f7b056696 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -218,6 +218,7 @@ struct wpa_sm { struct wpabuf *dpp_z; int dpp_pfs; #endif /* CONFIG_DPP2 */ + struct wpa_sm_mlo mlo; }; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index f57b058f8..202afa8a5 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3410,6 +3410,66 @@ static int wpa_drv_get_mlo_info(struct wpa_supplicant *wpa_s) } +static int wpa_sm_set_ml_info(struct wpa_supplicant *wpa_s) +{ + struct driver_sta_mlo_info drv_mlo; + struct wpa_sm_mlo wpa_mlo; + const u8 *bss_rsn = NULL, *bss_rsnx = NULL; + int i; + + os_memset(&drv_mlo, 0, sizeof(drv_mlo)); + if (wpas_drv_get_sta_mlo_info(wpa_s, &drv_mlo)) { + wpa_dbg(wpa_s, MSG_INFO, "Failed to get MLO link info"); + return -1; + } + + os_memset(&wpa_mlo, 0, sizeof(wpa_mlo)); + if (!drv_mlo.valid_links) + goto out; + + os_memcpy(wpa_mlo.ap_mld_addr, drv_mlo.ap_mld_addr, ETH_ALEN); + wpa_mlo.assoc_link_id = drv_mlo.assoc_link_id; + wpa_mlo.valid_links = drv_mlo.valid_links; + wpa_mlo.req_links = drv_mlo.req_links; + + for (i = 0; i < MAX_NUM_MLD_LINKS; i++) { + struct wpa_bss *bss; + + if (!(drv_mlo.req_links & BIT(i))) + continue; + + bss = wpa_supplicant_get_new_bss(wpa_s, drv_mlo.links[i].bssid); + if (!bss) { + wpa_supplicant_update_scan_results(wpa_s); + bss = wpa_supplicant_get_new_bss( + wpa_s, drv_mlo.links[i].bssid); + } + + if (!bss) { + wpa_dbg(wpa_s, MSG_INFO, + "Failed to get MLO link %d BSS", i); + return -1; + } + + bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); + bss_rsnx = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + + wpa_mlo.links[i].ap_rsne = bss_rsn ? (u8 *) bss_rsn : NULL; + wpa_mlo.links[i].ap_rsne_len = bss_rsn ? 2 + bss_rsn[1] : 0; + wpa_mlo.links[i].ap_rsnxe = bss_rsnx ? (u8 *) bss_rsnx : NULL; + wpa_mlo.links[i].ap_rsnxe_len = bss_rsnx ? 2 + bss_rsnx[1] : 0; + + os_memcpy(wpa_mlo.links[i].bssid, drv_mlo.links[i].bssid, + ETH_ALEN); + os_memcpy(wpa_mlo.links[i].addr, drv_mlo.links[i].addr, + ETH_ALEN); + } + +out: + return wpa_sm_set_mlo_params(wpa_s->wpa, &wpa_mlo); +} + + static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { @@ -3534,6 +3594,15 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); } wpa_sm_notify_assoc(wpa_s->wpa, bssid); + + if (wpa_sm_set_ml_info(wpa_s)) { + wpa_dbg(wpa_s, MSG_INFO, + "Failed to set MLO connection info to wpa_sm"); + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + return; + } + if (wpa_s->l2) l2_packet_notify_auth_start(wpa_s->l2); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ba1c48fca..a56510a48 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -403,6 +403,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, #ifdef CONFIG_WEP int i; #endif /* CONFIG_WEP */ + struct wpa_sm_mlo mlo; if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) wpa_s->key_mgmt = WPA_KEY_MGMT_WPS; @@ -443,6 +444,8 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, wpa_s->mgmt_group_cipher); pmksa_cache_clear_current(wpa_s->wpa); + os_memset(&mlo, 0, sizeof(mlo)); + wpa_sm_set_mlo_params(wpa_s->wpa, &mlo); }