sme.c revision df5a7e4c5c64890c2425bb47d665bbce4992b676
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - SME 3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_common.h" 17a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#include "common/sae.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/pmksa_cache.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpas_glue.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sme.h" 3004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hs20_supplicant.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SME_AUTH_TIMEOUT 5 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define SME_ASSOC_TIMEOUT 5 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_auth_timer(void *eloop_ctx, void *timeout_ctx); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx); 3704949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_stop_sa_query(struct wpa_supplicant *wpa_s); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 43d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 44d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 45a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int index_within_array(const int *array, int idx) 46a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 47a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int i; 48a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (i = 0; i < idx; i++) { 49cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (array[i] <= 0) 50a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 51a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 52a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 1; 53a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 54a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 55a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 56a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic int sme_set_sae_group(struct wpa_supplicant *wpa_s) 57a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{ 58a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int *groups = wpa_s->conf->sae_groups; 59cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int default_groups[] = { 19, 20, 21, 25, 26, 0 }; 60a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 61cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (!groups || groups[0] <= 0) 62a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt groups = default_groups; 63a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 64a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt /* Configuration may have changed, so validate current index */ 65a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (!index_within_array(groups, wpa_s->sme.sae_group_index)) 66a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 67a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 68a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt for (;;) { 69a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int group = groups[wpa_s->sme.sae_group_index]; 70a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (group < 0) 71a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt break; 72a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sae_set_group(&wpa_s->sme.sae, group) == 0) { 73a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d", 74a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.group); 75a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 76a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 77a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae_group_index++; 78a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 79a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 80a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 81a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt} 82a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 83a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 84a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtstatic struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, 85a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt struct wpa_ssid *ssid, 86a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt const u8 *bssid) 87d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 88d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *buf; 89a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt size_t len; 90a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 91a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ssid->passphrase == NULL) { 92a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "SAE: No password available"); 93a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return NULL; 94a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 95d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 96a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sme_set_sae_group(wpa_s) < 0) { 97a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "SAE: Failed to select group"); 98a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return NULL; 99a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 100a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 101a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sae_prepare_commit(wpa_s->own_addr, bssid, 102a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt (u8 *) ssid->passphrase, 103a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_strlen(ssid->passphrase), 104a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt &wpa_s->sme.sae) < 0) { 105a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); 106a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return NULL; 107a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 108a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 109a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0; 110a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len); 111d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (buf == NULL) 112d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return NULL; 113d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 114d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_put_le16(buf, 1); /* Transaction seq# */ 115d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); 116a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token); 117d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 118d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return buf; 119d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 120d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 121d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 122d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s) 123d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 124d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *buf; 125d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 126a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN); 127d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (buf == NULL) 128d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return NULL; 129d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 130d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_put_le16(buf, 2); /* Transaction seq# */ 131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); 132a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sae_write_confirm(&wpa_s->sme.sae, buf); 133d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 134d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return buf; 135d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 136d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 137d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 138d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 139d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 140d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic void sme_send_authentication(struct wpa_supplicant *wpa_s, 141d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_bss *bss, struct wpa_ssid *ssid, 142d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int start) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_auth_params params; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *old_ssid; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ie; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *md = NULL; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, bssid_changed; 153d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpabuf *resp = NULL; 154a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt u8 ext_capab[10]; 155a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt int ext_capab_len; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bss == NULL) { 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the network"); 160fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_bss = bss; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->reassociate = 0; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freq = bss->freq; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.bssid = bss->bssid; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssid = bss->ssid; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssid_len = bss->ssid_len; 1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.p2p = ssid->p2p_group; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.ssid_len != params.ssid_len || 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.prev_bssid_set = 0; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.freq = params.freq; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ssid_len = params.ssid_len; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg = WPA_AUTH_ALG_OPEN; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->leap) { 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->non_leap == 0) 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg = WPA_AUTH_ALG_LEAP; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg |= WPA_AUTH_ALG_LEAP; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */ 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg); 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->auth_alg) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg = ssid->auth_alg; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "0x%x", params.auth_alg); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 201d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 202d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_key_mgmt_sae(ssid->key_mgmt)) { 203d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt const u8 *rsn; 204d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_ie_data ied; 205d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 206d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 207d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (rsn && 208d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { 209d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_key_mgmt_sae(ied.key_mgmt)) { 210d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); 211d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt params.auth_alg = WPA_AUTH_ALG_SAE; 212d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 213d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 214d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 215d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < NUM_WEP_KEYS; i++) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid->wep_key_len[i]) 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wep_key[i] = ssid->wep_key[i]; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wep_key_len[i] = ssid->wep_key_len[i]; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wep_tx_keyidx = ssid->wep_tx_keyidx; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpa_s->bssid, 0, ETH_ALEN); 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bssid_changed) 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_bssid_changed(wpa_s); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_key_mgmt_wpa(ssid->key_mgmt)) { 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int try_opportunistic; 234d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt try_opportunistic = (ssid->proactive_key_caching < 0 ? 235d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->conf->okc : 236d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid->proactive_key_caching) && 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (ssid->proto & WPA_PROTO_RSN); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid, 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt try_opportunistic) == 0) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &wpa_s->sme.assoc_req_ie_len)) { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key management and encryption suites"); 248fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && 25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { 25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Both WPA and non-WPA IEEE 802.1X enabled in configuration - 25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * use non-WPA since the scan results did not indicate that the 25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * AP is using WPA or WPA2. 25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = 0; 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie, 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &wpa_s->sme.assoc_req_ie_len)) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key management and encryption suites (no " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "scan results)"); 268fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *wps_ie; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wps_ie && wpabuf_len(wps_ie) <= 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(wpa_s->sme.assoc_req_ie)) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = 0; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(wps_ie); 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */ 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len = 0; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt md = ie + 2; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (md) { 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Prepare for the next transition */ 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.assoc_req_ie_len + 5 < 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(wpa_s->sme.assoc_req_ie)) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_mdie *mdie; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos = wpa_s->sme.assoc_req_ie + 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = WLAN_EID_MOBILITY_DOMAIN; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = sizeof(*mdie); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie = (struct rsn_mdie *) pos; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(mdie->mobility_domain, md, 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MOBILITY_DOMAIN_ID_LEN); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len += 5; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.ft_used && 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_has_ptk(wpa_s->wpa)) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "over-the-air"); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.auth_alg = WPA_AUTH_ALG_FT; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ie = wpa_s->sme.ft_ies; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ie_len = wpa_s->sme.ft_ies_len; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 328d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 329d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->conf->pmf : ssid->ieee80211w; 330d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data _ie; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ie.capabilities & 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MFP: require MFP"); 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->global->p2p) { 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = sizeof(wpa_s->sme.assoc_req_ie) - 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len; 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ssid->p2p_group); 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res >= 0) 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie_len += res; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */ 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 35804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_HS20 35951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt if (is_hs20_network(wpa_s, ssid, bss)) { 36004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *hs20; 36104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt hs20 = wpabuf_alloc(20); 36204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (hs20) { 363f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); 364f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpas_hs20_add_indication(hs20, pps_mo_id); 36504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcpy(wpa_s->sme.assoc_req_ie + 36604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.assoc_req_ie_len, 36704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(hs20), wpabuf_len(hs20)); 36804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); 36904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(hs20); 37004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 37104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 37204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_HS20 */ 37304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 374a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); 375a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (ext_capab_len > 0) { 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos = wpa_s->sme.assoc_req_ie; 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += 2 + pos[1]; 379a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memmove(pos + ext_capab_len, pos, 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_s->sme.assoc_req_ie_len - 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (pos - wpa_s->sme.assoc_req_ie)); 382a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.assoc_req_ie_len += ext_capab_len; 383a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt os_memcpy(pos, ext_capab, ext_capab_len); 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 386d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 387d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (params.auth_alg == WPA_AUTH_ALG_SAE) { 388d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (start) 389a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt resp = sme_auth_build_sae_commit(wpa_s, ssid, 390a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt bss->bssid); 391d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt else 392d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt resp = sme_auth_build_sae_confirm(wpa_s); 393fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (resp == NULL) { 394fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 395d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return; 396fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 397d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt params.sae_data = wpabuf_head(resp); 398d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt params.sae_data_len = wpabuf_len(resp); 399a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; 400d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 401d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 402d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_supplicant_cancel_sched_scan(wpa_s); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_cancel_scan(wpa_s); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_clear_keys(wpa_s, bss->bssid); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_ssid = wpa_s->current_ssid; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid = ssid; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_initiate_eapol(wpa_s); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (old_ssid != wpa_s->current_ssid) 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_network_changed(wpa_s); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.auth_alg = params.auth_alg; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver failed"); 4231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpas_connection_failed(wpa_s, bss->bssid); 424c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_supplicant_mark_disassoc(wpa_s); 425d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_free(resp); 426fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Association will be started based on the authentication event from 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the driver. 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 437d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 438d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpabuf_free(resp); 439d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 440d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 441d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 442fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void sme_auth_start_cb(struct wpa_radio_work *work, int deinit) 443fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{ 444fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_connect_work *cwork = work->ctx; 445fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_supplicant *wpa_s = work->wpa_s; 446fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 447fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (deinit) { 448bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt if (work->started) 449bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt wpa_s->connect_work = NULL; 450bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt 451fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_free(cwork); 452fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 453fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 454fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 455fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_s->connect_work = work; 456fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 457fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (!wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) { 458fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt"); 459fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_done(wpa_s); 460fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 461fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 462fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 463fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1); 464fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt} 465fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 466fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 467d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtvoid sme_authenticate(struct wpa_supplicant *wpa_s, 468d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt struct wpa_bss *bss, struct wpa_ssid *ssid) 469d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 470fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct wpa_connect_work *cwork; 471fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 472fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (bss == NULL || ssid == NULL) 473fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 474fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (wpa_s->connect_work) { 475fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist"); 476fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 477fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt } 478fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 479f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if (radio_work_pending(wpa_s, "sme-connect")) { 480df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt /* 481df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * The previous sme-connect work might no longer be valid due to 482df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * the fact that the BSS list was updated. In addition, it makes 483df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt * sense to adhere to the 'newer' decision. 484df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt */ 485df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, 486df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt "SME: Remove previous pending sme-connect"); 487df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt radio_remove_works(wpa_s, "sme-connect", 0); 488f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 489f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 490fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cwork = os_zalloc(sizeof(*cwork)); 491fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (cwork == NULL) 492fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt return; 493fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cwork->bss = bss; 494fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cwork->ssid = ssid; 495fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt cwork->sme = 1; 496fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 497a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_SAE 498a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.state = SAE_NOTHING; 499a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.send_confirm = 0; 500cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_s->sme.sae_group_index = 0; 501a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_SAE */ 502fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt 503fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1, 504fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt sme_auth_start_cb, cwork) < 0) 505fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt wpas_connect_work_free(cwork); 506d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt} 507d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 508d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 509d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 510d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 511d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, 512d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt u16 status_code, const u8 *data, size_t len) 513d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{ 514d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u " 515d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt "status code %u", auth_transaction, status_code); 516a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 517a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (auth_transaction == 1 && 518a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && 519a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.state == SAE_COMMITTED && 520a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->current_bss && wpa_s->current_ssid) { 521a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE anti-clogging token " 522a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt "requested"); 523a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpabuf_free(wpa_s->sme.sae_token); 524a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae_token = wpabuf_alloc_copy(data, len); 525a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sme_send_authentication(wpa_s, wpa_s->current_bss, 526a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->current_ssid, 1); 527a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 528a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 529a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 530a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (auth_transaction == 1 && 531a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED && 532a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.state == SAE_COMMITTED && 533a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->current_bss && wpa_s->current_ssid) { 534a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported"); 535a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae_group_index++; 536a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sme_set_sae_group(wpa_s) < 0) 537a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; /* no other groups enabled */ 538a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group"); 539a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sme_send_authentication(wpa_s, wpa_s->current_bss, 540a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->current_ssid, 1); 541a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; 542a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 543d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 544d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (status_code != WLAN_STATUS_SUCCESS) 545d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 546d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 547d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (auth_transaction == 1) { 548cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int *groups = wpa_s->conf->sae_groups; 549cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 550d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit"); 551d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (wpa_s->current_bss == NULL || 552d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->current_ssid == NULL) 553d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_s->sme.sae.state != SAE_COMMITTED) 555d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 556cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (groups && groups[0] <= 0) 557cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt groups = NULL; 558a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL, 559cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt groups) != WLAN_STATUS_SUCCESS) 560d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 561a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 562a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sae_process_commit(&wpa_s->sme.sae) < 0) { 563a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "SAE: Failed to process peer " 564a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt "commit"); 565a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return -1; 566a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt } 567a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 568a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpabuf_free(wpa_s->sme.sae_token); 569a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae_token = NULL; 570d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt sme_send_authentication(wpa_s, wpa_s->current_bss, 571d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->current_ssid, 0); 572d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 0; 573d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } else if (auth_transaction == 2) { 574d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm"); 575a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (wpa_s->sme.sae.state != SAE_CONFIRMED) 576d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 577a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0) 578d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 579a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae.state = SAE_ACCEPTED; 580a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sae_clear_temp_data(&wpa_s->sme.sae); 581d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return 1; 582d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 583d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 584d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return -1; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 586d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid = wpa_s->current_ssid; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ssid == NULL) { 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when network is not selected"); 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "when not in authenticating state"); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with " 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected peer " MACSTR, 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(data->auth.peer)); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 613d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt " auth_type=%d auth_transaction=%d status_code=%d", 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(data->auth.peer), data->auth.auth_type, 615d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt data->auth.auth_transaction, data->auth.status_code); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth.ies, data->auth.ies_len); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 621d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_SAE 622d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (data->auth.auth_type == WLAN_AUTH_SAE) { 623d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt int res; 624d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt res = sme_sae_auth(wpa_s, data->auth.auth_transaction, 625d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt data->auth.status_code, data->auth.ies, 626d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt data->auth.ies_len); 627d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (res < 0) { 628d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 629d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 630d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 631d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 632d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (res != 1) 633d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return; 634a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt 635a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for " 636a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt "4-way handshake"); 637a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN); 638d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt } 639d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_SAE */ 640d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "code %d)", data->auth.status_code); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth.status_code != 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.auth_alg == data->auth.auth_type || 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) { 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 65004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6549767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt wpas_connect_work_done(wpa_s); 6559767226d8e6a1adaa33beb9f517ef40dddfa460cDmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->auth.auth_type) { 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_AUTH_OPEN: 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth"); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_AUTH_SHARED_KEY: 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth"); 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->current_ssid); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth.auth_type == WLAN_AUTH_FT) { 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data edata; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&edata, 0, sizeof(edata)); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt edata.ft_ies.ies = data->auth.ies; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt edata.ft_ies.ies_len = data->auth.ies_len; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_associate(wpa_s, ssid->mode, data->auth.peer, 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth.auth_type); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *bssid, u16 auth_type) 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_associate_params params; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ieee802_11_elems elems; 699c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_HT_OVERRIDES 700c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ieee80211_ht_capabilities htcaps; 701c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt struct ieee80211_ht_capabilities htcaps_mask; 702c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_HT_OVERRIDES */ 7032f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt#ifdef CONFIG_VHT_OVERRIDES 7042f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt struct ieee80211_vht_capabilities vhtcaps; 7052f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt struct ieee80211_vht_capabilities vhtcaps_mask; 7062f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt#endif /* CONFIG_VHT_OVERRIDES */ 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.bssid = bssid; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssid = wpa_s->sme.ssid; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssid_len = wpa_s->sme.ssid_len; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freq = wpa_s->sme.freq; 71304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params.bg_scan_period = wpa_s->current_ssid ? 71404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->current_ssid->bg_scan_period : -1; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.assoc_req_ie : NULL; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 718fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params.pairwise_suite = wpa_s->pairwise_cipher; 719fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt params.group_suite = wpa_s->group_cipher; 72015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params.key_mgmt_suite = wpa_s->key_mgmt; 72115907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt params.wpa_proto = wpa_s->wpa_proto; 722c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_HT_OVERRIDES 723c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(&htcaps, 0, sizeof(htcaps)); 724c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); 725c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params.htcaps = (u8 *) &htcaps; 726c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt params.htcaps_mask = (u8 *) &htcaps_mask; 727c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); 728c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_HT_OVERRIDES */ 7292f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt#ifdef CONFIG_VHT_OVERRIDES 7302f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt os_memset(&vhtcaps, 0, sizeof(vhtcaps)); 7312f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); 7322f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt params.vhtcaps = &vhtcaps; 7332f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt params.vhtcaps_mask = &vhtcaps_mask; 7342f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); 7352f023193a0fd630eb82ce6381b80911ad5a3462fDmitry Shmidt#endif /* CONFIG_VHT_OVERRIDES */ 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wpa_ie = wpa_s->sme.ft_ies; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.wpa_ie_len = wpa_s->sme.ft_ies_len; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */ 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.mode = mode; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.mgmt_frame_protection = wpa_s->sme.mfp; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.prev_bssid_set) 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.prev_bssid = wpa_s->sme.prev_bssid; 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.freq); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (params.wpa_ie == NULL || 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&elems, 0, sizeof(elems)); 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (elems.rsn_ie) { 7611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.wpa_proto = WPA_PROTO_RSN; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt elems.rsn_ie_len + 2); 7641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else if (elems.wpa_ie) { 7651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt params.wpa_proto = WPA_PROTO_WPA; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt elems.wpa_ie_len + 2); 768f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } else if (elems.osen) { 769f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt params.wpa_proto = WPA_PROTO_OSEN; 770f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2, 771f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt elems.osen_len + 2); 7721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 7741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.p2p = 1; 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->parent->set_sta_uapsd) 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.uapsd = wpa_s->parent->sta_uapsd; 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt params.uapsd = -1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver failed"); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 78604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ies, size_t ies_len) 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (md == NULL || ies == NULL) { 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain"); 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->sme.ft_ies); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies = NULL; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies_len = 0; 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_used = 0; 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->sme.ft_ies); 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies = os_malloc(ies_len); 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.ft_ies == NULL) 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies_len = ies_len; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_deauth(struct wpa_supplicant *wpa_s) 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int bssid_changed; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING) < 0) { 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver " 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.prev_bssid_set = 0; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpa_s->bssid, 0, ETH_ALEN); 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (bssid_changed) 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_notify_bssid_changed(wpa_s); 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data *data) 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: " 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "status code %d", MAC2STR(wpa_s->pending_bssid), 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->assoc_reject.status_code); 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * For now, unconditionally terminate the previous authentication. In 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * theory, this should not be needed, but mac80211 gets quite confused 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * if the authentication is left pending.. Some roaming cases might 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * benefit from using the previous authentication, so this could be 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * optimized in the future. 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_deauth(wpa_s); 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data *data) 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out"); 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 867c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_supplicant_mark_disassoc(wpa_s); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union wpa_event_data *data) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out"); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_mark_disassoc(wpa_s); 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_disassoc(struct wpa_supplicant *wpa_s, 881c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt struct disassoc_info *info) 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received"); 8841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpa_s->sme.prev_bssid_set) { 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cfg80211/mac80211 can get into somewhat confused state if 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the AP only disassociates us and leaves us in authenticated 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * state. For now, force the state to be cleared to avoid 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * confusing errors if we try to associate with the AP again. 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear " 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver state"); 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid, 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_DEAUTH_LEAVING); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_auth_timer(void *eloop_ctx, void *timeout_ctx) 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_AUTHENTICATING) { 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout"); 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_deauth(wpa_s); 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx) 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state == WPA_ASSOCIATING) { 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout"); 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_deauth(wpa_s); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_state_changed(struct wpa_supplicant *wpa_s) 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Make sure timers are cleaned up appropriately. */ 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state != WPA_ASSOCIATING) 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state != WPA_AUTHENTICATING) 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *prev_pending_bssid) 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * mac80211-workaround to force deauth on failed auth cmd, 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requires us to remain in authenticating state to allow the 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * second authentication attempt to be continued properly. 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication " 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "to proceed after disconnection event"); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN); 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Re-arm authentication timer in case auth fails for whatever reason. 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_deinit(struct wpa_supplicant *wpa_s) 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->sme.ft_ies); 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies = NULL; 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.ft_ies_len = 0; 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_stop_sa_query(wpa_s); 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 959a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_SAE 960a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpabuf_free(wpa_s->sme.sae_token); 961a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt wpa_s->sme.sae_token = NULL; 962a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt sae_clear_data(&wpa_s->sme.sae); 963a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_SAE */ 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 96704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL); 96804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 96904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 97004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 97104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, 97204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *chan_list, u8 num_channels, 97304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 num_intol) 97404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 97504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct ieee80211_2040_bss_coex_ie *bc_ie; 97604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct ieee80211_2040_intol_chan_report *ic_report; 97704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpabuf *buf; 97804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 979d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR 980d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt " (num_channels=%u num_intol=%u)", 981d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt MAC2STR(wpa_s->bssid), num_channels, num_intol); 982d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels", 983d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt chan_list, num_channels); 98404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 98504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt buf = wpabuf_alloc(2 + /* action.category + action_code */ 98604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sizeof(struct ieee80211_2040_bss_coex_ie) + 98704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sizeof(struct ieee80211_2040_intol_chan_report) + 98804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt num_channels); 98904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (buf == NULL) 99004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 99104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 99204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); 99304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX); 99404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 99504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt bc_ie = wpabuf_put(buf, sizeof(*bc_ie)); 99604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE; 99704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt bc_ie->length = 1; 99804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (num_intol) 99904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ; 100004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 100104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (num_channels > 0) { 100204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ic_report = wpabuf_put(buf, sizeof(*ic_report)); 100304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT; 100404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ic_report->length = num_channels + 1; 100504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ic_report->op_class = 0; 100604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memcpy(wpabuf_put(buf, num_channels), chan_list, 100704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt num_channels); 100804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 100904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 101004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 101104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->own_addr, wpa_s->bssid, 101204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { 101304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_msg(wpa_s, MSG_INFO, 101404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "SME: Failed to send 20/40 BSS Coexistence frame"); 101504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 101604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 101704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpabuf_free(buf); 101804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 101904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 102004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 102104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint sme_proc_obss_scan(struct wpa_supplicant *wpa_s) 102204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 102304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss; 102404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *ie; 102504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 ht_cap; 102604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 chan_list[P2P_MAX_CHANNELS], channel; 102704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u8 num_channels = 0, num_intol = 0, i; 102804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 102904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpa_s->sme.sched_obss_scan) 103004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 0; 103104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 103204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.sched_obss_scan = 0; 103304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED) 103404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 103504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 103604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* 103704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Check whether AP uses regulatory triplet or channel triplet in 103804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * country info. Right now the operating class of the BSS channel 103904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12), 104004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * based on the assumption that operating class triplet is not used in 104104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * beacon frame. If the First Channel Number/Operating Extension 104204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Identifier octet has a positive integer value of 201 or greater, 104304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * then its operating class triplet. 104404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 104504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * TODO: If Supported Operating Classes element is present in beacon 104604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * frame, have to lookup operating class in Annex E and fill them in 104704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * 2040 coex frame. 104804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt */ 104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY); 105004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (ie && (ie[1] >= 6) && (ie[5] >= 201)) 105104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 105204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 105304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(chan_list, 0, sizeof(chan_list)); 105404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 105504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { 105604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Skip other band bss */ 10574b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt enum hostapd_hw_mode mode; 10584b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt mode = ieee80211_freq_to_chan(bss->freq, &channel); 10594b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt if (mode != HOSTAPD_MODE_IEEE80211G && 10604b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt mode != HOSTAPD_MODE_IEEE80211B) 106104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 106204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 106304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP); 106404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0; 1065d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR 1066d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt " freq=%u chan=%u ht_cap=0x%x", 1067d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt MAC2STR(bss->bssid), bss->freq, channel, ht_cap); 106804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 106904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) { 1070d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT) 1071d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt num_intol++; 1072d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt 107304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Check whether the channel is already considered */ 107404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < num_channels; i++) { 107504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (channel == chan_list[i]) 107604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt break; 107704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 107804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (i != num_channels) 107904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 108004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 108104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt chan_list[num_channels++] = channel; 108204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 108304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 108404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 108504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol); 108604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return 1; 108704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 108804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 108904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 109004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, 109104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 num_modes, 109204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt enum hostapd_hw_mode mode) 109304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 109404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt u16 i; 109504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 109604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < num_modes; i++) { 109704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (modes[i].mode == mode) 109804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return &modes[i]; 109904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 110004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 110104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return NULL; 110204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 110304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 110404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 110504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, 110604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt enum hostapd_hw_mode band, 110704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params *params) 110804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 110904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Include only supported channels for the specified band */ 111004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_hw_modes *mode; 111104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int count, i; 111204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 111304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band); 111404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (mode == NULL) { 111504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* No channels supported in this band - use empty list */ 111604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params->freqs = os_zalloc(sizeof(int)); 111704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 111804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 111904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 112061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 112104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (params->freqs == NULL) 112204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 112304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (count = 0, i = 0; i < mode->num_channels; i++) { 112404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) 112504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 112604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params->freqs[count++] = mode->channels[i].freq; 112704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 112804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 112904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 113004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 113104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx) 113204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 113304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 113404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params params; 113504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 113604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!wpa_s->current_bss) { 113704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request"); 113804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 113904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 114004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 114104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 114204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms); 114304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan"); 114404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 114504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) 114604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan"); 114704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 114804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.sched_obss_scan = 1; 114904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt os_free(params.freqs); 115004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 115104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eloop_register_timeout(wpa_s->sme.obss_scan_int, 0, 115204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sme_obss_scan_timeout, wpa_s, NULL); 115304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 115404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 115504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 115604949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable) 115704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 115804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt const u8 *ie; 115904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_bss *bss = wpa_s->current_bss; 116004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_ssid *ssid = wpa_s->current_ssid; 116161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt struct hostapd_hw_modes *hw_mode = NULL; 116261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt int i; 116304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 116404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL); 116504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.sched_obss_scan = 0; 116604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!enable) 116704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 116804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 1169d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt /* 1170d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * Schedule OBSS scan if driver is using station SME in wpa_supplicant 1171d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt * or it expects OBSS scan to be performed by wpa_supplicant. 1172d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt */ 1173d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) || 1174d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) || 1175d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt ssid == NULL || ssid->mode != IEEE80211_MODE_INFRA) 1176d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt return; 117704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 117861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (!wpa_s->hw.modes) 117961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 118061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 118161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* only HT caps in 11g mode are relevant */ 118261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt for (i = 0; i < wpa_s->hw.num_modes; i++) { 118361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hw_mode = &wpa_s->hw.modes[i]; 118461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G) 118561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 118661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 118761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 118861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* Driver does not support HT40 for 11g or doesn't have 11g. */ 118961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (i == wpa_s->hw.num_modes || !hw_mode || 119061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) 119161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return; 119204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 119304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (bss == NULL || bss->freq < 2400 || bss->freq > 2500) 119404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; /* Not associated on 2.4 GHz band */ 119504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 119604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Check whether AP supports HT40 */ 119704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP); 119804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!ie || ie[1] < 2 || 119904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) 120004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; /* AP does not support HT40 */ 120104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 120204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ie = wpa_bss_get_ie(wpa_s->current_bss, 120304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS); 120404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (!ie || ie[1] < 14) 120504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; /* AP does not request OBSS scans */ 120604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 120704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6); 120804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (wpa_s->sme.obss_scan_int < 10) { 120904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u " 121004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt "replaced with the minimum 10 sec", 121104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.obss_scan_int); 121204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.obss_scan_int = 10; 121304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 121404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec", 121504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_s->sme.obss_scan_int); 121604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt eloop_register_timeout(wpa_s->sme.obss_scan_int, 0, 121704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sme_obss_scan_timeout, wpa_s, NULL); 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const unsigned int sa_query_max_timeout = 1000; 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const unsigned int sa_query_retry_timeout = 201; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s) 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 tu; 1229fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now, passed; 1230fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 1231fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed); 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tu = (passed.sec * 1000000 + passed.usec) / 1024; 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sa_query_max_timeout < tu) { 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out"); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_stop_sa_query(wpa_s); 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_supplicant_deauthenticate( 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID); 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_send_sa_query_req(struct wpa_supplicant *wpa_s, 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *trans_id) 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN]; 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to " 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(wpa_s->bssid)); 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID", 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trans_id, WLAN_SA_QUERY_TR_ID_LEN); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req[0] = WLAN_ACTION_SA_QUERY; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req[1] = WLAN_SA_QUERY_REQUEST; 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN); 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->own_addr, wpa_s->bssid, 12581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt req, sizeof(req), 0) < 0) 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query " 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Request"); 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx) 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_supplicant *wpa_s = eloop_ctx; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned int timeout, sec, usec; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *trans_id, *nbuf; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.sa_query_count > 0 && 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_check_sa_query_timeout(wpa_s)) 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 127461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id, 127561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_s->sme.sa_query_count + 1, 127661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt WLAN_SA_QUERY_TR_ID_LEN); 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (nbuf == NULL) 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.sa_query_count == 0) { 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Starting a new SA Query procedure */ 1281fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&wpa_s->sme.sa_query_start); 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.sa_query_trans_id = nbuf; 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.sa_query_count++; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeout = sa_query_retry_timeout; 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = ((timeout / 1000) * 1024) / 1000; 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt usec = (timeout % 1000) * 1024; 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL); 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d", 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.sa_query_count); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_send_sa_query_req(wpa_s, trans_id); 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void sme_start_sa_query(struct wpa_supplicant *wpa_s) 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_sa_query_timer(wpa_s, NULL); 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void sme_stop_sa_query(struct wpa_supplicant *wpa_s) 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL); 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(wpa_s->sme.sa_query_trans_id); 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.sa_query_trans_id = NULL; 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_s->sme.sa_query_count = 0; 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *da, u16 reason_code) 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ssid *ssid; 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->wpa_state != WPA_COMPLETED) 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ssid = wpa_s->current_ssid; 1324d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt if (ssid == NULL || 1325d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? 1326d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION) 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA && 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA) 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.sa_query_count > 0) 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - " 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "possible AP/STA state mismatch - trigger SA Query"); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_start_sa_query(wpa_s); 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t len) 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_s->sme.sa_query_trans_id == NULL || 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len < 1 + WLAN_SA_QUERY_TR_ID_LEN || 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data[0] != WLAN_SA_QUERY_RESPONSE) 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from " 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]); 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < wpa_s->sme.sa_query_count; i++) { 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(wpa_s->sme.sa_query_trans_id + 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i * WLAN_SA_QUERY_TR_ID_LEN, 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0) 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i >= wpa_s->sme.sa_query_count) { 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query " 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transaction identifier found"); 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received " 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from " MACSTR, MAC2STR(sa)); 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sme_stop_sa_query(wpa_s); 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */ 1376