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:
parent
be212bdb55
commit
99a8dd0495
5 changed files with 64 additions and 8 deletions
|
@ -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
|
* get_ie_ext - Fetch a specified extended information element from IEs buffer
|
||||||
* @ies: Information elements buffer
|
* @ies: Information elements buffer
|
||||||
|
|
|
@ -261,6 +261,7 @@ extern const struct oper_class_map global_op_class[];
|
||||||
extern size_t global_op_class_size;
|
extern size_t global_op_class_size;
|
||||||
|
|
||||||
const u8 * get_ie(const u8 *ies, size_t len, u8 eid);
|
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_ie_ext(const u8 *ies, size_t len, u8 ext);
|
||||||
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
const u8 * get_vendor_ie(const u8 *ies, size_t len, u32 vendor_type);
|
||||||
|
|
||||||
|
|
|
@ -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
|
* wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry
|
||||||
* @bss: BSS table entry
|
* @bss: BSS table entry
|
||||||
|
|
|
@ -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,
|
struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s,
|
||||||
unsigned int idf, unsigned int idl);
|
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(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_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(const struct wpa_bss *bss, u32 vendor_type);
|
||||||
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
|
const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss,
|
||||||
|
|
|
@ -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_BSS_PARAM_CH_COUNT |
|
||||||
BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
|
BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
int rnr_idx;
|
||||||
|
|
||||||
if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
|
if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
|
||||||
return false;
|
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);
|
wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
|
||||||
|
|
||||||
rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
|
ret = true;
|
||||||
if (!rnr_ie) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element");
|
|
||||||
ret = true;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
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));
|
i, MAC2STR(wpa_s->links[i].bssid));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = true;
|
|
||||||
out:
|
out:
|
||||||
wpabuf_free(mlbuf);
|
wpabuf_free(mlbuf);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue