From 88f7d4cedfeacb24e794fc93cde616582301c27c Mon Sep 17 00:00:00 2001 From: Pooventhiran G Date: Fri, 11 Apr 2025 16:58:31 +0530 Subject: [PATCH] Helper function for defragmenting of Multi-Link element subelements Subelements contained within an Multi-Link element can themselves be fragmented if they pack more than 255 bytes of data using a Fragment subelement similar to how the Multi-Link element uses a Fragment element. Add a helper function to enable this nested defragmentation by parsing subelements in a defragmented Multi-Link element. Reviewed-by: Rohan Dutta Signed-off-by: Pooventhiran G --- src/common/ieee802_11_common.c | 64 ++++++++++++++++++++++++++++++++++ src/common/ieee802_11_common.h | 3 ++ 2 files changed, 67 insertions(+) diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 1d28437fe..1adb08eaf 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -3436,6 +3436,70 @@ struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem) } +/** + * ieee802_11_defrag_mle_subelem - Defragment Multi-Link element subelements + * @mlbuf: Defragmented mlbuf (defragmented using ieee802_11_defrag()) + * @parent_subelem: Pointer to the subelement which may be fragmented + * @defrag_len: Defragmented length of the subelement + * Returns: Number of Fragment subelements parsed on success, -1 otherwise + * + * This function defragments a subelement present inside an Multi-Link element. + * It should be called individually for each subelement. + * + * Subelements can use the Fragment subelement if they pack more than 255 bytes + * of data, see IEEE P802.11be/D7.0 Figure 35-4 - Per-STA Profile subelement + * fragmentation within a fragmented Multi-Link element. + */ +size_t ieee802_11_defrag_mle_subelem(struct wpabuf *mlbuf, + const u8 *parent_subelem, + size_t *defrag_len) +{ + u8 *buf, *pos, *end; + size_t len, subelem_len; + const size_t min_defrag_len = 255; + int num_frag_subelems = 0; + + if (!mlbuf || !parent_subelem) + return -1; + + buf = wpabuf_mhead_u8(mlbuf); + len = wpabuf_len(mlbuf); + end = buf + len; + + *defrag_len = parent_subelem[1]; + if (parent_subelem[1] < min_defrag_len) + return 0; + + pos = (u8 *) parent_subelem; + if (2 + parent_subelem[1] > end - pos) + return -1; + pos += 2 + parent_subelem[1]; + subelem_len = parent_subelem[1]; + + while (end - pos > 2 && + pos[0] == MULTI_LINK_SUB_ELEM_ID_FRAGMENT && pos[1]) { + size_t elen = 2 + pos[1]; + + /* This Multi-Link parent subelement has more data and is + * fragmented. */ + num_frag_subelems++; + + if (elen > (size_t) (end - pos)) + return -1; + + os_memmove(pos, pos + 2, end - (pos + 2)); + pos += elen - 2; + subelem_len += elen - 2; + + /* Deduct Fragment subelement header */ + len -= 2; + } + + *defrag_len = subelem_len; + return num_frag_subelems; +} + + const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type) { const struct element *elem; diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index 0edd34c65..abd17f062 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -378,6 +378,9 @@ int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed, struct ieee80211_edmg_config requested); struct wpabuf * ieee802_11_defrag(const u8 *data, size_t len, bool ext_elem); +size_t ieee802_11_defrag_mle_subelem(struct wpabuf *mlbuf, + const u8 *parent_subelem, + size_t *defrag_len); const u8 * get_ml_ie(const u8 *ies, size_t len, u8 type); const u8 * get_basic_mle_mld_addr(const u8 *buf, size_t len); -- 2.47.2