wifi: mac80211: hide element parsing internals

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>
This commit is contained in:
Johannes Berg 2024-02-28 09:48:16 +01:00
parent b413c0bd9c
commit 5a21f0eae1
3 changed files with 78 additions and 58 deletions

View File

@ -1766,12 +1766,6 @@ struct ieee802_11_elems {
size_t ml_basic_len; size_t ml_basic_len;
size_t ml_reconf_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; u8 ttlm_num;
/* /*
@ -1784,14 +1778,6 @@ struct ieee802_11_elems {
/* whether/which parse error occurred while retrieving these elements */ /* whether/which parse error occurred while retrieving these elements */
u8 parse_error; 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( static inline struct ieee80211_local *hw_to_local(

View File

@ -34,12 +34,32 @@
#include "led.h" #include "led.h"
#include "wep.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 static void
ieee80211_parse_extension_element(u32 *crc, ieee80211_parse_extension_element(u32 *crc,
const struct element *elem, const struct element *elem,
struct ieee802_11_elems *elems, struct ieee80211_elems_parse *elems_parse,
struct ieee80211_elems_parse_params *params) struct ieee80211_elems_parse_params *params)
{ {
struct ieee802_11_elems *elems = &elems_parse->elems;
const void *data = elem->data + 1; const void *data = elem->data + 1;
bool calc_crc = false; bool calc_crc = false;
u8 len; u8 len;
@ -129,15 +149,15 @@ ieee80211_parse_extension_element(u32 *crc,
switch (le16_get_bits(mle->control, switch (le16_get_bits(mle->control,
IEEE80211_ML_CONTROL_TYPE)) { IEEE80211_ML_CONTROL_TYPE)) {
case IEEE80211_ML_CONTROL_TYPE_BASIC: case IEEE80211_ML_CONTROL_TYPE_BASIC:
if (elems->ml_basic_elem) { if (elems_parse->ml_basic_elem) {
elems->parse_error |= elems->parse_error |=
IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC; IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC;
break; break;
} }
elems->ml_basic_elem = (void *)elem; elems_parse->ml_basic_elem = elem;
break; break;
case IEEE80211_ML_CONTROL_TYPE_RECONF: case IEEE80211_ML_CONTROL_TYPE_RECONF:
elems->ml_reconf_elem = (void *)elem; elems_parse->ml_reconf_elem = elem;
break; break;
default: default:
break; break;
@ -169,9 +189,10 @@ ieee80211_parse_extension_element(u32 *crc,
static u32 static u32
_ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params, _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) const struct element *check_inherit)
{ {
struct ieee802_11_elems *elems = &elems_parse->elems;
const struct element *elem; const struct element *elem;
bool calc_crc = params->filter != 0; bool calc_crc = params->filter != 0;
DECLARE_BITMAP(seen_elems, 256); DECLARE_BITMAP(seen_elems, 256);
@ -586,7 +607,8 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
case WLAN_EID_EXTENSION: case WLAN_EID_EXTENSION:
ieee80211_parse_extension_element(calc_crc ? ieee80211_parse_extension_element(calc_crc ?
&crc : NULL, &crc : NULL,
elem, elems, params); elem, elems_parse,
params);
break; break;
case WLAN_EID_S1G_CAPABILITIES: case WLAN_EID_S1G_CAPABILITIES:
if (params->mode != IEEE80211_CONN_MODE_S1G) 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; return found ? profile_len : 0;
} }
static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems, static void
u8 link_id) 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; const struct ieee80211_multi_link_elem *ml = elems->ml_basic;
ssize_t ml_len = elems->ml_basic_len; ssize_t ml_len = elems->ml_basic_len;
const struct element *sub; const struct element *sub;
@ -741,26 +765,27 @@ static void ieee80211_mle_get_sta_prof(struct ieee802_11_elems *elems,
sta_prof_len = sta_prof_len =
cfg80211_defragment_element(sub, cfg80211_defragment_element(sub,
(u8 *)ml, ml_len, (u8 *)ml, ml_len,
elems->scratch_pos, elems_parse->scratch_pos,
elems->scratch + elems_parse->scratch +
elems->scratch_len - elems_parse->scratch_len -
elems->scratch_pos, elems_parse->scratch_pos,
IEEE80211_MLE_SUBELEM_FRAGMENT); IEEE80211_MLE_SUBELEM_FRAGMENT);
if (sta_prof_len < 0) if (sta_prof_len < 0)
return; return;
elems->prof = (void *)elems->scratch_pos; elems->prof = (void *)elems_parse->scratch_pos;
elems->sta_prof_len = sta_prof_len; elems->sta_prof_len = sta_prof_len;
elems->scratch_pos += sta_prof_len; elems_parse->scratch_pos += sta_prof_len;
return; 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 ieee80211_elems_parse_params *params)
{ {
struct ieee802_11_elems *elems = &elems_parse->elems;
struct ieee80211_mle_per_sta_profile *prof; struct ieee80211_mle_per_sta_profile *prof;
struct ieee80211_elems_parse_params sub = { struct ieee80211_elems_parse_params sub = {
.mode = params->mode, .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 struct element *non_inherit = NULL;
const u8 *end; 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->ie_start,
elems->total_len, elems->total_len,
elems->scratch_pos, elems_parse->scratch_pos,
elems->scratch + elems_parse->scratch +
elems->scratch_len - elems_parse->scratch_len -
elems->scratch_pos, elems_parse->scratch_pos,
WLAN_EID_FRAGMENT); WLAN_EID_FRAGMENT);
if (ml_len < 0) if (ml_len < 0)
return; 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->ml_basic_len = ml_len;
elems->scratch_pos += ml_len; elems_parse->scratch_pos += ml_len;
if (params->link_id == -1) if (params->link_id == -1)
return; return;
ieee80211_mle_get_sta_prof(elems, params->link_id); ieee80211_mle_get_sta_prof(elems_parse, params->link_id);
prof = elems->prof; prof = elems->prof;
if (!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, non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
sub.start, sub.len); 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 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; 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->ie_start,
elems->total_len, elems->total_len,
elems->scratch_pos, elems_parse->scratch_pos,
elems->scratch + elems_parse->scratch +
elems->scratch_len - elems_parse->scratch_len -
elems->scratch_pos, elems_parse->scratch_pos,
WLAN_EID_FRAGMENT); WLAN_EID_FRAGMENT);
if (ml_len < 0) if (ml_len < 0)
return; return;
elems->ml_reconf = (void *)elems->scratch_pos; elems->ml_reconf = (void *)elems_parse->scratch_pos;
elems->ml_reconf_len = ml_len; elems->ml_reconf_len = ml_len;
elems->scratch_pos += ml_len; elems_parse->scratch_pos += ml_len;
} }
struct ieee802_11_elems * struct ieee802_11_elems *
ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params) ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
{ {
struct ieee80211_elems_parse *elems_parse;
struct ieee802_11_elems *elems; struct ieee802_11_elems *elems;
const struct element *non_inherit = NULL; const struct element *non_inherit = NULL;
u8 *nontransmitted_profile; u8 *nontransmitted_profile;
int nontransmitted_profile_len = 0; int nontransmitted_profile_len = 0;
size_t scratch_len = 3 * params->len; size_t scratch_len = 3 * params->len;
elems = kzalloc(struct_size(elems, scratch, scratch_len), GFP_ATOMIC); BUILD_BUG_ON(offsetof(typeof(*elems_parse), elems) != 0);
if (!elems)
elems_parse = kzalloc(struct_size(elems_parse, scratch, scratch_len),
GFP_ATOMIC);
if (!elems_parse)
return NULL; 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->ie_start = params->start;
elems->total_len = params->len; 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 = nontransmitted_profile_len =
ieee802_11_find_bssid_profile(params->start, params->len, ieee802_11_find_bssid_profile(params->start, params->len,
elems, params->bss, elems, params->bss,
nontransmitted_profile); 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, non_inherit = cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
nontransmitted_profile, nontransmitted_profile,
nontransmitted_profile_len); 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 */ /* Override with nontransmitted profile, if found */
if (nontransmitted_profile_len) { if (nontransmitted_profile_len) {
@ -878,12 +912,12 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
.link_id = params->link_id, .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) { if (elems->tim && !elems->parse_error) {
const struct ieee80211_tim_ie *tim_ie = elems->tim; const struct ieee80211_tim_ie *tim_ie = elems->tim;

View File

@ -2,7 +2,7 @@
/* /*
* KUnit tests for element parsing * KUnit tests for element parsing
* *
* Copyright (C) 2023 Intel Corporation * Copyright (C) 2023-2024 Intel Corporation
*/ */
#include <kunit/test.h> #include <kunit/test.h>
#include "../ieee80211_i.h" #include "../ieee80211_i.h"
@ -69,7 +69,7 @@ static void mle_defrag(struct kunit *test)
if (IS_ERR_OR_NULL(parsed)) if (IS_ERR_OR_NULL(parsed))
goto free_skb; goto free_skb;
KUNIT_EXPECT_NOT_NULL(test, parsed->ml_basic_elem); KUNIT_EXPECT_NOT_NULL(test, parsed->ml_basic);
KUNIT_EXPECT_EQ(test, KUNIT_EXPECT_EQ(test,
parsed->ml_basic_len, parsed->ml_basic_len,
2 /* control */ + 2 /* control */ +