]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wpa_supplicant: Remove duplicate logic in wpas_ml_element()
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>
Mon, 20 Nov 2023 23:51:20 +0000 (01:51 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 25 Nov 2023 10:03:52 +0000 (12:03 +0200)
Parsing multiple RNR elements already exists in
wpa_bss_parse_basic_ml_element(), so wpas_ml_element() just duplicates
the same code. Combine the functionality of both these functions and
remove the duplicate.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h
wpa_supplicant/bss.c
wpa_supplicant/bss.h
wpa_supplicant/events.c
wpa_supplicant/sme.c

index 37a300ea48e69635fe2c5c5df57e2b0241077177..06f82ce303ce4a76b1ede43e06936e35ff2b74ea 100644 (file)
@@ -2495,35 +2495,6 @@ const u8 * get_ie(const u8 *ies, size_t len, u8 eid)
 }
 
 
-/**
- * get_ie_nth - Fetch a specified information element from IEs buffer
- * @ies: Information elements buffer
- * @len: Information elements buffer length
- * @eid: Information element identifier (WLAN_EID_*)
- * @nth: Return the nth element of the requested type (2 returns the second)
- * Returns: Pointer to the information element (id field) or %NULL if not found
- *
- * This function returns the nth matching information element in the IEs
- * buffer or %NULL in case the element is not found.
- */
-const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth)
-{
-       const struct element *elem;
-       int sofar = 0;
-
-       if (!ies)
-               return NULL;
-
-       for_each_element_id(elem, eid, ies, len) {
-               sofar++;
-               if (sofar == nth)
-                       return &elem->id;
-       }
-
-       return NULL;
-}
-
-
 /**
  * get_ie_ext - Fetch a specified extended information element from IEs buffer
  * @ies: Information elements buffer
index a8a2118b1f11e3ace31dbde67ac78423695a37ac..a7d407b65d91cdd6fc18d6790ac51059f6c822bf 100644 (file)
@@ -261,7 +261,6 @@ extern const struct oper_class_map global_op_class[];
 extern size_t global_op_class_size;
 
 const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
-const u8 * get_ie_nth(const u8 *ies, size_t len, u8 eid, int nth);
 const u8 * get_ie_ext(const u8 *ies, size_t len, u8 ext);
 const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
 
index ca11e72000ef66192b6bd05540bd48c450745752..fec0e527583d342059c038c69c4ac40eec314c4c 100644 (file)
@@ -13,6 +13,7 @@
 #include "common/ieee802_11_defs.h"
 #include "drivers/driver.h"
 #include "eap_peer/eap.h"
+#include "rsn_supp/wpa.h"
 #include "wpa_supplicant_i.h"
 #include "config.h"
 #include "notify.h"
@@ -1222,22 +1223,6 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
 }
 
 
-/**
- * wpa_bss_get_ie_nth - Fetch a specified information element from a BSS entry
- * @bss: BSS table entry
- * @ie: Information element identitifier (WLAN_EID_*)
- * @nth: Return the nth element of the requested type (2 returns the second)
- * Returns: Pointer to the information element (id field) or %NULL if not found
- *
- * This function returns the nth matching information element in the BSS
- * entry.
- */
-const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth)
-{
-       return get_ie_nth(wpa_bss_ie_ptr(bss), bss->ie_len, ie, nth);
-}
-
-
 /**
  * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
  * @bss: BSS table entry
@@ -1501,7 +1486,8 @@ static void
 wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
                             struct wpa_bss *bss, u8 mbssid_idx,
                             const struct ieee80211_neighbor_ap_info *ap_info,
-                            size_t len, u16 *seen, u16 *missing)
+                            size_t len, u16 *seen, u16 *missing,
+                            struct wpa_ssid *ssid)
 {
        const u8 *pos, *end;
        const u8 *mld_params;
@@ -1525,12 +1511,15 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
        pos += sizeof(*ap_info);
 
        for (i = 0; i < count; i++) {
+               u8 bss_params;
+
                if (bss->n_mld_links >= MAX_NUM_MLD_LINKS)
                        return;
 
                if (end - pos < ap_info->tbtt_info_len)
                        break;
 
+               bss_params = pos[1 + ETH_ALEN + 4];
                mld_params = pos + mld_params_offset;
 
                link_id = *(mld_params + 1) & EHT_ML_LINK_ID_MSK;
@@ -1546,7 +1535,13 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
                        wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
                                   *mld_params, link_id);
 
-                       if (neigh_bss) {
+                       if (!neigh_bss) {
+                               *missing |= BIT(link_id);
+                       } else if (!ssid ||
+                                  (bss_params & (RNR_BSS_PARAM_SAME_SSID |
+                                                 RNR_BSS_PARAM_CO_LOCATED)) ||
+                                  wpa_scan_res_match(wpa_s, 0, neigh_bss,
+                                                     ssid, 1, 0)) {
                                struct mld_link *l;
 
                                l = &bss->mld_links[bss->n_mld_links];
@@ -1555,8 +1550,6 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
                                          ETH_ALEN);
                                l->freq = neigh_bss->freq;
                                bss->n_mld_links++;
-                       } else {
-                               *missing |= BIT(link_id);
                        }
                }
 
@@ -1573,6 +1566,7 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
  * @link_info: Array to store link information (or %NULL),
  *   should be initialized and #MAX_NUM_MLD_LINKS elements long
  * @missing_links: Result bitmask of links that were not discovered (or %NULL)
+ * @ssid: Target SSID (or %NULL)
  * Returns: 0 on success or -1 for non-MLD or parsing failures
  *
  * Parses the Basic Multi-Link element of the BSS into @link_info using the scan
@@ -1583,7 +1577,8 @@ wpa_bss_parse_ml_rnr_ap_info(struct wpa_supplicant *wpa_s,
 int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
                                   struct wpa_bss *bss,
                                   u8 *ap_mld_addr,
-                                  u16 *missing_links)
+                                  u16 *missing_links,
+                                  struct wpa_ssid *ssid)
 {
        struct ieee802_11_elems elems;
        struct wpabuf *mlbuf;
@@ -1624,6 +1619,32 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 
        ml_ie_len = wpabuf_len(mlbuf);
 
+       if (ssid) {
+               struct wpa_ie_data ie;
+
+               if (!elems.rsn_ie ||
+                   wpa_parse_wpa_ie(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
+                                    &ie)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
+                       goto out;
+               }
+
+               if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
+                   wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "MLD: No management frame protection");
+                       goto out;
+               }
+
+               ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
+                                WPA_KEY_MGMT_PSK_SHA256);
+               if (!(ie.key_mgmt & ssid->key_mgmt)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "MLD: No valid key management");
+                       goto out;
+               }
+       }
+
        /*
         * for ext ID + 2 control + common info len + MLD address +
         * link info
@@ -1703,7 +1724,7 @@ int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
 
                        wpa_bss_parse_ml_rnr_ap_info(wpa_s, bss, mbssid_idx,
                                                     ap_info, len, &seen,
-                                                    &missing);
+                                                    &missing, ssid);
 
                        pos += ap_info_len;
                        len -= ap_info_len;
index 7b0b24c6162955ef42224eaad158b4f9e335032e..bacf0a8e9cf1cad143b4a16aed31e81d65b60a1a 100644 (file)
@@ -171,7 +171,6 @@ struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id);
 struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
                                      unsigned int idf, unsigned int idl);
 const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie);
-const u8 * wpa_bss_get_ie_nth(const struct wpa_bss *bss, u8 ie, int nth);
 const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext);
 const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type);
 const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
@@ -216,7 +215,8 @@ void calculate_update_time(const struct os_reltime *fetch_time,
 int wpa_bss_parse_basic_ml_element(struct wpa_supplicant *wpa_s,
                                   struct wpa_bss *bss,
                                   u8 *ap_mld_addr,
-                                  u16 *missing_links);
+                                  u16 *missing_links,
+                                  struct wpa_ssid *ssid);
 u16 wpa_bss_parse_reconf_ml_element(struct wpa_supplicant *wpa_s,
                                    struct wpa_bss *bss);
 
index b1a2fc6f98bfb299c04a6975c2e809646a8533ba..c404f4597f724b6994bf8113f6979353bdfcbbdf 100644 (file)
@@ -1153,7 +1153,7 @@ static bool wpas_valid_ml_bss(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
        u16 removed_links;
 
-       if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL))
+       if (wpa_bss_parse_basic_ml_element(wpa_s, bss, NULL, NULL, NULL))
                return true;
 
        if (bss->n_mld_links == 0)
@@ -1878,7 +1878,8 @@ static int wpa_supplicant_connect_ml_missing(struct wpa_supplicant *wpa_s,
 
        /* Try to resolve any missing link information */
        if (wpa_bss_parse_basic_ml_element(wpa_s, selected, NULL,
-                                          &missing_links) || !missing_links)
+                                          &missing_links, ssid) ||
+           !missing_links)
                return 0;
 
        removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, selected);
