MLD: Support multiple RNR elements

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>
This commit is contained in:
Ben Greear 2023-10-28 16:24:35 -07:00 committed by Jouni Malinen
parent be212bdb55
commit 99a8dd0495
5 changed files with 64 additions and 8 deletions

View 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

View 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);

View 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

View 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,

View 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;
/* 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;