mac80211: refactor extended element parsing
authorJohannes Berg <johannes.berg@intel.com>
Fri, 31 Jan 2020 11:12:40 +0000 (13:12 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 7 Feb 2020 11:38:21 +0000 (12:38 +0100)
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: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/20200131111300.891737-4-luca@coelho.fi
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/util.c

index 780df3e..72039c8 100644 (file)
@@ -890,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 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
 _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                            struct ieee802_11_elems *elems,
@@ -1220,33 +1265,9 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                                elems->max_idle_period_ie = (void *)pos;
                        break;
                case WLAN_EID_EXTENSION:
-                       if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
-                           elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
-                               elems->mu_edca_param_set = (void *)&pos[1];
-                               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];
-                       }
+                       ieee80211_parse_extension_element(calc_crc ?
+                                                               &crc : NULL,
+                                                         elem, elems);
                        break;
                default:
                        break;