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

Reply via email to