wifi: mac80211: hide element parsing internals
authorJohannes Berg <johannes.berg@intel.com>
Wed, 28 Feb 2024 08:48:16 +0000 (09:48 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 4 Mar 2024 13:33:03 +0000 (14:33 +0100)
Rework the data structures to hide element parsing internals
from the users.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240228094902.19c610b529e2.Ie7ea2dcb6713911590ace6583a4748f32dc37df2@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/parse.c
net/mac80211/tests/elems.c

index caee68cc8f14f03ec834e0b25b420c57a2ec24e8..da320799fbff8ba7696980613c1e613d177745d4 100644 (file)
@@ -1766,12 +1766,6 @@ struct ieee802_11_elems {
        size_t ml_basic_len;
        size_t ml_reconf_len;
 
-       /* The basic Multi-Link element in the original elements */
-       const struct element *ml_basic_elem;
-
-       /* The reconfiguration Multi-Link element in the original elements */
-       const struct element *ml_reconf_elem;
-
        u8 ttlm_num;
 
        /*
@@ -1784,14 +1778,6 @@ struct ieee802_11_elems {
 
        /* whether/which parse error occurred while retrieving these elements */
        u8 parse_error;
-
-       /*
-        * scratch buffer that can be used for various element parsing related
-        * tasks, e.g., element de-fragmentation etc.
-        */
-       size_t scratch_len;
-       u8 *scratch_pos;
-       u8 scratch[] __counted_by(scratch_len);
 };
 
 static inline struct ieee80211_local *hw_to_local(
index 73e52504ed97c826e11ecb2960f7a99b42307359..55e5497f89781c0fc2c74965b30b966366672d25 100644 (file)
 #include "led.h"
 #include "wep.h"
 
+struct ieee80211_elems_parse {
+       /* must be first for kfree to work */
+       struct ieee802_11_elems elems;
+
+       /* The basic Multi-Link element in the original elements */
+       const struct element *ml_basic_elem;
+
+       /* The reconfiguration Multi-Link element in the original elements */
+       const struct element *ml_reconf_elem;
+
+       /*
+        * scratch buffer that can be used for various element parsing related
+        * tasks, e.g., element de-fragmentation etc.
+        */
+       size_t scratch_len;
+       u8 *scratch_pos;
+       u8 scratch[] __counted_by(scratch_len);
+};
+
 static void
 ieee80211_parse_extension_element(u32 *crc,
                                  const struct element *elem,
-                                 struct ieee802_11_elems *elems,
+                                 struct ieee80211_elems_parse *elems_parse,
                                  struct ieee80211_elems_parse_params *params)
 {
+       struct ieee802_11_elems *elems = &elems_parse->elems;
        const void *data = elem->data + 1;
        bool calc_crc = false;
        u8 len;
@@ -129,15 +149,15 @@ ieee80211_parse_extension_element(u32 *crc,
                        switch (le16_get_bits(mle->control,
                                              IEEE80211_ML_CONTROL_TYPE)) {
                        case IEEE80211_ML_CONTROL_TYPE_BASIC:
-                               if (elems->ml_basic_elem) {
+                               if (elems_parse->ml_basic_elem) {
                                        elems->parse_error |=
                                                IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC;
                                        break;
                                }
-                               elems->ml_basic_elem = (void *)elem;
+                               elems_parse->ml_basic_elem = elem;
                                break;
                        case IEEE80211_ML_CONTROL_TYPE_RECONF:
-                               elems->ml_reconf_elem = (void *)elem;
+                               elems_parse->ml_reconf_elem = elem;
                                break;
                        default:
                                break;
@@ -169,9 +189,10 @@ ieee80211_parse_extension_element(u32 *crc,
 
 static u32
 _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
-                            struct ieee802_11_elems *elems,
+                            struct ieee80211_elems_parse *elems_parse,
                             const struct element *check_inherit)
 {
+       struct ieee802_11_elems *elems = &elems_parse->elems;
        const struct element *elem;
        bool calc_crc = params->filter != 0;
        DECLARE_BITMAP(seen_elems, 256);
@@ -586,7 +607,8 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
                case WLAN_EID_EXTENSION:
                        ieee80211_parse_extension_element(calc_crc ?
                                                                &crc : NULL,
-                                                         elem, elems, params);
+                                                         elem, elems_parse,
+                                                         params);
                        break;
                case WLAN_EID_S1G_CAPABILITIES:
                        if (params->mode != IEEE80211_CONN_MODE_S1G)
@@ -709,9 +731,11 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
        return found ? profile_len : 0;
 }
 
-static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems,
-                                      u8 link_id)
+static void
+ieee80211_mle_get_sta_prof(struct ieee80211_elems_parse *elems_parse,
+                          u8 link_id)
 {
+       struct ieee802_11_elems *elems = &elems_parse->elems;
        const struct ieee80211_multi_link_elem *ml = elems->ml_basic;
        ssize_t ml_len = elems->ml_basic_len;
        const struct element *sub;
@@ -741,26 +765,27 @@ static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems,
                sta_prof_len =
                        cfg80211_defragment_element(sub,
                                                    (u8 *)ml, ml_len,
-                                                   elems->scratch_pos,
-                                                   elems->scratch +
-                                                       elems->scratch_len -
-                                                       elems->scratch_pos,
+                                                   elems_parse->scratch_pos,
+                                                   elems_parse->scratch +
+                                                       elems_parse->scratch_len -
+                                                       elems_parse->scratch_pos,
                                                    IEEE80211_MLE_SUBELEM_FRAGMENT);
 
                if (sta_prof_len < 0)
                        return;
 
-               elems->prof = (void *)elems->scratch_pos;
+               elems->prof = (void *)elems_parse->scratch_pos;
                elems->sta_prof_len = sta_prof_len;
-               elems->scratch_pos += sta_prof_len;
+               elems_parse->scratch_pos += sta_prof_len;
 
                return;
        }
 }
 
-static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems,
+static void ieee80211_mle_parse_link(struct ieee80211_elems_parse *elems_parse,
                                     struct ieee80211_elems_parse_params *params)
 {
+       struct ieee802_11_elems *elems = &elems_parse->elems;
        struct ieee80211_mle_per_sta_profile *prof;
        struct ieee80211_elems_parse_params sub = {
                .mode = params->mode,
@@ -772,26 +797,26 @@ static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems,
        const struct element *non_inherit = NULL;
        const u8 *end;
 
-       ml_len = cfg80211_defragment_element(elems->ml_basic_elem,
+       ml_len = cfg80211_defragment_element(elems_parse->ml_basic_elem,
                                             elems->ie_start,
                                             elems->total_len,
-                                            elems->scratch_pos,
-                                            elems->scratch +
-                                               elems->scratch_len -
-                                               elems->scratch_pos,
+                                            elems_parse->scratch_pos,
+                                            elems_parse->scratch +
+                                               elems_parse->scratch_len -
+                                               elems_parse->scratch_pos,
                                             WLAN_EID_FRAGMENT);
 
        if (ml_len < 0)
                return;
 
-       elems->ml_basic = (const void *)elems->scratch_pos;
+       elems->ml_basic = (const void *)elems_parse->scratch_pos;
        elems->ml_basic_len = ml_len;
-       elems->scratch_pos += ml_len;
+       elems_parse->scratch_pos += ml_len;
 
        if (params->link_id == -1)
                return;
 
-       ieee80211_mle_get_sta_prof(elems, params->link_id);
+       ieee80211_mle_get_sta_prof(elems_parse, params->link_id);
        prof = elems->prof;
 
        if (!prof)
@@ -816,57 +841,66 @@ static void ieee80211_mle_parse_link(struct ieee802_11_elems *elems,
 
        non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
                                             sub.start, sub.len);
-       _ieee802_11_parse_elems_full(&sub, elems, non_inherit);
+       _ieee802_11_parse_elems_full(&sub, elems_parse, non_inherit);
 }
 
 static void
-ieee80211_mle_defrag_reconf(struct ieee802_11_elems *elems)
+ieee80211_mle_defrag_reconf(struct ieee80211_elems_parse *elems_parse)
 {
+       struct ieee802_11_elems *elems = &elems_parse->elems;
        ssize_t ml_len;
 
-       ml_len = cfg80211_defragment_element(elems->ml_reconf_elem,
+       ml_len = cfg80211_defragment_element(elems_parse->ml_reconf_elem,
                                             elems->ie_start,
                                             elems->total_len,
-                                            elems->scratch_pos,
-                                            elems->scratch +
-                                            elems->scratch_len -
-                                            elems->scratch_pos,
+                                            elems_parse->scratch_pos,
+                                            elems_parse->scratch +
+                                               elems_parse->scratch_len -
+                                               elems_parse->scratch_pos,
                                             WLAN_EID_FRAGMENT);
        if (ml_len < 0)
                return;
-       elems->ml_reconf = (void *)elems->scratch_pos;
+       elems->ml_reconf = (void *)elems_parse->scratch_pos;
        elems->ml_reconf_len = ml_len;
-       elems->scratch_pos += ml_len;
+       elems_parse->scratch_pos += ml_len;
 }
 
 struct ieee802_11_elems *
 ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
 {
+       struct ieee80211_elems_parse *elems_parse;
        struct ieee802_11_elems *elems;
        const struct element *non_inherit = NULL;
        u8 *nontransmitted_profile;
        int nontransmitted_profile_len = 0;
        size_t scratch_len = 3 * params->len;
 
-       elems = kzalloc(struct_size(elems, scratch, scratch_len), GFP_ATOMIC);
-       if (!elems)
+       BUILD_BUG_ON(offsetof(typeof(*elems_parse), elems) != 0);
+
+       elems_parse = kzalloc(struct_size(elems_parse, scratch, scratch_len),
+                             GFP_ATOMIC);
+       if (!elems_parse)
                return NULL;
+
+       elems_parse->scratch_len = scratch_len;
+       elems_parse->scratch_pos = elems_parse->scratch;
+
+       elems = &elems_parse->elems;
        elems->ie_start = params->start;
        elems->total_len = params->len;
-       elems->scratch_len = scratch_len;
-       elems->scratch_pos = elems->scratch;
 
-       nontransmitted_profile = elems->scratch_pos;
+       nontransmitted_profile = elems_parse->scratch_pos;
        nontransmitted_profile_len =
                ieee802_11_find_bssid_profile(params->start, params->len,
                                              elems, params->bss,
                                              nontransmitted_profile);
-       elems->scratch_pos += nontransmitted_profile_len;
+       elems_parse->scratch_pos += nontransmitted_profile_len;
        non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
                                             nontransmitted_profile,
                                             nontransmitted_profile_len);
 
-       elems->crc = _ieee802_11_parse_elems_full(params, elems, non_inherit);
+       elems->crc = _ieee802_11_parse_elems_full(params, elems_parse,
+                                                 non_inherit);
 
        /* Override with nontransmitted profile, if found */
        if (nontransmitted_profile_len) {
@@ -878,12 +912,12 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
                        .link_id = params->link_id,
                };
 
-               _ieee802_11_parse_elems_full(&sub, elems, NULL);
+               _ieee802_11_parse_elems_full(&sub, elems_parse, NULL);
        }
 
-       ieee80211_mle_parse_link(elems, params);
+       ieee80211_mle_parse_link(elems_parse, params);
 
-       ieee80211_mle_defrag_reconf(elems);
+       ieee80211_mle_defrag_reconf(elems_parse);
 
        if (elems->tim && !elems->parse_error) {
                const struct ieee80211_tim_ie *tim_ie = elems->tim;
index 30fc0acb7ac29abea683652c35e81bea180b8b9b..a413ba29f7592398b526ee7befae664464bcb266 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * KUnit tests for element parsing
  *
- * Copyright (C) 2023 Intel Corporation
+ * Copyright (C) 2023-2024 Intel Corporation
  */
 #include <kunit/test.h>
 #include "../ieee80211_i.h"
@@ -69,7 +69,7 @@ static void mle_defrag(struct kunit *test)
        if (IS_ERR_OR_NULL(parsed))
                goto free_skb;
 
-       KUNIT_EXPECT_NOT_NULL(test, parsed->ml_basic_elem);
+       KUNIT_EXPECT_NOT_NULL(test, parsed->ml_basic);
        KUNIT_EXPECT_EQ(test,
                        parsed->ml_basic_len,
                        2 /* control */ +