diff options
author | Benjamin Berg <benjamin.berg@intel.com> | 2023-06-16 09:54:05 +0300 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2023-06-19 13:05:29 +0300 |
commit | f837a653a09700daa136a3db49c0c97d7295ca30 (patch) | |
tree | 90346dcd83b8a7178a635eb5fed80ff0c5c4de0a /net/wireless | |
parent | 39432f8a3752a87a53fd8d5e51824a43aaae5cab (diff) | |
download | linux-f837a653a09700daa136a3db49c0c97d7295ca30.tar.xz |
wifi: cfg80211: add element defragmentation helper
This is already needed within mac80211 and support is also needed by
cfg80211 to parse ML elements.
Signed-off-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Gregory Greenman <gregory.greenman@intel.com>
Link: https://lore.kernel.org/r/20230616094949.29c3ebeed10d.I009c049289dd0162c2e858ed8b68d2875a672ed6@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/scan.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 75e6e032bb3a..dc71c6ac5bf5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2288,6 +2288,66 @@ out: kfree(profile); } +ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies, + size_t ieslen, u8 *data, size_t data_len, + u8 frag_id) +{ + const struct element *next; + ssize_t copied; + u8 elem_datalen; + + if (!elem) + return -EINVAL; + + /* elem might be invalid after the memmove */ + next = (void *)(elem->data + elem->datalen); + + elem_datalen = elem->datalen; + if (elem->id == WLAN_EID_EXTENSION) { + copied = elem->datalen - 1; + if (copied > data_len) + return -ENOSPC; + + memmove(data, elem->data + 1, copied); + } else { + copied = elem->datalen; + if (copied > data_len) + return -ENOSPC; + + memmove(data, elem->data, copied); + } + + /* Fragmented elements must have 255 bytes */ + if (elem_datalen < 255) + return copied; + + for (elem = next; + elem->data < ies + ieslen && + elem->data + elem->datalen < ies + ieslen; + elem = next) { + /* elem might be invalid after the memmove */ + next = (void *)(elem->data + elem->datalen); + + if (elem->id != frag_id) + break; + + elem_datalen = elem->datalen; + + if (copied + elem_datalen > data_len) + return -ENOSPC; + + memmove(data + copied, elem->data, elem_datalen); + copied += elem_datalen; + + /* Only the last fragment may be short */ + if (elem_datalen != 255) + break; + } + + return copied; +} +EXPORT_SYMBOL(cfg80211_defragment_element); + struct cfg80211_bss * cfg80211_inform_bss_data(struct wiphy *wiphy, struct cfg80211_inform_bss *data, |