Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 08 Dec 2025 15:44:19 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 85db0f528a06 - stable/15 - LinuxKPI: 802.11: fill in more skeleton functions
Message-ID:  <6936f253.374e4.53267e5d@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help

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),



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6936f253.374e4.53267e5d>