mac80211: handle RIC data element in reassociation request
When the RIC data element (RDE) is included in the IEs coming from userspace for an association request, its handling is currently broken as any IEs that are contained within it would be split off from it and inserted again after all the IEs that mac80211 generates (e.g. HT, VHT.) To fix this, treat the RIC element specially, and stop after it only when we find something that doesn't actually belong to it. This assumes userspace is actually correctly building it, directly after the fast BSS transition IE and before all the others like extended capabilities. This leaves as a potential problem the case where userspace is building the following IEs: [RDE] [vendor resource description] [vendor non-resource IE] In this case, we'd erroneously consider all three IEs to be part of the RIC data together, and not split them between the two vendor IEs. Unfortunately, it isn't easily possible to distinguish vendor IEs, so this isn't easy to fix. Luckily, this case is rare as normally wpa_supplicant will include an extended capabilities IE in the IEs, and that certainly will break the two vendor IEs apart correctly. Reviewed-by: Eliad Peller <eliad@wizery.com> Reviewed-by: Beni Lev <beni.lev@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
239281f803
commit
8ed2874715
|
@ -1903,6 +1903,10 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
|
|||
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids,
|
||||
const u8 *after_ric, int n_after_ric,
|
||||
size_t offset);
|
||||
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
|
||||
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
|
||||
u16 cap);
|
||||
|
|
|
@ -775,11 +775,30 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||
WLAN_EID_QOS_CAPA,
|
||||
WLAN_EID_RRM_ENABLED_CAPABILITIES,
|
||||
WLAN_EID_MOBILITY_DOMAIN,
|
||||
WLAN_EID_FAST_BSS_TRANSITION, /* reassoc only */
|
||||
WLAN_EID_RIC_DATA, /* reassoc only */
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
||||
};
|
||||
noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
|
||||
before_ht, ARRAY_SIZE(before_ht),
|
||||
offset);
|
||||
static const u8 after_ric[] = {
|
||||
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
|
||||
WLAN_EID_HT_CAPABILITY,
|
||||
WLAN_EID_BSS_COEX_2040,
|
||||
WLAN_EID_EXT_CAPABILITY,
|
||||
WLAN_EID_QOS_TRAFFIC_CAPA,
|
||||
WLAN_EID_TIM_BCAST_REQ,
|
||||
WLAN_EID_INTERWORKING,
|
||||
/* 60GHz doesn't happen right now */
|
||||
WLAN_EID_VHT_CAPABILITY,
|
||||
WLAN_EID_OPMODE_NOTIF,
|
||||
};
|
||||
|
||||
noffset = ieee80211_ie_split_ric(assoc_data->ie,
|
||||
assoc_data->ie_len,
|
||||
before_ht,
|
||||
ARRAY_SIZE(before_ht),
|
||||
after_ric,
|
||||
ARRAY_SIZE(after_ric),
|
||||
offset);
|
||||
pos = skb_put(skb, noffset - offset);
|
||||
memcpy(pos, assoc_data->ie + offset, noffset - offset);
|
||||
offset = noffset;
|
||||
|
@ -813,6 +832,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
|
|||
WLAN_EID_TIM_BCAST_REQ,
|
||||
WLAN_EID_INTERWORKING,
|
||||
};
|
||||
|
||||
/* RIC already taken above, so no need to handle here anymore */
|
||||
noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
|
||||
before_vht, ARRAY_SIZE(before_vht),
|
||||
offset);
|
||||
|
|
|
@ -2101,16 +2101,34 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids, size_t offset)
|
||||
size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids,
|
||||
const u8 *after_ric, int n_after_ric,
|
||||
size_t offset)
|
||||
{
|
||||
size_t pos = offset;
|
||||
|
||||
while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
|
||||
pos += 2 + ies[pos + 1];
|
||||
while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
|
||||
if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
|
||||
pos += 2 + ies[pos + 1];
|
||||
|
||||
while (pos < ielen &&
|
||||
!ieee80211_id_in_list(after_ric, n_after_ric,
|
||||
ies[pos]))
|
||||
pos += 2 + ies[pos + 1];
|
||||
} else {
|
||||
pos += 2 + ies[pos + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
|
||||
const u8 *ids, int n_ids, size_t offset)
|
||||
{
|
||||
return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_ie_split);
|
||||
|
||||
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
|
||||
|
|
Loading…
Reference in New Issue