]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MLD: Support multiple RNR elements
authorBen Greear <greearb@candelatech.com>
Sat, 28 Oct 2023 23:24:35 +0000 (16:24 -0700)
committerJouni Malinen <j@w1.fi>
Tue, 7 Nov 2023 16:55:50 +0000 (18:55 +0200)
Beacon frames are allowed to optionally include one more more Reduced
Neighbor Report elements. Only the first one was parsed previously.
Extend this to use a loop to go through all included RNR elements.

Signed-off-by: Ben Greear <greearb@candelatech.com>
src/common/ieee802_11_common.c
src/common/ieee802_11_common.h
wpa_supplicant/bss.c
wpa_supplicant/bss.h
wpa_supplicant/sme.c

index 093339cb4392b13d144a4a05e9c81810ad2ded58..70d56ffbf2873a5754a7282fe43d57f99e859393 100644 (file)
@@ -2495,6 +2495,35 @@ 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 f8cede008485a2f036db35a30471e72818aaaceb..00dc2fb108e6caf23b6702d23a93f0b266a94f06 100644 (file)
@@ -261,6 +261,7 @@ 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 2ad74f3a4b4eadd2c895492e25efaf0c0b9b4d9d..26cdeaf28b4c2c17fed1a68c549b1044a0cf465b 100644 (file)
@@ -1220,6 +1220,22 @@ 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
index 39dad868e71a91d59caa45933c07d3a53f0c4280..9e673db0d488ae5c8a54947232b38a56df5a0edb 100644 (file)
@@ -169,6 +169,7 @@ 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,
index 9a9ada25157b9b2b06ea53568cb9738656dc0cc1..4448a8d3cfc258a9efa07940646271217a9c7aad 100644 (file)
@@ -454,6 +454,7 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                             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;
@@ -519,14 +520,23 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
 
        wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
 
-       rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
-       if (!rnr_ie) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element");
-               ret = true;
-               goto out;
-       }
+       ret = true;
 
-       wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
+       /* 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);
 
@@ -538,7 +548,6 @@ static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
                           i, MAC2STR(wpa_s->links[i].bssid));
        }
 
-       ret = true;
 out:
        wpabuf_free(mlbuf);
        return ret;