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>
This commit is contained in:
parent
39432f8a37
commit
f837a653a0
|
@ -6676,6 +6676,28 @@ cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
|
|||
return (const void *)cfg80211_find_vendor_elem(oui, oui_type, ies, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_defragment_element - Defrag the given element data into a buffer
|
||||
*
|
||||
* @elem: the element to defragment
|
||||
* @ies: elements where @elem is contained
|
||||
* @ieslen: length of @ies
|
||||
* @data: buffer to store element data
|
||||
* @data_len: length of @data
|
||||
* @frag_id: the element ID of fragments
|
||||
*
|
||||
* Return: length of @data, or -EINVAL on error
|
||||
*
|
||||
* Copy out all data from an element that may be fragmented into @data, while
|
||||
* skipping all headers.
|
||||
*
|
||||
* The function uses memmove() internally. It is acceptable to defragment an
|
||||
* element in-place.
|
||||
*/
|
||||
ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies,
|
||||
size_t ieslen, u8 *data, size_t data_len,
|
||||
u8 frag_id);
|
||||
|
||||
/**
|
||||
* cfg80211_send_layer2_update - send layer 2 update frame
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue