]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MLD STA: Set MLO connection info to wpa_sm
authorVeerendranath Jakkam <quic_vjakkam@quicinc.com>
Thu, 3 Nov 2022 08:08:45 +0000 (13:38 +0530)
committerJouni Malinen <j@w1.fi>
Sun, 6 Nov 2022 16:04:09 +0000 (18:04 +0200)
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 <quic_vjakkam@quicinc.com>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
src/rsn_supp/wpa_i.h
wpa_supplicant/events.c
wpa_supplicant/wpa_supplicant.c

index 3a9d03bdaa3456faabde2eb42e27d4bda53cc727..ea32858d02c3b6ecaab1d8d28a57198958106b0e 100644 (file)
 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()
index cbeab435c3cf476b90cd09215c22b3cd6529d4c6..5c4e3e59c21d1420c034d167de5efe24a37514d3 100644 (file)
@@ -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
index 3811c3bc4681d4333dd17b859c8188bcdd44fbbc..f7b0566960234d6d7f67119c1caa56484776e825 100644 (file)
@@ -218,6 +218,7 @@ struct wpa_sm {
        struct wpabuf *dpp_z;
        int dpp_pfs;
 #endif /* CONFIG_DPP2 */
+       struct wpa_sm_mlo mlo;
 };
 
 
index f57b058f8b7530e4a890cec77f829ac748247714..202afa8a5356d628c6cc4198078eaffc560c4f93 100644 (file)
@@ -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);
 
index ba1c48fcab3dc3492bbd3e67cbe4f0d20d885b35..a56510a48873867778e25d7fcf2d7ccd687223a9 100644 (file)
@@ -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);
 }