summaryrefslogtreecommitdiff
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2022-07-07 15:28:14 +0200
committerJohannes Berg <johannes.berg@intel.com>2022-07-15 11:43:19 +0200
commite434254946c64bb27d7b202c0eeac03e49c166aa (patch)
treeea17abb92e362c85d2b9e4956df1b9236252e3ce /net/mac80211/util.c
parent8a263dcb585f5d4193e33e22ae245e90dd0b0786 (diff)
wifi: mac80211: add a helper to fragment an element
The way this works is that you add all the element data, keeping a pointer to the length field of the element. Then call this helper function, which will fragment the element if there was more than 255 bytes in the element, memmove()ing the data back if needed. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 6d6ba23aa074..2ff8d1ec564c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -4780,3 +4780,31 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos,
return pos;
}
+
+void ieee80211_fragment_element(struct sk_buff *skb, u8 *len_pos)
+{
+ unsigned int elem_len;
+
+ if (!len_pos)
+ return;
+
+ elem_len = skb->data + skb->len - len_pos - 1;
+
+ while (elem_len > 255) {
+ /* this one is 255 */
+ *len_pos = 255;
+ /* remaining data gets smaller */
+ elem_len -= 255;
+ /* make space for the fragment ID/len in SKB */
+ skb_put(skb, 2);
+ /* shift back the remaining data to place fragment ID/len */
+ memmove(len_pos + 255 + 3, len_pos + 255 + 1, elem_len);
+ /* place the fragment ID */
+ len_pos += 255 + 1;
+ *len_pos = WLAN_EID_FRAGMENT;
+ /* and point to fragment length to update later */
+ len_pos++;
+ }
+
+ *len_pos = elem_len;
+}