The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=af22833348c6c7ffed0186651437b5f50be1550b
commit af22833348c6c7ffed0186651437b5f50be1550b Author: Bjoern A. Zeeb <[email protected]> AuthorDate: 2025-11-29 03:19:47 +0000 Commit: Bjoern A. Zeeb <[email protected]> CommitDate: 2025-12-03 19:54:43 +0000 LinuxKPI: 802.11: fill in more skeleton functions Some of these are used by mt76 and while I was here and it only was a handfull I figured I should just clean this all up. There is one problem in that between 802.11az and 802.11-2024 action frame formats have changed; I got compile errors from iwlwifi(4) given I updated them to -2024 so we remain on older versions for the moment. Sponsored by: The FreeBSD Foundation MFC after: 3 days --- .../linuxkpi/common/include/linux/ieee80211.h | 168 +++++++++++++++++---- sys/compat/linuxkpi/common/include/net/cfg80211.h | 4 + 2 files changed, 141 insertions(+), 31 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/ieee80211.h b/sys/compat/linuxkpi/common/include/linux/ieee80211.h index ea8c0fc8ef5e..12160df43915 100644 --- a/sys/compat/linuxkpi/common/include/linux/ieee80211.h +++ b/sys/compat/linuxkpi/common/include/linux/ieee80211.h @@ -43,8 +43,13 @@ extern int linuxkpi_debug_80211; #ifndef D80211_TODO #define D80211_TODO 0x1 #endif +#ifndef D80211_IMPROVE +#define D80211_IMPROVE 0x2 +#endif #define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) +#define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ + printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) /* 9.4.2.55 Management MIC element (CMAC-256, GMAC-128, and GMAC-256). */ @@ -568,17 +573,25 @@ struct ieee80211_mgmt { uint8_t tpc_elem_tx_power; uint8_t tpc_elem_link_margin; } __packed tpc_report; - /* 9.6.8.33 Fine Timing Measurement frame format */ + /* 802.11-2024, 9.6.7.32 FTM Request frame format */ + struct { + uint8_t public_action; + uint8_t trigger; + uint8_t variable[0]; + } __packed ftmr; + /* 802.11az-2022, 9.6.7.33 Fine Timing Measurement (FTM) frame format */ + /* XXX CHANGED IN 802.11-2024, 9.6.7.33 Fine Timing Measurement frame format */ struct { - uint8_t dialog_token; - uint8_t follow_up; - uint8_t tod[6]; - uint8_t toa[6]; + uint8_t public_action; + uint8_t dialog_token; + uint8_t follow_up; + uint8_t tod[6]; + uint8_t toa[6]; uint16_t tod_error; uint16_t toa_error; uint8_t variable[0]; } __packed ftm; - /* 802.11-2016, 9.6.5.2 ADDBA Request frame format */ + /* 802.11-2024, 9.6.4.2 ADDBA Request frame format */ struct { uint8_t action_code; uint8_t dialog_token; @@ -588,9 +601,12 @@ struct ieee80211_mgmt { /* Optional follows... */ uint8_t variable[0]; } __packed addba_req; - /* XXX */ + /* 802.11-2024, 9.6.13.3 Event Report frame format */ struct { + uint8_t wnm_action; uint8_t dialog_token; + /* Optional follows... */ + uint8_t variable[0]; } __packed wnm_timing_msr; } u; } __packed action; @@ -1087,24 +1103,42 @@ ieee80211_is_bufferable_mmpdu(struct sk_buff *skb) struct ieee80211_mgmt *mgmt; __le16 fc; + KASSERT(skb->len >= sizeof(fc), ("%s: skb %p short len %d\n", + __func__, skb, skb->len)); + mgmt = (struct ieee80211_mgmt *)skb->data; fc = mgmt->frame_control; - /* 11.2.2 Bufferable MMPDUs, 80211-2020. */ - /* XXX we do not care about IBSS yet. */ + /* 11.2.2 Bufferable MMPDUs, 802.11-2024. */ + IMPROVE("XXX IBBS"); if (!ieee80211_is_mgmt(fc)) return (false); - if (ieee80211_is_action(fc)) /* XXX FTM? */ - return (true); /* XXX false? */ if (ieee80211_is_disassoc(fc)) return (true); if (ieee80211_is_deauth(fc)) return (true); + if (!ieee80211_is_action(fc)) + return (false); - TODO(); + /* + * Now we know it is an action frame, so we can check for a proper + * length before accessing any further data to check if it is an + * FTM/FTMR, which is non-bufferable. + * 9.6.7.32 FTM Request frame format + * 9.6.7.33 FTM frame format + */ + if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.public_action)) + return (false); - return (false); + if (mgmt->u.action.category != IEEE80211_ACTION_CAT_PUBLIC) + return (false); + + if (mgmt->u.action.u.ftm.public_action == 33 || /* FTM xxx defines? */ + mgmt->u.action.u.ftmr.public_action == 32) /* FTMR xxx defines? */ + return (false); + + return (true); } static __inline bool @@ -1207,53 +1241,125 @@ ieee80211_get_DA(struct ieee80211_hdr *hdr) return (hdr->addr1); } +static __inline bool +ieee80211_has_morefrags(__le16 fc) +{ + + fc &= htole16(IEEE80211_FC1_MORE_FRAG << 8); + return (fc != 0); +} + static __inline bool ieee80211_is_frag(struct ieee80211_hdr *hdr) { - TODO(); - return (false); + return (ieee80211_has_morefrags(hdr->frame_control) || + (hdr->seq_ctrl & htole16(IEEE80211_SEQ_FRAG_MASK)) != 0); } static __inline bool -ieee80211_is_first_frag(__le16 fc) +ieee80211_is_first_frag(__le16 seq_ctrl) { - TODO(); - return (false); + return ((seq_ctrl & htole16(IEEE80211_SEQ_FRAG_MASK)) == 0); } static __inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb) { - TODO(); - return (false); + struct ieee80211_mgmt *mgmt; + + if (skb->len < sizeof(mgmt->frame_control)) + return (false); + mgmt = (struct ieee80211_mgmt *)skb->data; + + /* 802.11-2024, 12.2.7 Requirements for management frame protection */ + + if (ieee80211_is_disassoc(mgmt->frame_control)) + return (true); + if (ieee80211_is_deauth(mgmt->frame_control)) + return (true); + + if (!ieee80211_is_action(mgmt->frame_control)) + return (false); + + /* + * If the action frame is a protected frame the peer has already + * decided that it is a robust mgmt frame. + * This is not exactly in the books but maintaining the below + * table will go out of sync eventually and this can save us. + */ + if (ieee80211_has_protected(mgmt->frame_control)) + return (true); + + /* + * 802.11-2024, 9.4.1.11 Action Fields, + * Table 9-81-Category values; check for the ones marked Robust: no. + */ + /* Check length again before accessing more data. */ + if (skb->len < offsetofend(typeof(*mgmt), u.action.category)) + return (false); + + switch (mgmt->u.action.category) { + case 4: /* Public */ + case 7: /* HT */ + case 11: /* Unprotected WNM */ + /* 12 */ /* TDLS */ + case 15: /* Self-protected */ + case 20: /* Unprotected DMG */ + case 21: /* VHT */ + case 22: /* Unprotected S1G */ + case 30: /* HE */ + case 127: /* Vendor-specific */ + return (false); + default: + return (true); + } } static __inline bool ieee80211_is_ftm(struct sk_buff *skb) { - TODO(); + struct ieee80211_mgmt *mgmt; + + /* First check length before accessing data. */ + if (skb->len < offsetofend(typeof(*mgmt), u.action.u.ftm.public_action)) + return (false); + + mgmt = (struct ieee80211_mgmt *)skb->data; + if (!ieee80211_is_action(mgmt->frame_control)) + return (false); + if (mgmt->u.action.category != IEEE80211_ACTION_CAT_PUBLIC) + return (false); + if (mgmt->u.action.u.ftm.public_action == 33) /* FTM xxx defines? */ + return (true); + return (false); } static __inline bool ieee80211_is_timing_measurement(struct sk_buff *skb) { - TODO(); - return (false); -} + struct ieee80211_mgmt *mgmt; + + /* First check length before accessing data. */ + if (skb->len < offsetofend(typeof(*mgmt), u.action.u.wnm_timing_msr.wnm_action)) + return (false); + + mgmt = (struct ieee80211_mgmt *)skb->data; + if (!ieee80211_is_action(mgmt->frame_control)) + return (false); + + if (mgmt->u.action.category != IEEE80211_ACTION_CAT_UNPROTECTED_WNM) + return (false); + if (mgmt->u.action.u.wnm_timing_msr.wnm_action == 1) /* Event Report xxx defines? */ + return (true); -static __inline bool -ieee80211_has_pm(__le16 fc) -{ - TODO(); return (false); } static __inline bool -ieee80211_has_morefrags(__le16 fc) +ieee80211_has_pm(__le16 fc) { - - fc &= htole16(IEEE80211_FC1_MORE_FRAG << 8); + fc &= htole16(IEEE80211_FC1_PWR_MGT << 8); return (fc != 0); } diff --git a/sys/compat/linuxkpi/common/include/net/cfg80211.h b/sys/compat/linuxkpi/common/include/net/cfg80211.h index 305026b34451..d7ed2bc97c98 100644 --- a/sys/compat/linuxkpi/common/include/net/cfg80211.h +++ b/sys/compat/linuxkpi/common/include/net/cfg80211.h @@ -55,10 +55,14 @@ extern int linuxkpi_debug_80211; #ifndef D80211_IMPROVE #define D80211_IMPROVE 0x2 #endif +#ifndef TODO #define TODO(fmt, ...) if (linuxkpi_debug_80211 & D80211_TODO) \ printf("%s:%d: XXX LKPI80211 TODO " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) +#endif +#ifndef IMPROVE #define IMPROVE(fmt, ...) if (linuxkpi_debug_80211 & D80211_IMPROVE) \ printf("%s:%d: XXX LKPI80211 IMPROVE " fmt "\n", __func__, __LINE__, ##__VA_ARGS__) +#endif enum rfkill_hard_block_reasons { RFKILL_HARD_BLOCK_NOT_OWNER = BIT(0),
