Commit e4d005b8 authored by Johannes Berg's avatar Johannes Berg

mac80211: refactor extended element parsing

This code was really ugly, refactor it a bit to make it more
readable.

While at it, use sizeof() and fix the UORA element length
check bug.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131111300.891737-4-luca@coelho.fiSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 75e296e9
...@@ -890,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, ...@@ -890,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
} }
EXPORT_SYMBOL(ieee80211_queue_delayed_work); EXPORT_SYMBOL(ieee80211_queue_delayed_work);
static void ieee80211_parse_extension_element(u32 *crc,
const struct element *elem,
struct ieee802_11_elems *elems)
{
const void *data = elem->data + 1;
u8 len = elem->datalen - 1;
switch (elem->data[0]) {
case WLAN_EID_EXT_HE_MU_EDCA:
if (len == sizeof(*elems->mu_edca_param_set)) {
elems->mu_edca_param_set = data;
if (crc)
*crc = crc32_be(*crc, (void *)elem,
elem->datalen + 2);
}
break;
case WLAN_EID_EXT_HE_CAPABILITY:
elems->he_cap = data;
elems->he_cap_len = len;
break;
case WLAN_EID_EXT_HE_OPERATION:
if (len >= sizeof(*elems->he_operation) &&
len == ieee80211_he_oper_size(data) - 1)
elems->he_operation = data;
break;
case WLAN_EID_EXT_UORA:
if (len == 1)
elems->uora_element = data;
break;
case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME:
if (len == 3)
elems->max_channel_switch_time = data;
break;
case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION:
if (len == sizeof(*elems->mbssid_config_ie))
elems->mbssid_config_ie = data;
break;
case WLAN_EID_EXT_HE_SPR:
if (len >= sizeof(*elems->he_spr) &&
len >= ieee80211_he_spr_size(data))
elems->he_spr = data;
break;
}
}
static u32 static u32
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems, struct ieee802_11_elems *elems,
...@@ -1220,33 +1265,9 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ...@@ -1220,33 +1265,9 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
elems->max_idle_period_ie = (void *)pos; elems->max_idle_period_ie = (void *)pos;
break; break;
case WLAN_EID_EXTENSION: case WLAN_EID_EXTENSION:
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA && ieee80211_parse_extension_element(calc_crc ?
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) { &crc : NULL,
elems->mu_edca_param_set = (void *)&pos[1]; elem, elems);
if (calc_crc)
crc = crc32_be(crc, pos - 2, elen + 2);
} else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) {
elems->he_cap = (void *)&pos[1];
elems->he_cap_len = elen - 1;
} else if (pos[0] == WLAN_EID_EXT_HE_OPERATION &&
elen >= sizeof(*elems->he_operation) &&
elen >= ieee80211_he_oper_size(&pos[1])) {
elems->he_operation = (void *)&pos[1];
} else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
elems->uora_element = (void *)&pos[1];
} else if (pos[0] ==
WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME &&
elen == 4) {
elems->max_channel_switch_time = pos + 1;
} else if (pos[0] ==
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
elen == 3) {
elems->mbssid_config_ie = (void *)&pos[1];
} else if (pos[0] == WLAN_EID_EXT_HE_SPR &&
elen >= sizeof(*elems->he_spr) &&
elen >= ieee80211_he_spr_size(&pos[1])) {
elems->he_spr = (void *)&pos[1];
}
break; break;
default: default:
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment