From ad1c72140c390cd07b7a1e5b694e6c96db341954 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Mar 2023 16:59:08 +0200 Subject: [PATCH] wifi: ieee80211: correctly mark FTM frames non-bufferable The checks of whether or not a frame is bufferable were not taking into account that some action frames aren't, such as FTM. Check this, which requires some changes to the function ieee80211_is_bufferable_mmpdu() since we need the whole skb for the checks now. Reviewed-by: Ilan Peer Signed-off-by: Johannes Berg Signed-off-by: Christian Lamparter --- include/linux/ieee80211.h | 52 ++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 5c88243..1ec899d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -786,20 +786,6 @@ static inline bool ieee80211_is_any_nullfunc(__le16 fc) return (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)); } -/** - * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU - * @fc: frame control field in little-endian byteorder - */ -static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc) -{ - /* IEEE 802.11-2012, definition of "bufferable management frame"; - * note that this ignores the IBSS special case. */ - return ieee80211_is_mgmt(fc) && - (ieee80211_is_action(fc) || - ieee80211_is_disassoc(fc) || - ieee80211_is_deauth(fc)); -} - /** * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set * @seq_ctrl: frame sequence control bytes in little-endian byteorder @@ -4132,6 +4118,44 @@ static inline u8 *ieee80211_get_SA(struct ieee80211_hdr *hdr) return hdr->addr2; } +/** + * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU + * @skb: the skb to check, starting with the 802.11 header + */ +static inline bool ieee80211_is_bufferable_mmpdu(struct ieee80211_hdr *hdr, size_t len) +{ + struct ieee80211_mgmt *mgmt = (void *)hdr; + __le16 fc = mgmt->frame_control; + + /* + * IEEE 802.11 REVme D2.0 definition of bufferable MMPDU; + * note that this ignores the IBSS special case. + */ + if (!ieee80211_is_mgmt(fc)) + return false; + + if (ieee80211_is_disassoc(fc) || ieee80211_is_deauth(fc)) + return true; + + if (!ieee80211_is_action(fc)) + return false; + + if (len < offsetofend(typeof(*mgmt), u.action.u.ftm.action_code)) + return true; + + /* action frame - additionally check for non-bufferable FTM */ + + if (mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && + mgmt->u.action.category != WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION) + return true; + + if (mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_REQUEST || + mgmt->u.action.u.ftm.action_code == WLAN_PUB_ACTION_FTM_RESPONSE) + return false; + + return true; +} + /** * ieee80211_get_DA - get pointer to DA * @hdr: the frame -- 2.31.1