git: 85db0f528a06 - stable/15 - LinuxKPI: 802.11: fill in more skeleton functions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 08 Dec 2025 15:44:19 UTC
The branch stable/15 has been updated by bz:
URL: https://cgit.FreeBSD.org/src/commit/?id=85db0f528a067e298eabfcaf9c845369999c6dda
commit 85db0f528a067e298eabfcaf9c845369999c6dda
Author: Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-11-29 03:19:47 +0000
Commit: Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-12-08 15:43:53 +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
(cherry picked from commit af22833348c6c7ffed0186651437b5f50be1550b)
---
.../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),