cfg80211: use for_each_element() for multi-bssid parsing

Use the new for_each_element() helper here, we cannot use
for_each_subelement() since we have a fixed 1 byte before
the subelements start.

While at it, also fix le16_to_cpup() to be get_unaligned_le16()
since we don't know anything about alignment.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2019-02-07 22:36:33 +01:00
parent 0b8fb8235b
commit 1c8745f3ec
1 changed files with 15 additions and 32 deletions

View File

@ -1377,9 +1377,9 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
struct cfg80211_bss *trans_bss, struct cfg80211_bss *trans_bss,
gfp_t gfp) gfp_t gfp)
{ {
const u8 *pos, *subelement, *mbssid_end_pos; const u8 *mbssid_index_ie;
const u8 *tmp, *mbssid_index_ie; const struct element *elem, *sub;
size_t subie_len, new_ie_len; size_t new_ie_len;
u8 new_bssid[ETH_ALEN]; u8 new_bssid[ETH_ALEN];
u8 *new_ie; u8 *new_ie;
u16 capability; u16 capability;
@ -1390,34 +1390,21 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen)) if (!cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ie, ielen))
return; return;
pos = ie;
new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp); new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
if (!new_ie) if (!new_ie)
return; return;
while (pos < ie + ielen + 2) { for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) {
tmp = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, pos, if (elem->datalen < 4)
ielen - (pos - ie)); continue;
if (!tmp) for_each_element(sub, elem->data + 1, elem->datalen - 1) {
break; if (sub->id != 0 || sub->datalen < 4) {
mbssid_end_pos = tmp + tmp[1] + 2;
/* Skip Element ID, Len, MaxBSSID Indicator */
if (tmp[1] < 4)
break;
for (subelement = tmp + 3; subelement < mbssid_end_pos - 1;
subelement += 2 + subelement[1]) {
subie_len = subelement[1];
if (mbssid_end_pos - subelement < 2 + subie_len)
break;
if (subelement[0] != 0 || subelement[1] < 4) {
/* not a valid BSS profile */ /* not a valid BSS profile */
continue; continue;
} }
if (subelement[2] != WLAN_EID_NON_TX_BSSID_CAP || if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
subelement[3] != 2) { sub->data[1] != 2) {
/* The first element within the Nontransmitted /* The first element within the Nontransmitted
* BSSID Profile is not the Nontransmitted * BSSID Profile is not the Nontransmitted
* BSSID Capability element. * BSSID Capability element.
@ -1428,26 +1415,24 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
/* found a Nontransmitted BSSID Profile */ /* found a Nontransmitted BSSID Profile */
mbssid_index_ie = cfg80211_find_ie mbssid_index_ie = cfg80211_find_ie
(WLAN_EID_MULTI_BSSID_IDX, (WLAN_EID_MULTI_BSSID_IDX,
subelement + 2, subie_len); sub->data, sub->datalen);
if (!mbssid_index_ie || mbssid_index_ie[1] < 1 || if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
mbssid_index_ie[2] == 0) { mbssid_index_ie[2] == 0) {
/* No valid Multiple BSSID-Index element */ /* No valid Multiple BSSID-Index element */
continue; continue;
} }
cfg80211_gen_new_bssid(bssid, tmp[2], cfg80211_gen_new_bssid(bssid, elem->data[0],
mbssid_index_ie[2], mbssid_index_ie[2],
new_bssid); new_bssid);
memset(new_ie, 0, IEEE80211_MAX_DATA_LEN); memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
new_ie_len = cfg80211_gen_new_ie(ie, ielen, new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data,
subelement + 2, sub->datalen, new_ie,
subie_len, new_ie,
gfp); gfp);
if (!new_ie_len) if (!new_ie_len)
continue; continue;
capability = le16_to_cpup((const __le16 *) capability = get_unaligned_le16(sub->data + 2);
&subelement[4]);
bss = cfg80211_inform_single_bss_data(wiphy, data, bss = cfg80211_inform_single_bss_data(wiphy, data,
ftype, ftype,
new_bssid, tsf, new_bssid, tsf,
@ -1460,8 +1445,6 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
break; break;
cfg80211_put_bss(wiphy, bss); cfg80211_put_bss(wiphy, bss);
} }
pos = mbssid_end_pos;
} }
kfree(new_ie); kfree(new_ie);