}
+/**
+ * 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
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);
}
+/**
+ * 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
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,
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;
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);
i, MAC2STR(wpa_s->links[i].bssid));
}
- ret = true;
out:
wpabuf_free(mlbuf);
return ret;