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,