index 26abdc69c48da2ff8de5539ff020e347128f00fb..9af7a368a2d47528ba3953ec9f72c1cd1ec2acff 100644 (file)
@@ -378,225 +378,6 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
 }
 
 
-static void wpas_process_tbtt_info(struct wpa_supplicant *wpa_s, const u8 *data)
-{
-       struct wpa_bss *neigh_bss;
-       const u8 *bssid;
-       u8 bss_params;
-       u8 link_id;
-
-       /* TBTT Information field
-        * Neighbor AP TBTT Offset[1]
-        * BSSID[6]
-        * Short SSID[4]
-        * BSS parameters[1]
-        * 20 MHz PSD[1]
-        * MLD Parameters[3]
-        *   B0..B7: AP MLD ID
-        *   B7..B11: Link ID
-        *   B12..B19: BSS Parameters Change Count
-        *   B20: All Updates Included
-        *   B21: Disabled Link Indication */
-
-       bssid = data + 1;
-       bss_params = data[1 + ETH_ALEN + 4];
-
-       data += 13; /* MLD Parameters */
-       link_id = *(data + 1) & 0xF;
-
-       wpa_dbg(wpa_s, MSG_DEBUG,
-               "MLD: mld ID=%u, link ID=%u, bssid=" MACSTR ", bss_params=0x%x",
-               *data, link_id, MAC2STR(bssid), bss_params);
-
-       if (*data) {
-               wpa_printf(MSG_DEBUG, "MLD: Reported link not part of MLD");
-               return;
-       }
-
-       neigh_bss = wpa_bss_get_bssid(wpa_s, bssid);
-       if (!neigh_bss) {
-               wpa_printf(MSG_DEBUG, "MLD: Neighbor not found in scan");
-               return;
-       }
-
-       if (!((bss_params & RNR_BSS_PARAM_SAME_SSID) &&
-             (bss_params & RNR_BSS_PARAM_CO_LOCATED)) &&
-           !wpa_scan_res_match(wpa_s, 0, neigh_bss, wpa_s->current_ssid,
-                               1, 0)) {
-               wpa_printf(MSG_DEBUG,
-                          "MLD: Neighbor doesn't match current SSID - skip link");
-               return;
-       }
-
-       wpa_s->valid_links |= BIT(link_id);
-       os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
-       wpa_s->links[link_id].freq = neigh_bss->freq;
-}
-
-
-static void wpas_process_rnr(struct wpa_supplicant *wpa_s, const u8 *pos,
-                            size_t rnr_ie_len)
-{
-       while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
-               const struct ieee80211_neighbor_ap_info *ap_info =
-                       (const struct ieee80211_neighbor_ap_info *) pos;
-               /* The first TBTT Information field */
-               const u8 *data = ap_info->data;
-               u8 tbtt_count;
-               size_t len;
-               int tbtt_i;
-
-               if (rnr_ie_len < sizeof(struct ieee80211_neighbor_ap_info))
-                       break;
-
-               tbtt_count = (ap_info->tbtt_info_hdr >> 4) + 1;
-               len = sizeof(struct ieee80211_neighbor_ap_info) +
-                       ap_info->tbtt_info_len * tbtt_count;
-
-               wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
-                          ap_info->op_class, ap_info->channel);
-
-               if (len > rnr_ie_len)
-                       break;
-
-               if (ap_info->tbtt_info_len < 16) {
-                       rnr_ie_len -= len;
-                       pos += len;
-                       continue;
-               }
-
-               for (tbtt_i = 0; tbtt_i < tbtt_count; tbtt_i++) {
-                       wpas_process_tbtt_info(wpa_s, data);
-                       data += ap_info->tbtt_info_len;
-               }
-
-               rnr_ie_len -= len;
-               pos += len;
-       }
-}
-
-
-static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
-                           struct wpa_ssid *ssid)
-{
-       struct wpabuf *mlbuf;
-       const u8 *rnr_ie, *rsn_ie;
-       struct wpa_ie_data ie;
-       u8 ml_ie_len;
-       const struct ieee80211_eht_ml *eht_ml;
-       const struct eht_ml_basic_common_info *ml_basic_common_info;
-       struct ieee802_11_elems elems;
-       u8 i;
-       const u16 control =
-               host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
-                            BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
-                            BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
-                            BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
-       bool ret = false;
-       int rnr_idx;
-
-       if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
-               return false;
-
-       if (ieee802_11_parse_elems(wpa_bss_ie_ptr(bss),
-                                  bss->ie_len, &elems, 1) == ParseFailed)
-               return false;
-
-       mlbuf = ieee802_11_defrag(elems.basic_mle, elems.basic_mle_len, true);
-       if (!mlbuf) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
-               return false;
-       }
-
-       rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
-       if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
-               goto out;
-       }
-
-       if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
-           wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
-               wpa_dbg(wpa_s, MSG_DEBUG,
-                       "MLD: No management frame protection");
-               goto out;
-       }
-
-       ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
-                        WPA_KEY_MGMT_PSK_SHA256);
-       if (!(ie.key_mgmt & ssid->key_mgmt)) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
-               goto out;
-       }
-
-       ml_ie_len = wpabuf_len(mlbuf);
-
-       /* control + common info len + MLD address + MLD link information */
-       if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
-               goto out;
-
-       eht_ml = wpabuf_head(mlbuf);
-       if ((eht_ml->ml_control & control) != control) {
-               wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
-                          eht_ml->ml_control);
-               goto out;
-       }
-
-       ml_basic_common_info =
-               (const struct eht_ml_basic_common_info *) eht_ml->variable;
-
-       /* common info length should be valid (self, mld_addr, link_id) */
-       if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
-               goto out;
-
-       /* get the MLD address and MLD link ID */
-       os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
-                 ETH_ALEN);
-       wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
-               EHT_ML_LINK_ID_MSK;
-
-       os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
-                 ETH_ALEN);
-       wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
-
-       wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
-                  MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
-
-       wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
-
-       ret = true;
-
-       /* Process all Reduced Neighbor Report elements */
-       for (rnr_idx = 1; ; rnr_idx++) {
-               rnr_ie = wpa_bss_get_ie_nth(bss,
-                                           WLAN_EID_REDUCED_NEIGHBOR_REPORT,
-                                           rnr_idx);
-               if (!rnr_ie) {
-                       if (rnr_idx == 0) {
-                               wpa_dbg(wpa_s, MSG_DEBUG,
-                                       "MLD: No RNR element");
-                               goto out;
-                       }
-                       break;
-               }
-               wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
-       }
-
-       wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
-
-       for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
-               if (!(wpa_s->valid_links & BIT(i)))
-                       continue;
-
-               wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
-                          i, MAC2STR(wpa_s->links[i].bssid));
-       }
-
-out:
-       wpabuf_free(mlbuf);
-       return ret;
-}
-
-
 static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
                                         struct wpa_bss *bss)
 {
@@ -737,6 +518,27 @@ out:
 }
 
 
