From 2b9713d61611c946e3e41a135e7aafb146f8a61f Mon Sep 17 00:00:00 2001 From: Ananya Barat Date: Tue, 10 Mar 2020 12:07:33 +0530 Subject: [PATCH] Fill the current opclass in (Re)AssocRequest depending on HT/VHT IEs 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 --- wpa_supplicant/op_classes.c | 29 ++++++++++++++++++++++++----- wpa_supplicant/rrm.c | 4 ++-- wpa_supplicant/sme.c | 2 +- wpa_supplicant/wpa_supplicant.c | 2 +- wpa_supplicant/wpa_supplicant_i.h | 4 +++- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index f49bdb094..983801faa 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -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, ¤t, &chan) < 0 && + ieee80211_freq_to_channel_ext(bss->freq, 0, CHANWIDTH_USE_HT, ¤t, &chan) == NUM_HOSTAPD_MODES) return 0; diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index 66855b877..afc117275 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -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; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index aa59f151a..d4c12d1e3 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -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); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index ba8ae65ae..584ca3b91 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index eac7cad2d..383bf8e69 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -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,