]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Fill the current opclass in (Re)AssocRequest depending on HT/VHT IEs
authorAnanya Barat <abarat@codeaurora.org>
Tue, 10 Mar 2020 06:37:33 +0000 (12:07 +0530)
committerJouni Malinen <j@w1.fi>
Wed, 11 Mar 2020 16:30:31 +0000 (18:30 +0200)
The previous implementation was assuming a fixed 20 MHz channel
bandwidth when determining which operating class value to indicate as
the Current Operating Class in the Supported Operating Classes element.
This is not accurate for many HT/VHT cases.

Fix this by determining the current operating class (i.e., the operating
class used for the requested association) based on the HT/VHT operation
elements from scan results.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
wpa_supplicant/op_classes.c
wpa_supplicant/rrm.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index f49bdb0945dfaf32f6399803998bd45fd5159d61..983801faa4218e0d47d656e952876bd5ef8e1995 100644 (file)
@@ -14,6 +14,7 @@
 #include "utils/common.h"
 #include "common/ieee802_11_common.h"
 #include "wpa_supplicant_i.h"
+#include "bss.h"
 
 
 static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode,
@@ -356,9 +357,25 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
 }
 
 
+static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current,
+                                            u8 *channel)
+{
+
+       u8 *ies, phy_type;
+       size_t ies_len;
+
+       if (!bss)
+               return -1;
+       ies = (u8 *) (bss + 1);
+       ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len;
+       return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current,
+                                   channel, &phy_type);
+}
+
+
 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
                             struct wpa_ssid *ssid,
-                            int freq, u8 *pos, size_t len)
+                            struct wpa_bss *bss, u8 *pos, size_t len)
 {
        struct wpabuf *buf;
        u8 op, current, chan;
@@ -366,11 +383,13 @@ size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
        size_t res;
 
        /*
-        * Assume 20 MHz channel for now.
-        * TODO: Use the secondary channel and VHT channel width that will be
-        * used after association.
+        * Determine the current operating class correct mode based on
+        * advertised BSS capabilities, if available. Fall back to a less
+        * accurate guess based on frequency if the needed IEs are not available
+        * or used.
         */
-       if (ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT,
+       if (wpas_sta_secondary_channel_offset(bss, &current, &chan) < 0 &&
+           ieee80211_freq_to_channel_ext(bss->freq, 0, CHANWIDTH_USE_HT,
                                          &current, &chan) == NUM_HOSTAPD_MODES)
                return 0;
 
index 66855b8773624ce8c44ae270ddd3c2444490e0bc..afc11727572400995f6195faa7d41b7631fb3013 100644 (file)
@@ -695,8 +695,8 @@ static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s,
 }
 
 
-static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
-                               u8 *op_class, u8 *chan, u8 *phy_type)
+int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+                        u8 *op_class, u8 *chan, u8 *phy_type)
 {
        const u8 *ie;
        int sec_chan = 0, vht = 0;
index aa59f151af49de3010a167b86f500a5e696ef55d..d4c12d1e32e041ac8283aac7c8a63db3d0543f74 100644 (file)
@@ -578,7 +578,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
        sme_auth_handle_rrm(wpa_s, bss);
 
        wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
-               wpa_s, ssid, bss->freq,
+               wpa_s, ssid, bss,
                wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
                sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
 
index ba8ae65ae0cea75592a7b9c6bbea8164312c2b75..584ca3b912a6d5f85ecc93452244b8c70c85eebc 100644 (file)
@@ -2890,7 +2890,7 @@ static u8 * wpas_populate_assoc_ies(
 #endif /* CONFIG_P2P */
 
        if (bss) {
-               wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq,
+               wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss,
                                                    wpa_ie + wpa_ie_len,
                                                    max_wpa_ie_len -
                                                    wpa_ie_len);
index eac7cad2dcac74b61a75d358ec33d6a74dc2f10b..383bf8e69ae1c95fe34bdad23401d5cb8843ed65 100644 (file)
@@ -1394,6 +1394,8 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style);
 int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s);
 void add_freq(int *freqs, int *num_freqs, int freq);
 
+int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len,
+                        u8 *op_class, u8 *chan, u8 *phy_type);
 void wpas_rrm_reset(struct wpa_supplicant *wpa_s);
 void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s,
                                   const u8 *report, size_t report_len);
@@ -1453,7 +1455,7 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class,
                                 u8 channel, u8 bw);
 size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s,
                             struct wpa_ssid *ssid,
-                            int freq, u8 *pos, size_t len);
+                            struct wpa_bss *bss, u8 *pos, size_t len);
 int * wpas_supp_op_classes(struct wpa_supplicant *wpa_s);
 
 int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s,