diff options
author | Johannes Berg <johannes.berg@intel.com> | 2015-09-04 20:03:23 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-10-27 16:03:27 +0200 |
commit | 8ac63448651f579494894f9687a759b9112967df (patch) | |
tree | 763277cdb472857c5e07d87f16dfa198dfc03b5e /net/wireless/util.c | |
parent | ce0ce13a1c89ff8b94b7f8fb32eb4c43e111c82e (diff) | |
download | linux-8ac63448651f579494894f9687a759b9112967df.tar.gz linux-8ac63448651f579494894f9687a759b9112967df.tar.bz2 linux-8ac63448651f579494894f9687a759b9112967df.zip |
cfg80211: handle fragmented IEs in splitting
The IEs "output" can sometimes combine IEs coming from userspace
with IEs generated in the kernel - in particular mac80211 does
this for association frames.
Add support in this code for the 802.11 IE fragmentation.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index 7681b65c4a3b..32060f81a8e7 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1382,6 +1382,25 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) return false; } +static size_t skip_ie(const u8 *ies, size_t ielen, size_t pos) +{ + /* we assume a validly formed IEs buffer */ + u8 len = ies[pos + 1]; + + pos += 2 + len; + + /* the IE itself must have 255 bytes for fragments to follow */ + if (len < 255) + return pos; + + while (pos < ielen && ies[pos] == WLAN_EID_FRAGMENT) { + len = ies[pos + 1]; + pos += 2 + len; + } + + return pos; +} + 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, @@ -1391,14 +1410,14 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen, 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]; + pos = skip_ie(ies, ielen, pos); while (pos < ielen && !ieee80211_id_in_list(after_ric, n_after_ric, ies[pos])) - pos += 2 + ies[pos + 1]; + pos = skip_ie(ies, ielen, pos); } else { - pos += 2 + ies[pos + 1]; + pos = skip_ie(ies, ielen, pos); } } |