X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fsme.c;h=3a8f5b1aa62c9a75b7d72b73c37a18f68e85b707;hb=9c21b2bf45e35ba169d9123941c46cf3b2896d9c;hp=e4f2d123e192a58d3e3524daa5ef4f71bec98e8d;hpb=cb5ef952c843de4429b11e180f9e88b568460153;p=mech_eap.git diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index e4f2d12..3a8f5b1 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -67,7 +67,7 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s) for (;;) { int group = groups[wpa_s->sme.sae_group_index]; - if (group < 0) + if (group <= 0) break; if (sae_set_group(&wpa_s->sme.sae, group) == 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d", @@ -137,6 +137,64 @@ static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s) #endif /* CONFIG_SAE */ +/** + * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt + * @wpa_s: Pointer to wpa_supplicant data + * @bss: Pointer to the bss which is the target of authentication attempt + */ +static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ + const u8 rrm_ie_len = 5; + u8 *pos; + const u8 *rrm_ie; + + wpa_s->rrm.rrm_used = 0; + + wpa_printf(MSG_DEBUG, + "RRM: Determining whether RRM can be used - device support: 0x%x", + wpa_s->drv_rrm_flags); + + rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES); + if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) { + wpa_printf(MSG_DEBUG, "RRM: No RRM in network"); + return; + } + + if (!((wpa_s->drv_rrm_flags & + WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) && + (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) && + !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) { + wpa_printf(MSG_DEBUG, + "RRM: Insufficient RRM support in driver - do not use RRM"); + return; + } + + if (sizeof(wpa_s->sme.assoc_req_ie) < + wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) { + wpa_printf(MSG_INFO, + "RRM: Unable to use RRM, no room for RRM IE"); + return; + } + + wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request"); + pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; + os_memset(pos, 0, 2 + rrm_ie_len); + *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; + *pos++ = rrm_ie_len; + + /* Set supported capabilites flags */ + if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) + *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT; + + if (wpa_s->lci) + pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT; + + wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2; + wpa_s->rrm.rrm_used = 1; +} + + static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) @@ -153,6 +211,10 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpabuf *resp = NULL; u8 ext_capab[18]; int ext_capab_len; + int skip_auth; +#ifdef CONFIG_MBO + const u8 *mbo; +#endif /* CONFIG_MBO */ if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " @@ -161,6 +223,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, return; } + skip_auth = wpa_s->conf->reassoc_same_bss_optim && + wpa_s->reassoc_same_bss; wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); @@ -199,17 +263,22 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, "0x%x", params.auth_alg); } #ifdef CONFIG_SAE + wpa_s->sme.sae_pmksa_caching = 0; if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); - if (rsn && - wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { - if (wpa_key_mgmt_sae(ied.key_mgmt)) { - wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); - params.auth_alg = WPA_AUTH_ALG_SAE; - } + if (!rsn) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SAE enabled, but target BSS does not advertise RSN"); + } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 && + wpa_key_mgmt_sae(ied.key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); + params.auth_alg = WPA_AUTH_ALG_SAE; + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "SAE enabled, but target BSS does not advertise SAE AKM for RSN"); } } #endif /* CONFIG_SAE */ @@ -238,7 +307,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); + eapol_sm_notify_pmkid_attempt(wpa_s->eapol); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, @@ -325,8 +394,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W - wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w; + wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid); if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; @@ -355,9 +423,60 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_FST + if (wpa_s->fst_ies) { + int fst_ies_len = wpabuf_len(wpa_s->fst_ies); + + if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <= + sizeof(wpa_s->sme.assoc_req_ie)) { + os_memcpy(wpa_s->sme.assoc_req_ie + + wpa_s->sme.assoc_req_ie_len, + wpabuf_head(wpa_s->fst_ies), + fst_ies_len); + wpa_s->sme.assoc_req_ie_len += fst_ies_len; + } + } +#endif /* CONFIG_FST */ + + sme_auth_handle_rrm(wpa_s, bss); + +#ifdef CONFIG_MBO + mbo = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE); + if (mbo) { + int len; + + len = wpas_mbo_supp_op_class_ie( + wpa_s, bss->freq, + 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); + if (len > 0) + wpa_s->sme.assoc_req_ie_len += len; + } +#endif /* CONFIG_MBO */ + + if (params.p2p) + wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT); + else + wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION); + + ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, + sizeof(ext_capab)); + if (ext_capab_len > 0) { + u8 *pos = wpa_s->sme.assoc_req_ie; + if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) + pos += 2 + pos[1]; + os_memmove(pos + ext_capab_len, pos, + wpa_s->sme.assoc_req_ie_len - + (pos - wpa_s->sme.assoc_req_ie)); + wpa_s->sme.assoc_req_ie_len += ext_capab_len; + os_memcpy(pos, ext_capab, ext_capab_len); + } + #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; + hs20 = wpabuf_alloc(20); if (hs20) { int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); @@ -377,28 +496,51 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_HS20 */ - ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, - sizeof(ext_capab)); - if (ext_capab_len > 0) { - u8 *pos = wpa_s->sme.assoc_req_ie; - if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) - pos += 2 + pos[1]; - os_memmove(pos + ext_capab_len, pos, - wpa_s->sme.assoc_req_ie_len - - (pos - wpa_s->sme.assoc_req_ie)); - wpa_s->sme.assoc_req_ie_len += ext_capab_len; - os_memcpy(pos, ext_capab, ext_capab_len); + if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) { + struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]; + size_t len; + + len = sizeof(wpa_s->sme.assoc_req_ie) - + wpa_s->sme.assoc_req_ie_len; + if (wpabuf_len(buf) <= len) { + os_memcpy(wpa_s->sme.assoc_req_ie + + wpa_s->sme.assoc_req_ie_len, + wpabuf_head(buf), wpabuf_len(buf)); + wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf); + } } +#ifdef CONFIG_MBO + if (mbo) { + int len; + + len = wpas_mbo_ie(wpa_s, 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); + if (len >= 0) + wpa_s->sme.assoc_req_ie_len += len; + } +#endif /* CONFIG_MBO */ + #ifdef CONFIG_SAE - if (params.auth_alg == WPA_AUTH_ALG_SAE) { + if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE && + pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0) + { + wpa_dbg(wpa_s, MSG_DEBUG, + "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication"); + params.auth_alg = WPA_AUTH_ALG_OPEN; + wpa_s->sme.sae_pmksa_caching = 1; + } + + if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) { - wpas_connect_work_done(wpa_s); + wpas_connection_failed(wpa_s, bss->bssid); return; } params.sae_data = wpabuf_head(resp); @@ -423,6 +565,10 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); +#ifdef CONFIG_HS20 + hs20_configure_frame_filters(wpa_s); +#endif /* CONFIG_HS20 */ + #ifdef CONFIG_P2P /* * If multi-channel concurrency is not supported, check for any @@ -449,6 +595,15 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_P2P */ + if (skip_auth) { + wpa_msg(wpa_s, MSG_DEBUG, + "SME: Skip authentication step on reassoc-to-same-BSS"); + wpabuf_free(resp); + sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN); + return; + } + + wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " @@ -487,7 +642,9 @@ static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit) wpa_s->connect_work = work; - if (!wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) { + if (cwork->bss_removed || + !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) || + wpas_network_disabled(wpa_s, cwork->ssid)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt"); wpas_connect_work_done(wpa_s); return; @@ -520,6 +677,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, radio_remove_works(wpa_s, "sme-connect", 0); } + wpas_abort_ongoing_scan(wpa_s); + cwork = os_zalloc(sizeof(*cwork)); if (cwork == NULL) return; @@ -544,6 +703,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s, static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, u16 status_code, const u8 *data, size_t len) { + int *groups; + wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u " "status code %u", auth_transaction, status_code); @@ -551,10 +712,32 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && wpa_s->sme.sae.state == SAE_COMMITTED && wpa_s->current_bss && wpa_s->current_ssid) { - wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE anti-clogging token " - "requested"); + int default_groups[] = { 19, 20, 21, 25, 26, 0 }; + u16 group; + + groups = wpa_s->conf->sae_groups; + if (!groups || groups[0] <= 0) + groups = default_groups; + + if (len < sizeof(le16)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: Too short SAE anti-clogging token request"); + return -1; + } + group = WPA_GET_LE16(data); + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: SAE anti-clogging token requested (group %u)", + group); + if (sae_group_allowed(&wpa_s->sme.sae, groups, group) != + WLAN_STATUS_SUCCESS) { + wpa_dbg(wpa_s, MSG_ERROR, + "SME: SAE group %u of anti-clogging request is invalid", + group); + return -1; + } wpabuf_free(wpa_s->sme.sae_token); - wpa_s->sme.sae_token = wpabuf_alloc_copy(data, len); + wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16), + len - sizeof(le16)); sme_send_authentication(wpa_s, wpa_s->current_bss, wpa_s->current_ssid, 1); return 0; @@ -578,7 +761,9 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, return -1; if (auth_transaction == 1) { - int *groups = wpa_s->conf->sae_groups; + u16 res; + + groups = wpa_s->conf->sae_groups; wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit"); if (wpa_s->current_bss == NULL || @@ -588,8 +773,14 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, return -1; if (groups && groups[0] <= 0) groups = NULL; - if (sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL, - groups) != WLAN_STATUS_SUCCESS) + res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL, + groups); + if (res == SAE_SILENTLY_DISCARD) { + wpa_printf(MSG_DEBUG, + "SAE: Drop commit message due to reflection attack"); + return 0; + } + if (res != WLAN_STATUS_SUCCESS) return -1; if (sae_process_commit(&wpa_s->sme.sae) < 0) { @@ -667,13 +858,28 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for " "4-way handshake"); - wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN, + wpa_s->sme.sae.pmkid, wpa_s->pending_bssid); } #endif /* CONFIG_SAE */ if (data->auth.status_code != WLAN_STATUS_SUCCESS) { - wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " - "code %d)", data->auth.status_code); + char *ie_txt = NULL; + + if (data->auth.ies && data->auth.ies_len) { + size_t buflen = 2 * data->auth.ies_len + 1; + ie_txt = os_malloc(buflen); + if (ie_txt) { + wpa_snprintf_hex(ie_txt, buflen, data->auth.ies, + data->auth.ies_len); + } + } + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR + " auth_type=%u auth_transaction=%u status_code=%u ie=%s", + MAC2STR(data->auth.peer), data->auth.auth_type, + data->auth.auth_transaction, data->auth.status_code, + ie_txt); + os_free(ie_txt); if (data->auth.status_code != WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || @@ -710,12 +916,20 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) #ifdef CONFIG_IEEE80211R if (data->auth.auth_type == WLAN_AUTH_FT) { - union wpa_event_data edata; - os_memset(&edata, 0, sizeof(edata)); - edata.ft_ies.ies = data->auth.ies; - edata.ft_ies.ies_len = data->auth.ies_len; - os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); - wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); + if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies, + data->auth.ies_len, 0, + data->auth.peer, NULL, 0) < 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: FT Authentication response processing failed"); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" + MACSTR + " reason=%d locally_generated=1", + MAC2STR(wpa_s->pending_bssid), + WLAN_REASON_DEAUTH_LEAVING); + wpas_connection_failed(wpa_s, wpa_s->pending_bssid); + wpa_supplicant_mark_disassoc(wpa_s); + return; + } } #endif /* CONFIG_IEEE80211R */ @@ -742,7 +956,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; - params.freq = wpa_s->sme.freq; + params.freq.freq = wpa_s->sme.freq; params.bg_scan_period = wpa_s->current_ssid ? wpa_s->current_ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? @@ -774,13 +988,14 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; + params.rrm_used = wpa_s->rrm.rrm_used; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", - params.freq); + params.freq.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); @@ -807,8 +1022,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; - if (wpa_s->parent->set_sta_uapsd) - params.uapsd = wpa_s->parent->sta_uapsd; + if (wpa_s->p2pdev->set_sta_uapsd) + params.uapsd = wpa_s->p2pdev->sta_uapsd; else params.uapsd = -1; @@ -881,6 +1096,27 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); +#ifdef CONFIG_SAE + if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid && + wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication"); + wpa_sm_aborted_cached(wpa_s->wpa); + wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid); + if (wpa_s->current_bss) { + struct wpa_bss *bss = wpa_s->current_bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + + wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, + WLAN_REASON_DEAUTH_LEAVING); + wpas_connect_work_done(wpa_s); + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_connect(wpa_s, bss, ssid); + return; + } + } +#endif /* CONFIG_SAE */ + /* * For now, unconditionally terminate the previous authentication. In * theory, this should not be needed, but mac80211 gets quite confused @@ -981,6 +1217,21 @@ void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, } +void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s) +{ + wpa_s->sme.prev_bssid_set = 0; +#ifdef CONFIG_SAE + wpabuf_free(wpa_s->sme.sae_token); + wpa_s->sme.sae_token = NULL; + sae_clear_data(&wpa_s->sme.sae); +#endif /* CONFIG_SAE */ +#ifdef CONFIG_IEEE80211R + if (wpa_s->sme.ft_ies) + sme_update_ft_ies(wpa_s, NULL, NULL, 0); +#endif /* CONFIG_IEEE80211R */ +} + + void sme_deinit(struct wpa_supplicant *wpa_s) { os_free(wpa_s->sme.ft_ies); @@ -989,11 +1240,7 @@ void sme_deinit(struct wpa_supplicant *wpa_s) #ifdef CONFIG_IEEE80211W sme_stop_sa_query(wpa_s); #endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_SAE - wpabuf_free(wpa_s->sme.sae_token); - wpa_s->sme.sae_token = NULL; - sae_clear_data(&wpa_s->sme.sae); -#endif /* CONFIG_SAE */ + sme_clear_on_disassoc(wpa_s); eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); @@ -1120,43 +1367,72 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) } -static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, - u16 num_modes, - enum hostapd_hw_mode mode) -{ - u16 i; - - for (i = 0; i < num_modes; i++) { - if (modes[i].mode == mode) - return &modes[i]; - } - - return NULL; -} - - -static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, - enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params) +static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) { - /* Include only supported channels for the specified band */ + /* Include only affected channels */ struct hostapd_hw_modes *mode; int count, i; + int start, end; - mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band); + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211G); if (mode == NULL) { /* No channels supported in this band - use empty list */ params->freqs = os_zalloc(sizeof(int)); return; } + if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN && + wpa_s->current_bss) { + const u8 *ie; + + ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION); + if (ie && ie[1] >= 2) { + u8 o; + + o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; + if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) + wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE; + else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) + wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW; + } + } + + start = wpa_s->assoc_freq - 10; + end = wpa_s->assoc_freq + 10; + switch (wpa_s->sme.ht_sec_chan) { + case HT_SEC_CHAN_UNKNOWN: + /* HT40+ possible on channels 1..9 */ + if (wpa_s->assoc_freq <= 2452) + start -= 20; + /* HT40- possible on channels 5-13 */ + if (wpa_s->assoc_freq >= 2432) + end += 20; + break; + case HT_SEC_CHAN_ABOVE: + end += 20; + break; + case HT_SEC_CHAN_BELOW: + start -= 20; + break; + } + wpa_printf(MSG_DEBUG, + "OBSS: assoc_freq %d possible affected range %d-%d", + wpa_s->assoc_freq, start, end); + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); if (params->freqs == NULL) return; for (count = 0, i = 0; i < mode->num_channels; i++) { + int freq; + if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) continue; - params->freqs[count++] = mode->channels[i].freq; + freq = mode->channels[i].freq; + if (freq - 10 >= end || freq + 10 <= start) + continue; /* not affected */ + params->freqs[count++] = freq; } } @@ -1172,7 +1448,7 @@ static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx) } os_memset(¶ms, 0, sizeof(params)); - wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms); + wpa_obss_scan_freqs_list(wpa_s, ¶ms); params.low_priority = 1; wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan"); @@ -1197,6 +1473,7 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable) eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL); wpa_s->sme.sched_obss_scan = 0; + wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN; if (!enable) return; @@ -1359,9 +1636,7 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, if (wpa_s->wpa_state != WPA_COMPLETED) return; ssid = wpa_s->current_ssid; - if (ssid == NULL || - (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? - wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION) + if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) return; if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) return;