+static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
+                                  struct wpa_bss *bss)
+{
+       int i;
+
+       wpa_s->valid_links = 0;
+
+       for (i = 0; i < bss->n_mld_links; i++) {
+               u8 link_id = bss->mld_links[i].link_id;
+               const u8 *bssid = bss->mld_links[i].bssid;
+
+               if (i == 0)
+                       wpa_s->mlo_assoc_link_id = link_id;
+               wpa_s->valid_links |= BIT(link_id);
+               os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
+               wpa_s->links[link_id].freq = bss->mld_links[i].freq;
+               wpa_s->links[link_id].bss = wpa_bss_get_bssid(wpa_s, bssid);
+       }
+}
+
+
 static void sme_send_authentication(struct wpa_supplicant *wpa_s,
                                    struct wpa_bss *bss, struct wpa_ssid *ssid,
                                    int start)
@@ -769,8 +571,14 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
        }
 
        os_memset(&params, 0, sizeof(params));
-       if (wpas_ml_element(wpa_s, bss, ssid)) {
+
+       if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
+           !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
+                                           NULL, ssid) &&
+           bss->n_mld_links) {
                wpa_printf(MSG_DEBUG, "MLD: In authentication");
+               wpas_sme_set_mlo_links(wpa_s, bss);
+
 #ifdef CONFIG_TESTING_OPTIONS
                bss = wpas_ml_connect_pref(wpa_s, bss);