OSDN Git Service

mac80211: use ieee802_11_parse_elems() in ieee80211_prep_channel()
authorWen Gong <wgong@codeaurora.org>
Fri, 24 Sep 2021 10:00:51 +0000 (06:00 -0400)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 24 Sep 2021 10:57:24 +0000 (12:57 +0200)
In function ieee80211_prep_channel(), it has some ieee80211_bss_get_ie()
and cfg80211_find_ext_ie() to get the IE, this is to use another
function ieee802_11_parse_elems() to get all the IEs in one time.

Signed-off-by: Wen Gong <wgong@codeaurora.org>
Link: https://lore.kernel.org/r/20210924100052.32029-6-wgong@codeaurora.org
[remove now unnecessary size validation, use -ENOMEM, free elems earlier
 for less error handling code]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c

index e80f338..2938820 100644 (file)
@@ -4998,10 +4998,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
        bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
        struct ieee80211_bss *bss = (void *)cbss->priv;
+       struct ieee802_11_elems *elems;
+       const struct cfg80211_bss_ies *ies;
        int ret;
        u32 i;
        bool have_80mhz;
 
+       rcu_read_lock();
+
+       ies = rcu_dereference(cbss->ies);
+       elems = ieee802_11_parse_elems(ies->data, ies->len, false,
+                                      NULL, NULL);
+       if (!elems) {
+               rcu_read_unlock();
+               return -ENOMEM;
+       }
+
        sband = local->hw.wiphy->bands[cbss->channel->band];
 
        ifmgd->flags &= ~(IEEE80211_STA_DISABLE_40MHZ |
@@ -5024,18 +5036,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                                         ieee80211_vif_type_p2p(&sdata->vif)))
                ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
 
-       rcu_read_lock();
-
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && !is_6ghz) {
-               const u8 *ht_oper_ie, *ht_cap_ie;
-
-               ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
-               if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
-                       ht_oper = (void *)(ht_oper_ie + 2);
-
-               ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
-               if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap))
-                       ht_cap = (void *)(ht_cap_ie + 2);
+               ht_oper = elems->ht_operation;
+               ht_cap = elems->ht_cap_elem;
 
                if (!ht_cap) {
                        ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
@@ -5044,12 +5047,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        }
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && !is_6ghz) {
-               const u8 *vht_oper_ie, *vht_cap;
-
-               vht_oper_ie = ieee80211_bss_get_ie(cbss,
-                                                  WLAN_EID_VHT_OPERATION);
-               if (vht_oper_ie && vht_oper_ie[1] >= sizeof(*vht_oper))
-                       vht_oper = (void *)(vht_oper_ie + 2);
+               vht_oper = elems->vht_operation;
                if (vht_oper && !ht_oper) {
                        vht_oper = NULL;
                        sdata_info(sdata,
@@ -5059,25 +5057,14 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                        ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
                }
 
-               vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY);
-               if (!vht_cap || vht_cap[1] < sizeof(struct ieee80211_vht_cap)) {
+               if (!elems->vht_cap_elem) {
                        ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
                        vht_oper = NULL;
                }
        }
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) {
-               const struct cfg80211_bss_ies *ies;
-               const u8 *he_oper_ie;
-
-               ies = rcu_dereference(cbss->ies);
-               he_oper_ie = cfg80211_find_ext_ie(WLAN_EID_EXT_HE_OPERATION,
-                                                 ies->data, ies->len);
-               if (he_oper_ie &&
-                   he_oper_ie[1] >= ieee80211_he_oper_size(&he_oper_ie[3]))
-                       he_oper = (void *)(he_oper_ie + 3);
-               else
-                       he_oper = NULL;
+               he_oper = elems->he_operation;
 
                if (!ieee80211_verify_sta_he_mcs_support(sdata, sband, he_oper))
                        ifmgd->flags |= IEEE80211_STA_DISABLE_HE;
@@ -5098,13 +5085,8 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
 
        if (sband->band == NL80211_BAND_S1GHZ) {
-               const u8 *s1g_oper_ie;
-
-               s1g_oper_ie = ieee80211_bss_get_ie(cbss,
-                                                  WLAN_EID_S1G_OPERATION);
-               if (s1g_oper_ie && s1g_oper_ie[1] >= sizeof(*s1g_oper))
-                       s1g_oper = (void *)(s1g_oper_ie + 2);
-               else
+               s1g_oper = elems->s1g_oper;
+               if (!s1g_oper)
                        sdata_info(sdata,
                                   "AP missing S1G operation element?\n");
        }
@@ -5120,6 +5102,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                                      local->rx_chains);
 
        rcu_read_unlock();
+       /* the element data was RCU protected so no longer valid anyway */
+       kfree(elems);
+       elems = NULL;
 
        if (ifmgd->flags & IEEE80211_STA_DISABLE_HE && is_6ghz) {
                sdata_info(sdata, "Rejecting non-HE 6/7 GHz connection");