18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - Driver event processing
3fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * Copyright (c) 2003-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 "eapol_supp/eapol_supp_sm.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "config.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_supplicant_i.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "driver_i.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pcsc_funcs.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/preauth.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/pmksa_cache.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_peer/eap.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap/hostapd.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h"
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "wnm_sta.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "notify.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "blacklist.h"
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpas_glue.h"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_supplicant.h"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ibss_rsn.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sme.h"
361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "gas_query.h"
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p_supplicant.h"
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bgscan.h"
3904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "autoscan.h"
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap.h"
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "bss.h"
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "scan.h"
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "offchannel.h"
4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "interworking.h"
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4734af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#ifndef CONFIG_NO_SCAN_PROCESSING
488da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidtstatic int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
49e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt					      int new_scan, int own_request);
5034af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* CONFIG_NO_SCAN_PROCESSING */
514b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
524b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			      struct wpa_ssid *ssid)
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
56fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (ssid == NULL || ssid->disabled_until.sec == 0)
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 0;
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
61fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (ssid->disabled_until.sec > now.sec)
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return ssid->disabled_until.sec - now.sec;
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_clear_temp_disabled(wpa_s, ssid, 0);
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	return 0;
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
71cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic struct wpa_bss * wpa_supplicant_get_new_bss(
72cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpa_supplicant *wpa_s, const u8 *bssid)
73cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
74cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpa_bss *bss = NULL;
75cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
76cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
77cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (ssid->ssid_len > 0)
78cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
79cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (!bss)
80cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		bss = wpa_bss_get_bssid(wpa_s, bssid);
81cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
82cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return bss;
83cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
84cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
85cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
865c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinenstatic void wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s)
875c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen{
885c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
895c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen
905c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	if (!bss) {
915c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen		wpa_supplicant_update_scan_results(wpa_s);
925c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen
935c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen		/* Get the BSS from the new scan results */
945c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen		bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
955c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	}
965c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen
975c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	if (bss)
985c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen		wpa_s->current_bss = bss;
995c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen}
1005c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen
1015c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid, *old_ssid;
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	int res;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1075c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) {
1085c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen		wpa_supplicant_update_current_bss(wpa_s);
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1105c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	}
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association "
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"information");
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_supplicant_get_ssid(wpa_s);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO,
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"No network configuration found for the current AP");
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpas_network_disabled(wpa_s, ssid)) {
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is disabled");
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
126d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (disallowed_bssid(wpa_s, wpa_s->bssid) ||
127d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    disallowed_ssid(wpa_s, ssid->ssid, ssid->ssid_len)) {
128d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS is disallowed");
129d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return -1;
130d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	res = wpas_temp_disabled(wpa_s, ssid);
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (res > 0) {
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is temporarily "
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			"disabled for %d second(s)", res);
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return -1;
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the "
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"current AP");
1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 wpa_ie[80];
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t wpa_ie_len = sizeof(wpa_ie);
144a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
145a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt					      wpa_ie, &wpa_ie_len) < 0)
146a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Could not set WPA suites");
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid && wpa_s->current_ssid != ssid)
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_invalidate_cached_session(wpa_s->eapol);
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	old_ssid = wpa_s->current_ssid;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->current_ssid = ssid;
155cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
1565c879ee8a1def48a71e0929d378c0912ef63bb3fJouni Malinen	wpa_supplicant_update_current_bss(wpa_s);
157cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_initiate_eapol(wpa_s);
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (old_ssid != wpa_s->current_ssid)
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_network_changed(wpa_s);
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx)
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->countermeasures) {
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->countermeasures = 0;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_set_countermeasures(wpa_s, 0);
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped");
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 0, 0);
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int bssid_changed;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wnm_bss_keep_alive_deinit(wpa_s);
18504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IBSS_RSN
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ibss_rsn_deinit(wpa_s->ibss_rsn);
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->ibss_rsn = NULL;
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IBSS_RSN */
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
191c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#ifdef CONFIG_AP
192c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	wpa_supplicant_ap_deinit(wpa_s);
193c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#endif /* CONFIG_AP */
194c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(wpa_s->bssid, 0, ETH_ALEN);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
20204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_SME
20304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_s->sme.prev_bssid_set = 0;
20404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_SME */
205c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#ifdef CONFIG_P2P
206c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
207c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt#endif /* CONFIG_P2P */
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->current_bss = NULL;
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->assoc_freq = 0;
210c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#ifdef CONFIG_IEEE80211R
211c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#ifdef CONFIG_SME
212c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt	if (wpa_s->sme.ft_ies)
213c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt		sme_update_ft_ies(wpa_s, NULL, NULL, 0);
214c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#endif /* CONFIG_SME */
215c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt#endif /* CONFIG_IEEE80211R */
216c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bssid_changed)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_notify_bssid_changed(wpa_s);
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->ap_ies_from_associnfo = 0;
22561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s->current_ssid = NULL;
226b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpa_s->key_mgmt = 0;
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ie_data ie;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pmksa_set = -1;
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 ||
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ie.pmkid == NULL)
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < ie.num_pmkid; i++) {
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    ie.pmkid + i * PMKID_LEN,
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						    NULL, NULL, 0);
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (pmksa_set == 0) {
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from "
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"PMKSA cache", pmksa_set == 0 ? "" : "not ");
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_pmkid_candidate(struct wpa_supplicant *wpa_s,
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 union wpa_event_data *data)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL) {
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "RSN: No data in PMKID candidate "
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"event");
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		" index=%d preauth=%d",
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(data->pmkid_candidate.bssid),
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pmkid_candidate.index,
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		data->pmkid_candidate.preauth);
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pmksa_candidate_add(wpa_s->wpa, data->pmkid_candidate.bssid,
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->pmkid_candidate.index,
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->pmkid_candidate.preauth);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid &&
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    !(wpa_s->current_ssid->eapol_flags &
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	      (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) {
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* IEEE 802.1X, but not using dynamic WEP keys (i.e., either
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * plaintext or static WEP keys). */
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: pointer to wpa_supplicant data
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ssid: Configuration data for the network
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called when starting authentication with a network that is
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA).
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      struct wpa_ssid *ssid)
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef PCSC_FUNCS
312391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	int aka = 0, sim = 0;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
314df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	if ((ssid != NULL && ssid->eap.pcsc == NULL) ||
315df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	    wpa_s->scard != NULL || wpa_s->conf->external_sim)
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt	if (ssid == NULL || ssid->eap.eap_methods == NULL) {
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sim = 1;
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aka = 1;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct eap_method_type *eap = ssid->eap.eap_methods;
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		while (eap->vendor != EAP_VENDOR_IETF ||
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       eap->method != EAP_TYPE_NONE) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (eap->vendor == EAP_VENDOR_IETF) {
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (eap->method == EAP_TYPE_SIM)
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					sim = 1;
32804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				else if (eap->method == EAP_TYPE_AKA ||
32904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 eap->method == EAP_TYPE_AKA_PRIME)
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					aka = 1;
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eap++;
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL)
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sim = 0;
33804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL &&
33904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME) ==
34004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	    NULL)
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aka = 0;
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!sim && !aka) {
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to "
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"use SIM, but neither EAP-SIM nor EAP-AKA are "
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"enabled");
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM "
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"(sim=%d aka=%d) - initialize PCSC", sim, aka);
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3532271d3fdd5982d0e5e81cf9999a861bba933eacbDmitry Shmidt	wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->scard == NULL) {
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(pcsc-lite)");
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* PCSC_FUNCS */
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_SCAN_PROCESSING
369b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
370b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int has_wep_key(struct wpa_ssid *ssid)
371b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{
372b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	int i;
373b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
374b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	for (i = 0; i < NUM_WEP_KEYS; i++) {
375b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		if (ssid->wep_key_len[i])
376b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			return 1;
377b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	}
378b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
379b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	return 0;
380b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt}
381b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
382b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
3839bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidtstatic int wpa_supplicant_match_privacy(struct wpa_bss *bss,
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					struct wpa_ssid *ssid)
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
386b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	int privacy = 0;
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mixed_cell)
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
396b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt	if (has_wep_key(ssid))
397b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		privacy = 1;
398b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef IEEE8021X_EAPOL
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 EAPOL_FLAG_REQUIRE_KEY_BROADCAST))
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		privacy = 1;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* IEEE8021X_EAPOL */
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
40675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (wpa_key_mgmt_wpa(ssid->key_mgmt))
40775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		privacy = 1;
40875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
409f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)
410f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		privacy = 1;
411f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bss->caps & IEEE80211_CAP_PRIVACY)
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return privacy;
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return !privacy;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_ssid *ssid,
4209bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt					 struct wpa_bss *bss)
4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ie_data ie;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int proto_match = 0;
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *rsn_ie, *wpa_ie;
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int wep_ok;
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ret >= 0)
4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ret;
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		(((ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) ||
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4389bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		proto_match++;
4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - parse "
4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"failed");
4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wep_ok &&
4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   selected based on TSN "
4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"in RSN IE");
4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.proto & ssid->proto)) {
4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - proto "
4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"mismatch");
4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - PTK "
4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"cipher mismatch");
4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.group_cipher & ssid->group_cipher)) {
4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - GTK "
4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"cipher mismatch");
4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.key_mgmt & ssid->key_mgmt)) {
4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - key mgmt "
4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"mismatch");
4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
482d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
483d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		     wpa_s->conf->pmf : ssid->ieee80211w) ==
484d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		    MGMT_FRAME_PROTECTION_REQUIRED) {
4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip RSN IE - no mgmt "
4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"frame protection");
4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   selected based on RSN IE");
4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4959bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		proto_match++;
4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) {
5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip WPA IE - parse "
5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"failed");
5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wep_ok &&
5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   selected based on TSN "
5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"in WPA IE");
5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.proto & ssid->proto)) {
5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip WPA IE - proto "
5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"mismatch");
5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip WPA IE - PTK "
5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"cipher mismatch");
5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.group_cipher & ssid->group_cipher)) {
5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip WPA IE - GTK "
5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"cipher mismatch");
5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!(ie.key_mgmt & ssid->key_mgmt)) {
5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip WPA IE - key mgmt "
5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"mismatch");
5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   selected based on WPA IE");
5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
54161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie &&
54261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	    !rsn_ie) {
54361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   allow for non-WPA IEEE 802.1X");
54461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return 1;
54561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
54661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) &&
5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) {
5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   skip - no WPA/RSN proto match");
5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
553f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) &&
554f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) {
555f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   allow in OSEN");
556f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		return 1;
557f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	}
558f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   allow in non-WPA/WPA2");
5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "   reject due to mismatch with "
5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		"WPA/WPA2");
5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int freq_allowed(int *freqs, int freq)
5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (freqs == NULL)
5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; freqs[i]; i++)
5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (freqs[i] == freq)
5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
5859ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtint ht_supported(const struct hostapd_hw_modes *mode)
5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver did not indicate whether it supports HT. Assume
5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * it does to avoid connection issues.
5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1;
5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/*
5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * IEEE Std 802.11n-2009 20.1.1:
5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 * An HT non-AP STA shall support all EQM rates for one spatial stream.
5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	 */
5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return mode->mcs_set[0] == 0xff;
6001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
6011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6039ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidtint vht_supported(const struct hostapd_hw_modes *mode)
604c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
605c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
606c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		/*
607c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		 * The driver did not indicate whether it supports VHT. Assume
608c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		 * it does to avoid connection issues.
609c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		 */
610c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return 1;
611c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
612c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
613c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	/*
614c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
615c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	 * TODO: Verify if this complies with the standard
616c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	 */
617c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	return (mode->vht_mcs_set[0] & 0x3) != 3;
618c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
619c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
620c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
6219bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidtstatic int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const struct hostapd_hw_modes *mode = NULL, *modes;
6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const u8 *rate_ie;
6261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int i, j, k;
6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (bss->freq == 0)
6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1; /* Cannot do matching without knowing band */
6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	modes = wpa_s->hw.modes;
6321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (modes == NULL) {
6331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
6341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * The driver does not provide any additional information
6351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * about the utilized hardware, so allow the connection attempt
6361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 * to continue.
6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
6381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 1;
6391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; i < wpa_s->hw.num_modes; i++) {
6421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		for (j = 0; j < modes[i].num_channels; j++) {
6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			int freq = modes[i].channels[j].freq;
6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (freq == bss->freq) {
6451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				if (mode &&
6461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				    mode->mode == HOSTAPD_MODE_IEEE80211G)
6471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					break; /* do not allow 802.11b replace
6481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						* 802.11g */
6491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				mode = &modes[i];
6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				break;
6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
6521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
6531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
6541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (mode == NULL)
6561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0;
6571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	for (i = 0; i < (int) sizeof(scan_ie); i++) {
6599bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		rate_ie = wpa_bss_get_ie(bss, scan_ie[i]);
6601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (rate_ie == NULL)
6611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
6621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		for (j = 2; j < rate_ie[1] + 2; j++) {
6641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			int flagged = !!(rate_ie[j] & 0x80);
6651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			int r = (rate_ie[j] & 0x7f) * 5;
6661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
6671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/*
6681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * IEEE Std 802.11n-2009 7.3.2.2:
6691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * The new BSS Membership selector value is encoded
6701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * like a legacy basic rate, but it is not a rate and
6711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * only indicates if the BSS members are required to
6721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * support the mandatory features of Clause 20 [HT PHY]
6731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * in order to join the BSS.
6741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 */
6751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (flagged && ((rate_ie[j] & 0x7f) ==
6761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					BSS_MEMBERSHIP_SELECTOR_HT_PHY)) {
6771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				if (!ht_supported(mode)) {
6781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					wpa_dbg(wpa_s, MSG_DEBUG,
6791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						"   hardware does not support "
6801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						"HT PHY");
6811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					return 0;
6821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				}
6831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				continue;
6841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
6851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
686c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			/* There's also a VHT selector for 802.11ac */
687c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (flagged && ((rate_ie[j] & 0x7f) ==
688c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) {
689c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				if (!vht_supported(mode)) {
690c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					wpa_dbg(wpa_s, MSG_DEBUG,
691c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt						"   hardware does not support "
692c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt						"VHT PHY");
693c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					return 0;
694c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				}
695c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				continue;
696c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
697c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
6981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (!flagged)
6991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				continue;
7001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/* check for legacy basic rates */
7021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			for (k = 0; k < mode->num_rates; k++) {
7031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				if (mode->rates[k] == r)
7041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					break;
7051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
7061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (k == mode->num_rates) {
7071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				/*
7081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 * IEEE Std 802.11-2007 7.3.2.2 demands that in
7091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 * order to join a BSS all required rates
7101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 * have to be supported by the hardware.
7111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				 */
7121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "   hardware does "
7131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					"not support required rate %d.%d Mbps",
7141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					r / 10, r % 10);
7151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return 0;
7161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
7171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
7181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
7191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return 1;
7211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
7221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
7231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
724f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt/*
725f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * Test whether BSS is in an ESS.
726f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt * This is done differently in DMG (60 GHz) and non-DMG bands
727f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt */
728f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidtstatic int bss_is_ess(struct wpa_bss *bss)
729f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt{
730f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	if (bss_is_dmg(bss)) {
731f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		return (bss->caps & IEEE80211_CAP_DMG_MASK) ==
732f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			IEEE80211_CAP_DMG_AP;
733f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	}
734f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
735f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	return ((bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
736f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		IEEE80211_CAP_ESS);
737f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt}
738f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
739f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt
7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
7419bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt					    int i, struct wpa_bss *bss,
742f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					    struct wpa_ssid *group,
743f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					    int only_first_ssid)
7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
7459bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	u8 wpa_ie_len, rsn_ie_len;
7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int wpa;
7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_blacklist *e;
7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *ie;
7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
750f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	int osen;
7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7529bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_ie_len = ie ? ie[1] : 0;
7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7559bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	rsn_ie_len = ie ? ie[1] : 0;
7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
759f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	osen = ie != NULL;
760f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
762f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s%s",
7639bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
7659657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "",
7669657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		(wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
7679657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		 wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ?
768f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		" p2p" : "",
769f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		osen ? " osen=1" : "");
7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	e = wpa_blacklist_get(wpa_s, bss->bssid);
7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (e) {
7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int limit = 1;
77404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_supplicant_enabled_networks(wpa_s) == 1) {
7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * When only a single network is enabled, we can
7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * trigger blacklisting on the first failure. This
7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * should not be done with multiple enabled networks to
7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * avoid getting forced to move into a worse ESS on
7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * single error if there are no other BSSes of the
7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * current ESS.
7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			limit = 0;
7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (e->count > limit) {
7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - blacklisted "
7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"(count=%d limit=%d)", e->count, limit);
7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return NULL;
7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
7929bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (bss->ssid_len == 0) {
7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   skip - SSID not known");
7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return NULL;
7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
797d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (disallowed_bssid(wpa_s, bss->bssid)) {
798d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   skip - BSSID disallowed");
799d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return NULL;
800d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
801d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
802d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
803d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   skip - SSID disallowed");
804d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return NULL;
805d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
806d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa = wpa_ie_len > 0 || rsn_ie_len > 0;
8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
809f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int check_ssid = wpa ? 1 : (ssid->ssid_len != 0);
81161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		int res;
8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
81304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpas_network_disabled(wpa_s, ssid)) {
8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - disabled");
8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
81861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		res = wpas_temp_disabled(wpa_s, ssid);
81961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (res > 0) {
82061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - disabled "
82161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"temporarily for %d second(s)", res);
82261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			continue;
82361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
82461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) {
8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - blacklisted "
8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"(WPS)");
8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa && ssid->ssid_len == 0 &&
8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			check_ssid = 0;
8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/* Only allow wildcard SSID match if an AP
8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * advertises active WPS operation that matches
8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * with our mode. */
8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			check_ssid = 1;
8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ssid->ssid_len == 0 &&
8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				check_ssid = 0;
8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (ssid->bssid_set && ssid->ssid_len == 0 &&
8481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0)
8491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			check_ssid = 0;
8501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (check_ssid &&
8529bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		    (bss->ssid_len != ssid->ssid_len ||
8539bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		     os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) {
8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - SSID mismatch");
8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid->bssid_set &&
8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - BSSID mismatch");
8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
867f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (!osen && !wpa &&
8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) {
8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - non-WPA network "
8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"not allowed");
8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
876b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
877b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		    has_wep_key(ssid)) {
878b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - ignore WPA/WPA2 AP for WEP network block");
879b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt			continue;
880b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		}
881b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt
882f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) {
883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - non-OSEN network "
884f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				"not allowed");
885f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			continue;
886f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		}
887f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
88875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (!wpa_supplicant_match_privacy(bss, ssid)) {
8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - privacy "
8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"mismatch");
8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
894f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (!bss_is_ess(bss)) {
895f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - not ESS network");
8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!freq_allowed(ssid->freq_list, bss->freq)) {
9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - frequency not "
9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"allowed");
9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!rate_match(wpa_s, bss)) {
9061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - rate sets do "
9071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"not match");
9081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			continue;
9091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
9101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
9129657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		if (ssid->p2p_group &&
9139657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		    !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
9149657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		    !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
9159657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - no P2P IE seen");
9169657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt			continue;
9179657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt		}
9189657139ca0bbea9a84e0a3c7e9438d1f53c9ed24Dmitry Shmidt
9195460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) {
9205460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			struct wpabuf *p2p_ie;
9215460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			u8 dev_addr[ETH_ALEN];
9225460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
9235460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
9245460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			if (ie == NULL) {
9255460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "   skip - no P2P element");
9265460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				continue;
9275460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			}
9285460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			p2p_ie = wpa_bss_get_vendor_ie_multi(
9295460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				bss, P2P_IE_VENDOR_TYPE);
9305460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			if (p2p_ie == NULL) {
9315460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "   skip - could not fetch P2P element");
9325460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				continue;
9335460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			}
9345460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
9355460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0
9365460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			    || os_memcmp(dev_addr, ssid->go_p2p_dev_addr,
9375460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt					 ETH_ALEN) != 0) {
9385460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "   skip - no matching GO P2P Device Address in P2P element");
9395460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				wpabuf_free(p2p_ie);
9405460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt				continue;
9415460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			}
9425460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt			wpabuf_free(p2p_ie);
9435460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt		}
9445460547a121207cf7a99eac45e05fcdd83be3161Dmitry Shmidt
9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * TODO: skip the AP if its P2P IE has Group Formation
9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * bit set in the P2P Group Capability Bitmap and we
9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * are not in Group Formation with that device.
9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Matching configuration found */
9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return ssid;
9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* No matching configuration found */
9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_bss *
9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  struct wpa_ssid *group,
964f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			  struct wpa_ssid **selected_ssid,
965f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			  int only_first_ssid)
9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9679bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	unsigned int i;
9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
969f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (only_first_ssid)
970f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d",
971f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			group->id);
972f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	else
973f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d",
974f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			group->priority);
9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9769bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	for (i = 0; i < wpa_s->last_scan_res_used; i++) {
9779bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		struct wpa_bss *bss = wpa_s->last_scan_res[i];
978f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group,
979f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt						    only_first_ssid);
9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!*selected_ssid)
9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "   selected BSS " MACSTR
9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" ssid='%s'",
9849bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt			MAC2STR(bss->bssid),
9859bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt			wpa_ssid_txt(bss->ssid, bss->ssid_len));
9869bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		return bss;
9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
993444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidtstruct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
994444d567b27731d8572ef37697dd12fd1c37c2f24Dmitry Shmidt					     struct wpa_ssid **selected_ssid)
9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_bss *selected = NULL;
9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prio;
9984582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt	struct wpa_ssid *next_ssid = NULL;
9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10009bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (wpa_s->last_scan_res == NULL ||
10019bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	    wpa_s->last_scan_res_used == 0)
10029bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		return NULL; /* no scan results from last update */
10039bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
10044582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt	if (wpa_s->next_ssid) {
10054582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		struct wpa_ssid *ssid;
1006f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
10074582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		/* check that next_ssid is still valid */
10084582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
10094582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			if (ssid == wpa_s->next_ssid)
10104582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt				break;
10114582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		}
10124582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		next_ssid = ssid;
10134582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		wpa_s->next_ssid = NULL;
10144582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt	}
1015f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
10164582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt	while (selected == NULL) {
10174582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt		for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
10184582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			if (next_ssid && next_ssid->priority ==
10194582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt			    wpa_s->conf->pssid[prio]->priority) {
1020f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				selected = wpa_supplicant_select_bss(
10214582d2a5dd8180c52eb95b1100fb183b9a289708Dmitry Shmidt					wpa_s, next_ssid, selected_ssid, 1);
1022f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				if (selected)
1023f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt					break;
1024f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			}
10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			selected = wpa_supplicant_select_bss(
10269bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt				wpa_s, wpa_s->conf->pssid[prio],
1027f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				selected_ssid, 0);
10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (selected)
10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (selected == NULL && wpa_s->blacklist &&
10331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    !wpa_s->countermeasures) {
10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear "
10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"blacklist and try again");
10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_blacklist_clear(wpa_s);
10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->blacklist_cleared++;
10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else if (selected == NULL)
10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return selected;
10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					int timeout_sec, int timeout_usec)
10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
104904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (!wpa_supplicant_enabled_networks(wpa_s)) {
10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * No networks are enabled; short-circuit request so
10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * we don't wait timeout seconds before transitioning
10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to INACTIVE state.
10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1055aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request "
1056aa532510a7b8c4da2d7d6e2c11dda5db840894e4Dmitry Shmidt			"since there are no enabled networks");
10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1060d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1061d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpa_s->scan_for_connection = 1;
10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec);
10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
106644da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidtint wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
10671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   struct wpa_bss *selected,
10681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   struct wpa_ssid *ssid)
10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"PBC session overlap");
10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
1074df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT ||
1075df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		    wpa_s->p2p_in_provisioning) {
1076df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt			eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb,
1077df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt					       wpa_s, NULL);
107844da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt			return -1;
1079df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt		}
10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS
10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_wps_cancel(wpa_s);
10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS */
108544da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt		return -1;
10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	wpa_msg(wpa_s, MSG_DEBUG,
1089f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		"Considering connect request: reassociate: %d  selected: "
1090f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		MACSTR "  bssid: " MACSTR "  pending: " MACSTR
1091f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		"  wpa_state: %s  ssid=%p  current_ssid=%p",
1092f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		wpa_s->reassociate, MAC2STR(selected->bssid),
1093f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1094f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		wpa_supplicant_state_txt(wpa_s->wpa_state),
1095f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		ssid, wpa_s->current_ssid);
1096f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt
10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Do not trigger new association unless the BSSID has changed or if
10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * reassociation is requested. If we are in process of associating with
11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * the selected BSSID, do not trigger new attempt.
11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
11021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->reassociate ||
11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     ((wpa_s->wpa_state != WPA_ASSOCIATING &&
11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	       wpa_s->wpa_state != WPA_AUTHENTICATING) ||
1106f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	      (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1107f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	       os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
1108f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	       0) ||
1109f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	      (is_zero_ether_addr(wpa_s->pending_bssid) &&
1110f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt	       ssid != wpa_s->current_ssid)))) {
11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_scard_init(wpa_s, ssid)) {
11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_req_new_scan(wpa_s, 10, 0);
111344da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt			return 0;
11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1115f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR,
1116f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			MAC2STR(selected->bssid));
11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_associate(wpa_s, selected, ssid);
11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1119f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Already associated or trying to "
1120f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt			"connect with the selected AP");
11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
112344da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt	return 0;
11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpa_ssid *
11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int prio;
11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (ssid = wpa_s->conf->pssid[prio]; ssid; ssid = ssid->pnext)
11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		{
113604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (wpas_network_disabled(wpa_s, ssid))
11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				continue;
11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (ssid->mode == IEEE80211_MODE_IBSS ||
11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    ssid->mode == IEEE80211_MODE_AP)
11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return ssid;
11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return NULL;
11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: move the rsn_preauth_scan_result*() to be called from notify.c based
11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * on BSS added and BSS changed events */
11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_rsn_preauth_scan_results(
115087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	struct wpa_supplicant *wpa_s)
11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
115287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	struct wpa_bss *bss;
11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (rsn_preauth_scan_results(wpa_s->wpa) < 0)
11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
115787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		const u8 *ssid, *rsn;
11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
116087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen		ssid = wpa_bss_get_ie(bss, WLAN_EID_SSID);
11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid == NULL)
11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
116487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen		rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (rsn == NULL)
11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
116887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen		rsn_preauth_scan_result(wpa_s->wpa, bss->bssid, ssid, rsn);
11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       struct wpa_bss *selected,
11769bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt				       struct wpa_ssid *ssid)
11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
11789bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	struct wpa_bss *current_bss = NULL;
11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int min_diff;
11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->reassociate)
11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* explicit request to reassociate */
11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state < WPA_ASSOCIATED)
11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* we are not associated; continue */
11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid == NULL)
11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* unknown current SSID */
11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid != ssid)
11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* different network block */
11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
11901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpas_driver_bss_selection(wpa_s))
11911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return 0; /* Driver-based roaming */
11921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
11939bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (wpa_s->current_ssid->ssid)
11949bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		current_bss = wpa_bss_get(wpa_s, wpa_s->bssid,
11959bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt					  wpa_s->current_ssid->ssid,
11969bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt					  wpa_s->current_ssid->ssid_len);
11979bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (!current_bss)
11989bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!current_bss)
12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* current BSS not seen in scan results */
12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12039bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (current_bss == selected)
12049bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		return 0;
12059bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
12069bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	if (selected->last_update_idx > current_bss->last_update_idx)
12079bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		return 1; /* current BSS not seen in the last scan */
12089bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
12099e07767d5d76159ef38a241da00eb0d9f3bc6420Dmitry Shmidt#ifndef CONFIG_NO_ROAMING
12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR " level=%d",
12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(current_bss->bssid), current_bss->level);
12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR " level=%d",
12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(selected->bssid), selected->level);
12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid->bssid_set &&
12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) ==
12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    0) {
12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS "
12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"has preferred BSSID");
12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1224d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (current_bss->level < 0 && current_bss->level > selected->level) {
1225d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
1226d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			"signal level");
1227d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0;
1228d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
1229d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	min_diff = 2;
12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (current_bss->level < 0) {
12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (current_bss->level < -85)
12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			min_diff = 1;
12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (current_bss->level < -80)
12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			min_diff = 2;
12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (current_bss->level < -75)
12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			min_diff = 3;
12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else if (current_bss->level < -70)
12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			min_diff = 4;
12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			min_diff = 5;
12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (abs(current_bss->level - selected->level) < min_diff) {
12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"in signal level");
12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
125004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#else /* CONFIG_NO_ROAMING */
1251efdec2efdda2f534d84b32f2737ca3d8a00fdf02Dmitry Shmidt	return 0;
125204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_NO_ROAMING */
12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1255c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
125689ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen/* Return != 0 if no scan results could be fetched or if scan results should not
125704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * be shared with other virtual interfaces. */
1258f6c92c4dd33d21c040e51bcb30beac24173a62b9Dmitry Shmidtstatic int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
125937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt					      union wpa_event_data *data,
126037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt					      int own_request)
12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1262fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct wpa_scan_results *scan_res = NULL;
1263fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	int ret = 0;
12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ap = 0;
12654530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#ifndef CONFIG_NO_RANDOM_POOL
12664530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt	size_t i, num;
12674530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt#endif /* CONFIG_NO_RANDOM_POOL */
12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface)
12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap = 1;
12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_notify_scanning(wpa_s, 0);
12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	scan_res = wpa_supplicant_get_scan_results(wpa_s,
12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   data ? &data->scan_info :
12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   NULL, 1);
12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (scan_res == NULL) {
12804b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		if (wpa_s->conf->ap_scan == 2 || ap ||
12814b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		    wpa_s->scan_res_handler == scan_only_handler)
12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
128337d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt		if (!own_request)
128437d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt			return -1;
12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"scanning again");
12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_new_scan(wpa_s, 1, 0);
1288fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		ret = -1;
1289fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_RANDOM_POOL
12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	num = scan_res->num;
12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (num > 10)
12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		num = 10;
12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num; i++) {
12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 buf[5];
12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_scan_res *res = scan_res->res[i];
12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[0] = res->bssid[5];
13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[1] = res->qual & 0xff;
13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[2] = res->noise & 0xff;
13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[3] = res->level & 0xff;
13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[4] = res->tsf & 0xff;
13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_add_randomness(buf, sizeof(buf));
13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_RANDOM_POOL */
13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1308fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (own_request && wpa_s->scan_res_handler &&
1309fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    (wpa_s->own_scan_running || !wpa_s->external_scan_running)) {
13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 struct wpa_scan_results *scan_res);
13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scan_res_handler = wpa_s->scan_res_handler;
13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->scan_res_handler = NULL;
13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		scan_res_handler(wpa_s, scan_res);
1316fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		ret = -2;
1317fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ap) {
13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode");
13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface->scan_cb)
13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
1326fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
132837d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
1329fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
1330fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->own_scan_running, wpa_s->external_scan_running);
1331fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
1332fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    wpa_s->manual_scan_use_id && wpa_s->own_scan_running) {
1333fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u",
1334fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			     wpa_s->manual_scan_id);
1335fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->manual_scan_use_id = 0;
1336fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	} else {
1337fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
1338fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
133904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_notify_scan_results(wpa_s);
13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpas_notify_scan_done(wpa_s, 1);
13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1343fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (!wpa_s->own_scan_running && wpa_s->external_scan_running) {
1344fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection");
134504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_scan_results_free(scan_res);
134604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return 0;
134704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
134804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1349fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (sme_proc_obss_scan(wpa_s) > 0)
1350fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1352fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
1353fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
1354fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1355fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (autoscan_notify_scan(wpa_s, scan_res))
1356fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
135704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->disconnected) {
13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1360fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (!wpas_driver_bss_selection(wpa_s) &&
1364fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    bgscan_notify_scan(wpa_s, scan_res) == 1)
1365fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		goto scan_work_done;
13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
136761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_wps_update_ap_info(wpa_s, scan_res);
136861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13699bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	wpa_scan_results_free(scan_res);
13709bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
1371fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (wpa_s->scan_work) {
1372fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		struct wpa_radio_work *work = wpa_s->scan_work;
1373fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->scan_work = NULL;
1374fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		radio_work_done(work);
1375fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
1376fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1377e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	return wpas_select_network_from_last_scan(wpa_s, 1, own_request);
1378fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
1379fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtscan_work_done:
1380fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_scan_results_free(scan_res);
1381fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (wpa_s->scan_work) {
1382fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		struct wpa_radio_work *work = wpa_s->scan_work;
1383fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->scan_work = NULL;
1384fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		radio_work_done(work);
1385fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
1386fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	return ret;
13879bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt}
13889bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
13899bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
13908da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidtstatic int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
1391e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt					      int new_scan, int own_request)
13929bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt{
13939bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	struct wpa_bss *selected;
13949bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	struct wpa_ssid *ssid = NULL;
13959bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt
13969bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt	selected = wpa_supplicant_pick_network(wpa_s, &ssid);
13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (selected) {
13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		int skip;
14009bce59c7fef20e34a05f04d1e33a4076083dca0cDmitry Shmidt		skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
14011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (skip) {
14028da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (new_scan)
14038da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				wpa_supplicant_rsn_preauth_scan_results(wpa_s);
14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 0;
14051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
14061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
140744da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt		if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) {
14081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed");
140944da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt			return -1;
141044da0253a740e0329b18f60c196e1f2dcacfcceaDmitry Shmidt		}
14118da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt		if (new_scan)
14128da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			wpa_supplicant_rsn_preauth_scan_results(wpa_s);
141389ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		/*
141489ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 * Do not notify other virtual radios of scan results since we do not
141589ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 * want them to start other associations at the same time.
141689ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 */
141789ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		return 1;
14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ssid = wpa_supplicant_pick_new_network(wpa_s);
14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ssid) {
14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Setup a new network");
14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_associate(wpa_s, NULL, ssid);
14248da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt			if (new_scan)
14258da800a193fb6f8832218715f82a7b4e2d2ad338Dmitry Shmidt				wpa_supplicant_rsn_preauth_scan_results(wpa_s);
1426e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt		} else if (own_request) {
1427e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			/*
1428e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			 * No SSID found. If SCAN results are as a result of
1429e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			 * own scan request and not due to a scan request on
1430e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			 * another shared interface, try another scan.
1431e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt			 */
14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int timeout_sec = wpa_s->scan_interval;
14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int timeout_usec = 0;
14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
143504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (wpas_p2p_scan_no_go_seen(wpa_s) == 1)
143604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				return 0;
143704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1438fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt			if (wpa_s->p2p_in_provisioning ||
143915907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt			    wpa_s->show_group_started ||
144015907098d1f67c24bb000e593e279af173cf57d7Dmitry Shmidt			    wpa_s->p2p_in_invitation) {
14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				/*
14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 * Use shorter wait during P2P Provisioning
1443fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt				 * state and during P2P join-a-group operation
1444fa3fc4a1ac08ad14272301c7f6f01b362997c3e4Dmitry Shmidt				 * to speed up group formation.
14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 */
14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				timeout_sec = 0;
14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				timeout_usec = 250000;
14481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
14491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt							    timeout_usec);
14501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				return 0;
14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
145361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_INTERWORKING
145461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (wpa_s->conf->auto_interworking &&
145561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    wpa_s->conf->interworking &&
145661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			    wpa_s->conf->cred) {
145761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: "
145861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					"start ANQP fetch since no matching "
145961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					"networks found");
146061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wpa_s->network_select = 1;
146161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				wpa_s->auto_network_select = 1;
146261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				interworking_start_fetch_anqp(wpa_s);
146389ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen				return 1;
146461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
146561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_INTERWORKING */
1466fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_WPS
1467fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (wpa_s->after_wps > 0 || wpas_wps_searching(wpa_s)) {
1468fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				wpa_dbg(wpa_s, MSG_DEBUG, "Use shorter wait during WPS processing");
1469fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				timeout_sec = 0;
1470fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				timeout_usec = 500000;
1471fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
1472fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt							    timeout_usec);
1473fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				return 0;
1474fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
1475fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_WPS */
14761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (wpa_supplicant_req_sched_scan(wpa_s))
14771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
14781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt							    timeout_usec);
14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      union wpa_event_data *data)
14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *ifs;
148937d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt
149037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt	if (_wpa_supplicant_event_scan_results(wpa_s, data, 1) != 0) {
14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * If no scan results could be fetched, then no need to
14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * notify those interfaces that did not actually request
149489ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 * this scan. Similarly, if scan results started a new operation on this
149589ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 * interface, do not notify other interfaces to avoid concurrent
149689ca702e8ed3247d7007dbdebe531036671c34afJouni Malinen		 * operations during a connection attempt.
14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
150201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	 * Check other interfaces to see if they share the same radio. If
15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so, they get updated with this same scan info.
15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
150501904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
150601904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 radio_list) {
150701904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		if (ifs != wpa_s) {
15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "%s: Updating scan results from "
15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "sibling", ifs->ifname);
151037d4d6a4efea4ef4f864347ac8ed8d62a9e19f90Dmitry Shmidt			_wpa_supplicant_event_scan_results(ifs, data, 0);
15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_SCAN_PROCESSING */
15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
15184b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidtint wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
15194b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt{
15204b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#ifdef CONFIG_NO_SCAN_PROCESSING
15214b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	return -1;
15224b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#else /* CONFIG_NO_SCAN_PROCESSING */
1523fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
15244b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
15254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	if (wpa_s->last_scan_res_used <= 0)
15264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		return -1;
15274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
1528fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
1529fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (os_reltime_expired(&now, &wpa_s->last_scan, 5)) {
15304b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
15314b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		return -1;
15324b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt	}
15334b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
1534e0e48dc666fb14a7bb60264ca87463ba7bc1fe0bDmitry Shmidt	return wpas_select_network_from_last_scan(wpa_s, 0, 1);
15354b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt#endif /* CONFIG_NO_SCAN_PROCESSING */
15364b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt}
15374b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt
153804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WNM
153904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
154004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wnm_bss_keep_alive(void *eloop_ctx, void *sock_ctx)
154104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
154204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
154304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
154404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->wpa_state < WPA_ASSOCIATED)
154504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
154604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1547a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (!wpa_s->no_keep_alive) {
1548a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WNM: Send keep-alive to AP " MACSTR,
1549a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			   MAC2STR(wpa_s->bssid));
1550a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/* TODO: could skip this if normal data traffic has been sent */
1551a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		/* TODO: Consider using some more appropriate data frame for
1552a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		 * this */
1553a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		if (wpa_s->l2)
1554a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			l2_packet_send(wpa_s->l2, wpa_s->bssid, 0x0800,
1555a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt				       (u8 *) "", 0);
1556a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
155704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
155804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_SME
155904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (wpa_s->sme.bss_max_idle_period) {
156004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int msec;
156104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		msec = wpa_s->sme.bss_max_idle_period * 1024; /* times 1000 */
156204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (msec > 100)
156304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			msec -= 100;
156404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
156504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       wnm_bss_keep_alive, wpa_s, NULL);
156604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
156704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_SME */
156804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
156904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
157004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
157104949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void wnm_process_assoc_resp(struct wpa_supplicant *wpa_s,
157204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				   const u8 *ies, size_t ies_len)
157304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
157404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	struct ieee802_11_elems elems;
157504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
157604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ies == NULL)
157704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
157804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
157904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
158004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		return;
158104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
158204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_SME
158304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (elems.bss_max_idle_period) {
158404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		unsigned int msec;
158504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->sme.bss_max_idle_period =
158604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			WPA_GET_LE16(elems.bss_max_idle_period);
158704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_printf(MSG_DEBUG, "WNM: BSS Max Idle Period: %u (* 1000 "
158804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   "TU)%s", wpa_s->sme.bss_max_idle_period,
158904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   (elems.bss_max_idle_period[2] & 0x01) ?
159004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			   " (protected keep-live required)" : "");
159104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_s->sme.bss_max_idle_period == 0)
159204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_s->sme.bss_max_idle_period = 1;
159304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
159404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
159504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			 /* msec times 1000 */
159604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			msec = wpa_s->sme.bss_max_idle_period * 1024;
159704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			if (msec > 100)
159804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				msec -= 100;
159904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
160004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					       wnm_bss_keep_alive, wpa_s,
160104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					       NULL);
160204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
160304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
160404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_SME */
160504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
160604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
160704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WNM */
160804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
160904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
161004949598a23f501be6eec21697465fd46a28840aDmitry Shmidtvoid wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
161104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
161204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WNM
161304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
161404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WNM */
161504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
161604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
161704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
1618051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_INTERWORKING
1619051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1620051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
1621051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			    size_t len)
1622051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1623051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	int res;
1624051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1625051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "Interworking: QoS Map Set", qos_map, len);
1626051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	res = wpa_drv_set_qos_map(wpa_s, qos_map, len);
1627051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (res) {
1628051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Interworking: Failed to configure QoS Map Set to the driver");
1629051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1630051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1631051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	return res;
1632051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1633051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1634051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1635051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
1636051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt					    const u8 *ies, size_t ies_len)
1637051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{
1638051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	struct ieee802_11_elems elems;
1639051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1640051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ies == NULL)
1641051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
1642051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1643051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
1644051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		return;
1645051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1646051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (elems.qos_map_set) {
1647051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		wpas_qos_map_set(wpa_s, elems.qos_map_set,
1648051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt				 elems.qos_map_set_len);
1649051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
1650051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt}
1651051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1652051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_INTERWORKING */
1653051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
1654051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					  union wpa_event_data *data)
16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int l, len, found = 0, wpa_found, rsn_found;
16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *p;
1660700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#ifdef CONFIG_IEEE80211R
1661700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	u8 bssid[ETH_ALEN];
1662700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->assoc_info.req_ies)
16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies,
16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->assoc_info.req_ies_len);
16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->assoc_info.resp_ies) {
16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies,
16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->assoc_info.resp_ies_len);
16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies,
16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->assoc_info.resp_ies_len);
16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
167504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#ifdef CONFIG_WNM
167604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
167704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				       data->assoc_info.resp_ies_len);
167804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#endif /* CONFIG_WNM */
1679051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_INTERWORKING
1680051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
1681051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt						data->assoc_info.resp_ies_len);
1682051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_INTERWORKING */
16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->assoc_info.beacon_ies)
16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "beacon_ies",
16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->assoc_info.beacon_ies,
16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->assoc_info.beacon_ies_len);
16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data->assoc_info.freq)
16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz",
16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->assoc_info.freq);
16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->assoc_info.req_ies;
16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	l = data->assoc_info.req_ies_len;
16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Go through the IEs and make a copy of the WPA/RSN IE, if present. */
16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p && l >= 2) {
16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = p[1] + 2;
16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > l) {
16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    p, l);
17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		     (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    (p[0] == WLAN_EID_RSN && p[1] >= 2)) {
17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			found = 1;
17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_find_assoc_pmkid(wpa_s);
17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l -= len;
17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p += len;
17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!found && data->assoc_info.req_ies)
17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SME
17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    wpa_ft_validate_reassoc_resp(wpa_s->wpa,
17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->assoc_info.resp_ies,
17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 data->assoc_info.resp_ies_len,
17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 bssid) < 0) {
17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"Reassociation Response failed");
17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_deauthenticate(
17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, WLAN_REASON_INVALID_IE);
17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->assoc_info.resp_ies;
17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	l = data->assoc_info.resp_ies_len;
17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_WPS_STRICT
17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (p && wpa_s->current_ssid &&
17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpabuf *wps;
17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wps = ieee802_11_vendor_ie_concat(p, l, WPS_IE_VENDOR_TYPE);
17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wps == NULL) {
17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(wpa_s, MSG_INFO, "WPS-STRICT: AP did not "
17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"include WPS IE in (Re)Association Response");
17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wps_validate_assoc_resp(wps) < 0) {
17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(wps);
17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_deauthenticate(
17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, WLAN_REASON_INVALID_IE);
17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wps);
17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Go through the IEs and make a copy of the MDIE, if present. */
17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p && l >= 2) {
17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = p[1] + 2;
17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > l) {
17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    p, l);
17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (p[0] == WLAN_EID_MOBILITY_DOMAIN &&
17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p[1] >= MOBILITY_DOMAIN_ID_LEN) {
17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->sme.ft_used = 1;
17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(wpa_s->sme.mobility_domain, p + 2,
17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  MOBILITY_DOMAIN_ID_LEN);
17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l -= len;
17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p += len;
17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SME */
17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1778700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	/* Process FT when SME is in the driver */
1779700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1780700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	    wpa_ft_is_completed(wpa_s->wpa)) {
1781700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
1782700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		    wpa_ft_validate_reassoc_resp(wpa_s->wpa,
1783700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt						 data->assoc_info.resp_ies,
1784700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt						 data->assoc_info.resp_ies_len,
1785700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt						 bssid) < 0) {
1786700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
1787700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				"Reassociation Response failed");
1788700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			wpa_supplicant_deauthenticate(
1789700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt				wpa_s, WLAN_REASON_INVALID_IE);
1790700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt			return -1;
1791700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		}
1792700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done");
1793700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt	}
1794700a137ab366edc72e371da68ba187b4717ee660Dmitry Shmidt
17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies,
17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     data->assoc_info.resp_ies_len);
17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* WPA/RSN IE from Beacon/ProbeResp */
18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	p = data->assoc_info.beacon_ies;
18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	l = data->assoc_info.beacon_ies_len;
18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Go through the IEs and make a copy of the WPA/RSN IEs, if present.
18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_found = rsn_found = 0;
18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (p && l >= 2) {
18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		len = p[1] + 2;
18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (len > l) {
18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies",
18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    p, l);
18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa_found &&
18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_found = 1;
18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!rsn_found &&
18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    p[0] == WLAN_EID_RSN && p[1] >= 2) {
18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			rsn_found = 1;
18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l -= len;
18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		p += len;
18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_found && data->assoc_info.beacon_ies)
18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!rsn_found && data->assoc_info.beacon_ies)
18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_found || rsn_found)
18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->ap_ies_from_associnfo = 1;
18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
183787fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	if (wpa_s->assoc_freq && data->assoc_info.freq &&
183887fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	    wpa_s->assoc_freq != data->assoc_info.freq) {
183987fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen		wpa_printf(MSG_DEBUG, "Operating frequency changed from "
184087fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen			   "%u to %u MHz",
184187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen			   wpa_s->assoc_freq, data->assoc_info.freq);
184287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen		wpa_supplicant_update_scan_results(wpa_s);
184387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen	}
184487fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen
18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->assoc_freq = data->assoc_info.freq;
18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1851c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidtstatic int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
1852c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt{
1853c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	const u8 *bss_wpa = NULL, *bss_rsn = NULL;
1854c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1855c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (!wpa_s->current_bss || !wpa_s->current_ssid)
1856c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1857c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1858c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt))
1859c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return 0;
1860c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1861c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1862c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					WPA_IE_VENDOR_TYPE);
1863c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
1864c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1865c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1866c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1867c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	    wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1868c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				 bss_rsn ? 2 + bss_rsn[1] : 0))
1869c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		return -1;
1870c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1871c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt	return 0;
1872c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt}
1873c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
1874c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       union wpa_event_data *data)
18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 bssid[ETH_ALEN];
18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ft_completed;
18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->ap_iface) {
188309f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt		if (!data)
188409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt			return;
18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_notif_assoc(wpa_s->ap_iface->bss[0],
18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->assoc_info.addr,
18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->assoc_info.req_ies,
18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->assoc_info.req_ies_len,
18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->assoc_info.reassoc);
18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ft_completed = wpa_ft_is_completed(wpa_s->wpa);
18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
189861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
189961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID");
1900d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		wpa_supplicant_deauthenticate(
190161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_s, WLAN_REASON_DEAUTH_LEAVING);
190261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
190361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
190461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
190661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(bssid));
19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_add_randomness(bssid, ETH_ALEN);
19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
191261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpas_notify_bssid_changed(wpa_s);
19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) {
19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_clear_keys(wpa_s, bssid);
19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_select_config(wpa_s) < 0) {
1918d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_supplicant_deauthenticate(
19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1922c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt
19231e1c48d2b342d4945d600ddb650bd2925822d1bbDmitry Shmidt#ifdef ANDROID
19241e1c48d2b342d4945d600ddb650bd2925822d1bbDmitry Shmidt		if (wpa_s->conf->ap_scan == 1) {
19251e1c48d2b342d4945d600ddb650bd2925822d1bbDmitry Shmidt#else
1926c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		if (wpa_s->conf->ap_scan == 1 &&
1927c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) {
19281e1c48d2b342d4945d600ddb650bd2925822d1bbDmitry Shmidt#endif
1929c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			if (wpa_supplicant_assoc_update_ie(wpa_s) < 0)
1930c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt				wpa_msg(wpa_s, MSG_WARNING,
1931c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					"WPA/RSN IEs not updated");
1932c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		}
19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SME
19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->sme.prev_bssid_set = 1;
19380c08fdcf5231617f2340cb18e45769a8ed3a1dc4Dmitry Shmidt	wpa_s->sme.last_unprot_disconnect.sec = 0;
19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SME */
19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid));
19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid) {
19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* When using scanning (ap_scan=1), SIM PC/SC interface can be
19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * initialized before association, but for other modes,
19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * initialize PC/SC here, if the current configuration needs
19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * smartcard or SIM/USIM. */
19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid);
19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_notify_assoc(wpa_s->wpa, bssid);
19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->l2)
19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l2_packet_notify_auth_start(wpa_s->l2);
19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Set portEnabled first to FALSE in order to get EAP state machine out
19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE
19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * state machine may transit to AUTHENTICATING state based on obsolete
19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to
19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * AUTHENTICATED without ever giving chance to EAP state machine to
19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * reset the state.
19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!ft_completed) {
19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed)
19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* 802.1X::portControl = Auto */
19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->eapol_received = 0;
19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    (wpa_s->current_ssid &&
19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
197409f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt		if (wpa_s->current_ssid &&
197509f57babfc1e4473db20ced4f58a4c9f082c8ed8Dmitry Shmidt		    wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
197651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		    (wpa_s->drv_flags &
197751b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		     WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
197851b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			/*
197951b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			 * Set the key after having received joined-IBSS event
198051b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			 * from the driver.
198151b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			 */
198251b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt			wpa_supplicant_set_wpa_none_key(wpa_s,
198351b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt							wpa_s->current_ssid);
198451b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt		}
19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_cancel_auth_timeout(wpa_s);
19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (!ft_completed) {
19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Timeout for receiving the first EAPOL packet */
19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_cancel_scan(wpa_s);
19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * We are done; the driver will take care of RSN 4-way
19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * handshake.
19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_cancel_auth_timeout(wpa_s);
20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * The driver will take care of RSN 4-way handshake, so we need
20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to allow EAPOL supplicant to complete its work without
20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * waiting for WPA supplicant.
20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (ft_completed) {
20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * FT protocol completed - make sure EAPOL state machine ends
20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * up in authenticated.
20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_cancel_auth_timeout(wpa_s);
20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2022a05074ca1abe62b3fd8a8c30a5558e044b1356d5Jouni Malinen	wpa_s->last_eapol_matches_bssid = 0;
2023a05074ca1abe62b3fd8a8c30a5558e044b1356d5Jouni Malinen
20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->pending_eapol_rx) {
2025fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		struct os_reltime now, age;
2026fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&now);
2027fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (age.sec == 0 && age.usec < 100000 &&
20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    0) {
20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"frame that was received just before "
20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"association notification");
20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_rx_eapol(
20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, wpa_s->pending_eapol_rx_src,
20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_head(wpa_s->pending_eapol_rx),
20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpabuf_len(wpa_s->pending_eapol_rx));
20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(wpa_s->pending_eapol_rx);
20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->pending_eapol_rx = NULL;
20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	     wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
204551b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	    wpa_s->current_ssid &&
204651b6ea882f234c14cd1fe1332a3840cf61fafccaDmitry Shmidt	    (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Set static WEP keys again */
20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IBSS_RSN
20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->current_ssid &&
20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->current_ssid->mode == WPAS_MODE_IBSS &&
20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE &&
20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->ibss_rsn == NULL) {
20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa_s->ibss_rsn) {
20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN");
20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_deauthenticate(
20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, WLAN_REASON_DEAUTH_LEAVING);
20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return;
20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ibss_rsn_set_psk(wpa_s->ibss_rsn, wpa_s->current_ssid->psk);
20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IBSS_RSN */
206861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
206961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_wps_notify_assoc(wpa_s, bssid);
20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic int disconnect_reason_recoverable(u16 reason_code)
20741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
20751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY ||
20761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA ||
20771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
20781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
20791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
2082c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  u16 reason_code,
2083c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt					  int locally_generated)
20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *bssid;
20862b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
20872b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
20882b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		/*
20892b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		 * At least Host AP driver and a Prism3 card seemed to be
20902b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		 * generating streams of disconnected events when configuring
20912b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		 * IBSS for WPA-None. Ignore them for now.
20922b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		 */
20932b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		return;
20942b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	}
20952b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
20962b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	bssid = wpa_s->bssid;
20972b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	if (is_zero_ether_addr(bssid))
20982b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		bssid = wpa_s->pending_bssid;
20992b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
21002b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	if (!is_zero_ether_addr(bssid) ||
21012b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	    wpa_s->wpa_state >= WPA_AUTHENTICATING) {
21022b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
21032b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			" reason=%d%s",
21042b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			MAC2STR(bssid), reason_code,
21052b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen			locally_generated ? " locally_generated=1" : "");
21062b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	}
21072b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen}
21082b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
21092b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen
2110d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtstatic int could_be_psk_mismatch(struct wpa_supplicant *wpa_s, u16 reason_code,
2111d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				 int locally_generated)
2112d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt{
2113d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE ||
2114d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	    !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
2115d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		return 0; /* Not in 4-way handshake with PSK */
2116d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2117d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	/*
2118d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * It looks like connection was lost while trying to go through PSK
2119d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * 4-way handshake. Filter out known disconnection cases that are caused
2120d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 * by something else than PSK mismatch to avoid confusing reports.
2121d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	 */
2122d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2123d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (locally_generated) {
2124d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (reason_code == WLAN_REASON_IE_IN_4WAY_DIFFERS)
2125d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return 0;
2126d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	}
2127d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2128d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return 1;
2129d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt}
2130d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
2131d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
21322b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinenstatic void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
21332b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen						 u16 reason_code,
21342b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen						 int locally_generated)
21352b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen{
21362b89da85b8cfe9bb862e8dd334855263c3522c00Jouni Malinen	const u8 *bssid;
21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int authenticating;
21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 prev_pending_bssid[ETH_ALEN];
21391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_bss *fast_reconnect = NULL;
21401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	struct wpa_ssid *fast_reconnect_ssid = NULL;
2141f8a26a8e6e081a2c576568198d0bcb4f976258acJouni Malinen	struct wpa_ssid *last_ssid;
21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * At least Host AP driver and a Prism3 card seemed to be
21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * generating streams of disconnected events when configuring
21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * IBSS for WPA-None. Ignore them for now.
21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - ignore in "
21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"IBSS/WPA-None mode");
21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2157d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) {
21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"pre-shared key may be incorrect");
2160391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (wpas_p2p_4way_hs_failed(wpa_s) > 0)
2161391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			return; /* P2P group removed */
21626dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt		wpas_auth_failed(wpa_s, "WRONG_KEY");
21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2164ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	if (!wpa_s->disconnected &&
2165ea69e84a6f4455c59348485895d3d5e3af77a65bDmitry Shmidt	    (!wpa_s->auto_reconnect_disabled ||
2166661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	     wpa_s->key_mgmt == WPA_KEY_MGMT_WPS ||
2167661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	     wpas_wps_searching(wpa_s))) {
21681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
2169661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			"reconnect (wps=%d/%d wpa_state=%d)",
21701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
2171661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			wpas_wps_searching(wpa_s),
21721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s->wpa_state);
21731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_s->wpa_state == WPA_COMPLETED &&
21741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_s->current_ssid &&
21751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
2176c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		    !locally_generated &&
21771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    disconnect_reason_recoverable(reason_code)) {
21781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/*
21791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * It looks like the AP has dropped association with
21801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * us, but could allow us to get back in. Try to
21811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * reconnect to the same BSS without full scan to save
21821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 * time for some common cases.
21831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			 */
21841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			fast_reconnect = wpa_s->current_bss;
21851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			fast_reconnect_ssid = wpa_s->current_ssid;
21861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		} else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
2187c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt			wpa_supplicant_req_scan(wpa_s, 0, 100000);
21881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
21891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
21901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				"immediate scan");
21918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
21921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
21938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"try to re-connect");
21948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->reassociate = 0;
21958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->disconnected = 1;
2196c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt		wpa_supplicant_cancel_sched_scan(wpa_s);
21978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
21988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	bssid = wpa_s->bssid;
21998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (is_zero_ether_addr(bssid))
22008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bssid = wpa_s->pending_bssid;
22011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
22021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpas_connection_failed(wpa_s, bssid);
22038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_notify_disassoc(wpa_s->wpa);
220404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (locally_generated)
220504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->disconnect_reason = -reason_code;
220604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	else
220704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_s->disconnect_reason = reason_code;
220804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpas_notify_disconnect_reason(wpa_s);
22098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_supplicant_dynamic_keys(wpa_s)) {
22108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
22118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_clear_keys(wpa_s, wpa_s->bssid);
22128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2213f8a26a8e6e081a2c576568198d0bcb4f976258acJouni Malinen	last_ssid = wpa_s->current_ssid;
22148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_supplicant_mark_disassoc(wpa_s);
22158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2216f8a26a8e6e081a2c576568198d0bcb4f976258acJouni Malinen	if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
22178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
2218f8a26a8e6e081a2c576568198d0bcb4f976258acJouni Malinen		wpa_s->current_ssid = last_ssid;
2219f8a26a8e6e081a2c576568198d0bcb4f976258acJouni Malinen	}
22201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
2221f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	if (fast_reconnect &&
2222f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !wpas_network_disabled(wpa_s, fast_reconnect_ssid) &&
2223f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !disallowed_bssid(wpa_s, fast_reconnect->bssid) &&
2224f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !disallowed_ssid(wpa_s, fast_reconnect->ssid,
2225f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			     fast_reconnect->ssid_len) &&
2226f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	    !wpas_temp_disabled(wpa_s, fast_reconnect_ssid)) {
22271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_SCAN_PROCESSING
22281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
22291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_supplicant_connect(wpa_s, fast_reconnect,
22301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   fast_reconnect_ssid) < 0) {
22311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			/* Recover through full scan */
22321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_supplicant_req_scan(wpa_s, 0, 100000);
22331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		}
22341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_SCAN_PROCESSING */
2235f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	} else if (fast_reconnect) {
2236f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		/*
2237f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 * Could not reconnect to the same BSS due to network being
2238f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 * disabled. Use a new scan to match the alternative behavior
2239f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 * above, i.e., to continue automatic reconnection attempt in a
2240f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 * way that enforces disabled network rules.
2241f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		 */
2242f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_supplicant_req_scan(wpa_s, 0, 100000);
22431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
22448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
22481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx)
22498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = eloop_ctx;
22518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!wpa_s->pending_mic_error_report)
22538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
22548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Sending pending MIC error report");
22568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise);
22578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->pending_mic_error_report = 0;
22588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
22598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
22608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
22638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
22648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 union wpa_event_data *data)
22658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
22668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int pairwise;
2267fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime t;
22688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
22708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	pairwise = (data && data->michael_mic_failure.unicast);
2271fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&t);
2272fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if ((wpa_s->last_michael_mic_error.sec &&
2273fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	     !os_reltime_expired(&t, &wpa_s->last_michael_mic_error, 60)) ||
22748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wpa_s->pending_mic_error_report) {
22758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->pending_mic_error_report) {
22768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
22778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Send the pending MIC error report immediately since
22788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * we are going to start countermeasures and AP better
22798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * do the same.
22808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
22818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_key_request(wpa_s->wpa, 1,
22828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   wpa_s->pending_mic_error_pairwise);
22838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
22848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* Send the new MIC error report immediately since we are going
22868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * to start countermeasures and AP better do the same.
22878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
22888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
22898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* initialize countermeasures */
22918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->countermeasures = 1;
22921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
22931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_blacklist_add(wpa_s, wpa_s->bssid);
22941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
22958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
22968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
22978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
22988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Need to wait for completion of request frame. We do not get
22998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * any callback for the message completion, so just wait a
23008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * short while and hope for the best. */
23018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_sleep(0, 10000);
23028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_drv_set_countermeasures(wpa_s, 1);
23048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_deauthenticate(wpa_s,
23058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      WLAN_REASON_MICHAEL_MIC_FAILURE);
23068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_cancel_timeout(wpa_supplicant_stop_countermeasures,
23078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     wpa_s, NULL);
23088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_register_timeout(60, 0,
23098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       wpa_supplicant_stop_countermeasures,
23108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       wpa_s, NULL);
23118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: mark the AP rejected for 60 second. STA is
23128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * allowed to associate with another AP.. */
23138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
23148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
23158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->mic_errors_seen) {
23168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			/*
23178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * Reduce the effectiveness of Michael MIC error
23188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * reports as a means for attacking against TKIP if
23198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * more than one MIC failure is noticed with the same
23208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * PTK. We delay the transmission of the reports by a
23218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * random time between 0 and 60 seconds in order to
23228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * force the attacker wait 60 seconds before getting
23238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * the information on whether a frame resulted in a MIC
23248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 * failure.
23258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 */
23268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			u8 rval[4];
23278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			int sec;
23288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (os_get_random(rval, sizeof(rval)) < 0)
23308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sec = os_random() % 60;
23318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			else
23328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sec = WPA_GET_BE32(rval) % 60;
23338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Delay MIC error "
23348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"report %d seconds", sec);
23358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->pending_mic_error_report = 1;
23368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->pending_mic_error_pairwise = pairwise;
23378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_cancel_timeout(
23388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_supplicant_delayed_mic_error_report,
23398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, NULL);
23408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_register_timeout(
23418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sec, os_random() % 1000000,
23428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_supplicant_delayed_mic_error_report,
23438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s, NULL);
23448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
23458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
23468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_DELAYED_MIC_ERROR_REPORT */
23488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
23498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
23508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2351fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_s->last_michael_mic_error = t;
23528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_s->mic_errors_seen++;
23538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TERMINATE_ONLASTIF
23578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int any_interfaces(struct wpa_supplicant *head)
23588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s;
23608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next)
23628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa_s->interface_removed)
23638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return 1;
23648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
23658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
23668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TERMINATE_ONLASTIF */
23678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
23708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
23718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      union wpa_event_data *data)
23728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
23738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0)
23748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
23758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
23768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->interface_status.ievent) {
23778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_ADDED:
23788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!wpa_s->interface_removed)
23798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
23808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->interface_removed = 0;
23818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was added");
23828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_supplicant_driver_init(wpa_s) < 0) {
23838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(wpa_s, MSG_INFO, "Failed to initialize the "
23848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"driver after interface was added");
23858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
23878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_REMOVED:
23888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed");
23898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->interface_removed = 1;
23908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_mark_disassoc(wpa_s);
239104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
23928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		l2_packet_deinit(wpa_s->l2);
23938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->l2 = NULL;
23948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TERMINATE_ONLASTIF
23958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* check if last interface */
23968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (!any_interfaces(wpa_s->global->ifaces))
23978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			eloop_terminate();
23988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TERMINATE_ONLASTIF */
23998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
24008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
24058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
24068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
24078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      union wpa_event_data *data)
24088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
24108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer);
24128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
24148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
24178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
24188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      union wpa_event_data *data)
24198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
24218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (data->tdls.oper) {
24238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TDLS_REQUEST_SETUP:
24244b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		wpa_tdls_remove(wpa_s->wpa, data->tdls.peer);
24254b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		if (wpa_tdls_is_external_setup(wpa_s->wpa))
24264b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			wpa_tdls_start(wpa_s->wpa, data->tdls.peer);
24274b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt		else
24284b9d52f502481b258fec743c03a5e957e5605afcDmitry Shmidt			wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, data->tdls.peer);
24298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
24308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case TDLS_REQUEST_TEARDOWN:
24316a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt		if (wpa_tdls_is_external_setup(wpa_s->wpa))
24326a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt			wpa_tdls_teardown_link(wpa_s->wpa, data->tdls.peer,
24336a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt					       data->tdls.reason_code);
24346a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt		else
24356a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt			wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN,
24366a9f522e56dae5b1fff00642e27b82e82772dcf7Sunil Dutt					  data->tdls.peer);
24378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
24388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
24418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2443a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM
244461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstatic void wpa_supplicant_event_wnm(struct wpa_supplicant *wpa_s,
244561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				     union wpa_event_data *data)
244661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
244761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (data == NULL)
244861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		return;
244961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	switch (data->wnm.oper) {
245061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case WNM_OPER_SLEEP:
245161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_printf(MSG_DEBUG, "Start sending WNM-Sleep Request "
245261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   "(action=%d, intval=%d)",
245361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			   data->wnm.sleep_action, data->wnm.sleep_intval);
245461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		ieee802_11_send_wnmsleep_req(wpa_s, data->wnm.sleep_action,
2455a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt					     data->wnm.sleep_intval, NULL);
245661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
245761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
245861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
2459a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */
246061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
246161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
24638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void
24648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtwpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s,
24658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				 union wpa_event_data *data)
24668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
24688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ft_process_response(wpa_s->wpa, data->ft_ies.ies,
24718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->ft_ies.ies_len,
24728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->ft_ies.ft_action,
24738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->ft_ies.target_ap,
24748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->ft_ies.ric_ies,
24758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    data->ft_ies.ric_ies_len) < 0) {
24768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: prevent MLME/driver from trying to associate? */
24778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
24788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
24798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
24808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IBSS_RSN
24838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_ibss_rsn_start(struct wpa_supplicant *wpa_s,
24848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						union wpa_event_data *data)
24858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
24868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_ssid *ssid;
24878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state < WPA_ASSOCIATED)
24888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data == NULL)
24908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssid = wpa_s->current_ssid;
24928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid == NULL)
24938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt))
24958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
24968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
24978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ibss_rsn_start(wpa_s->ibss_rsn, data->ibss_rsn_start.peer);
24988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2499c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2500c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2501c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic void wpa_supplicant_event_ibss_auth(struct wpa_supplicant *wpa_s,
2502c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					   union wpa_event_data *data)
2503c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
2504c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	struct wpa_ssid *ssid = wpa_s->current_ssid;
2505c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2506c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (ssid == NULL)
2507c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2508c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2509c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	/* check if the ssid is correctly configured as IBSS/RSN */
2510c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt))
2511c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2512c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2513c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	ibss_rsn_handle_auth(wpa_s->ibss_rsn, data->rx_mgmt.frame,
2514c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			     data->rx_mgmt.frame_len);
2515c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
25168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IBSS_RSN */
25178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
25208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ft_rx_action(struct wpa_supplicant *wpa_s, const u8 *data,
25218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			 size_t len)
25228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *sta_addr, *target_ap_addr;
25248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u16 status;
25258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "FT: RX Action", data, len);
25278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
25288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* only SME case supported for now */
25298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len < 1 + 2 * ETH_ALEN + 2)
25308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (data[0] != 2)
25328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return; /* Only FT Action Response is supported for now */
25338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta_addr = data + 1;
25348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	target_ap_addr = data + 1 + ETH_ALEN;
25358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	status = WPA_GET_LE16(data + 1 + 2 * ETH_ALEN);
25368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "FT: Received FT Action Response: STA "
25378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MACSTR " TargetAP " MACSTR " status %u",
25388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
25398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
25418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR
25428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" in FT Action Response", MAC2STR(sta_addr));
25438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (status) {
25478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "FT: FT Action Response indicates "
25488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"failure (status code %d)", status);
25498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/* TODO: report error to FT code(?) */
25508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_ft_process_response(wpa_s->wpa, data + 1 + 2 * ETH_ALEN + 2,
25548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    len - (1 + 2 * ETH_ALEN + 2), 1,
25558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    target_ap_addr, NULL, 0) < 0)
25568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
25578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_SME
25598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	{
25608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct wpa_bss *bss;
25618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bss = wpa_bss_get_bssid(wpa_s, target_ap_addr);
25628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (bss)
25638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s->sme.freq = bss->freq;
25648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->sme.auth_alg = WPA_AUTH_ALG_FT;
25658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sme_associate(wpa_s, WPAS_MODE_INFRA, target_ap_addr,
25668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      WLAN_AUTH_FT);
25678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
25688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_SME */
25698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
25718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_unprot_deauth(struct wpa_supplicant *wpa_s,
25748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					       struct unprot_deauth *e)
25758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
25778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Unprotected Deauthentication frame "
25788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dropped: " MACSTR " -> " MACSTR
25798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   " (reason code %u)",
25808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(e->sa), MAC2STR(e->da), e->reason_code);
25818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code);
25828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
25838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s,
25878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						 struct unprot_disassoc *e)
25888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
25898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
25908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "Unprotected Disassociation frame "
25918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "dropped: " MACSTR " -> " MACSTR
25928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   " (reason code %u)",
25938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   MAC2STR(e->sa), MAC2STR(e->da), e->reason_code);
25948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code);
25958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
25968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
25978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2599c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr,
2600c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				  u16 reason_code, int locally_generated,
2601c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				  const u8 *ie, size_t ie_len, int deauth)
2602c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
2603c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_AP
2604c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpa_s->ap_iface && addr) {
2605c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], addr);
2606c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2607c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2608c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2609c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpa_s->ap_iface) {
2610c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in AP mode");
2611c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2612c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2613c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_AP */
2614c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2615c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
2616c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2617344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	if (((reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
2618344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	      ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2619344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt		(wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
2620344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	       eapol_sm_failed(wpa_s->eapol))) &&
2621344abd362cfe2d03ed956666527352826b67bde5Dmitry Shmidt	     !wpa_s->eap_expected_failure))
26226dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt		wpas_auth_failed(wpa_s, "AUTH_FAILED");
2623c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2624c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_P2P
2625391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	if (deauth && reason_code > 0) {
2626c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (wpas_p2p_deauth_notif(wpa_s, addr, reason_code, ie, ie_len,
2627c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					  locally_generated) > 0) {
2628c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			/*
2629c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			 * The interface was removed, so cannot continue
2630c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			 * processing any additional operations after this.
2631c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			 */
2632c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			return;
2633c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
2634c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2635c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_P2P */
2636c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2637c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_supplicant_event_disassoc_finish(wpa_s, reason_code,
2638c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt					     locally_generated);
2639c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
2640c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2641c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2642c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic void wpas_event_disassoc(struct wpa_supplicant *wpa_s,
2643c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				struct disassoc_info *info)
2644c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
2645c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	u16 reason_code = 0;
2646c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int locally_generated = 0;
2647c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	const u8 *addr = NULL;
2648c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	const u8 *ie = NULL;
2649c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	size_t ie_len = 0;
2650c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2651c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification");
2652c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2653c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (info) {
2654c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		addr = info->addr;
2655c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		ie = info->ie;
2656c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		ie_len = info->ie_len;
2657c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		reason_code = info->reason_code;
2658c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		locally_generated = info->locally_generated;
2659c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", reason_code,
2660c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			locally_generated ? " (locally generated)" : "");
2661c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (addr)
2662c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
2663c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				MAC2STR(addr));
2664c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)",
2665c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			    ie, ie_len);
2666c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2667c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2668c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_AP
2669c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpa_s->ap_iface && info && info->addr) {
2670c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], info->addr);
2671c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2672c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2673c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2674c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpa_s->ap_iface) {
2675c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in AP mode");
2676c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		return;
2677c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2678c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_AP */
2679c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2680c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_P2P
2681c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (info) {
2682c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpas_p2p_disassoc_notif(
2683c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_s, info->addr, reason_code, info->ie, info->ie_len,
2684c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			locally_generated);
2685c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2686c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_P2P */
2687c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2688c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
2689c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		sme_event_disassoc(wpa_s, info);
2690c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2691c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpas_event_disconnect(wpa_s, addr, reason_code, locally_generated,
2692c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			      ie, ie_len, 0);
2693c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
2694c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2695c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2696c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidtstatic void wpas_event_deauth(struct wpa_supplicant *wpa_s,
2697c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			      struct deauth_info *info)
2698c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt{
2699c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	u16 reason_code = 0;
2700c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	int locally_generated = 0;
2701c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	const u8 *addr = NULL;
2702c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	const u8 *ie = NULL;
2703c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	size_t ie_len = 0;
2704c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2705c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Deauthentication notification");
2706c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2707c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	if (info) {
2708c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		addr = info->addr;
2709c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		ie = info->ie;
2710c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		ie_len = info->ie_len;
2711c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		reason_code = info->reason_code;
2712c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		locally_generated = info->locally_generated;
2713c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s",
2714c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			reason_code,
2715c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			locally_generated ? " (locally generated)" : "");
2716c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		if (addr) {
2717c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
2718c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				MAC2STR(addr));
2719c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		}
2720c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "Deauthentication frame IE(s)",
2721c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			    ie, ie_len);
2722c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	}
2723c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2724c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpa_reset_ft_completed(wpa_s->wpa);
2725c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2726c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt	wpas_event_disconnect(wpa_s, addr, reason_code,
2727c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			      locally_generated, ie, ie_len, 1);
2728c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt}
2729c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
2730c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt
27317dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidtstatic const char * reg_init_str(enum reg_change_initiator init)
27327dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt{
27337dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	switch (init) {
27347dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_SET_BY_CORE:
27357dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "CORE";
27367dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_SET_BY_USER:
27377dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "USER";
27387dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_SET_BY_DRIVER:
27397dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "DRIVER";
27407dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_SET_BY_COUNTRY_IE:
27417dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "COUNTRY_IE";
27427dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_BEACON_HINT:
27437dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "BEACON_HINT";
27447dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	}
27457dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	return "?";
27467dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt}
27477dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt
27487dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt
27497dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidtstatic const char * reg_type_str(enum reg_type type)
27507dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt{
27517dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	switch (type) {
27527dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_TYPE_UNKNOWN:
27537dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "UNKNOWN";
27547dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_TYPE_COUNTRY:
27557dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "COUNTRY";
27567dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_TYPE_WORLD:
27577dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "WORLD";
27587dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_TYPE_CUSTOM_WORLD:
27597dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "CUSTOM_WORLD";
27607dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	case REGDOM_TYPE_INTERSECTION:
27617dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		return "INTERSECTION";
27627dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	}
27637dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	return "?";
27647dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt}
27657dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt
27667dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt
27677dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidtstatic void wpa_supplicant_update_channel_list(
27687dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
2769cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{
2770cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	struct wpa_supplicant *ifs;
2771cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
27727dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
2773c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt		reg_init_str(info->initiator), reg_type_str(info->type),
27747dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		info->alpha2[0] ? " alpha2=" : "",
27757dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		info->alpha2[0] ? info->alpha2 : "");
27767dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt
2777cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	if (wpa_s->drv_priv == NULL)
2778cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		return; /* Ignore event during drv initialization */
2779cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2780cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	free_hw_features(wpa_s);
2781cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpa_s->hw.modes = wpa_drv_get_hw_feature_data(
2782cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags);
2783cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2784cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	wpas_p2p_update_channel_list(wpa_s);
2785cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2786cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	/*
278701904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	 * Check other interfaces to see if they share the same radio. If
2788cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 * so, they get updated with this same hw mode info.
2789cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	 */
279001904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt	dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
279101904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 radio_list) {
279201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		if (ifs != wpa_s) {
2793cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			wpa_printf(MSG_DEBUG, "%s: Updating hw mode",
2794cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				   ifs->ifname);
2795cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			free_hw_features(ifs);
2796cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt			ifs->hw.modes = wpa_drv_get_hw_feature_data(
2797cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt				ifs, &ifs->hw.num_modes, &ifs->hw.flags);
2798cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt		}
2799cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt	}
2800cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt}
2801cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2802cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt
2803fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidtstatic void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
2804623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt				      const u8 *frame, size_t len, int freq)
2805fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt{
2806623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt	const struct ieee80211_mgmt *mgmt;
2807fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	const u8 *payload;
2808fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	size_t plen;
2809fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	u8 category;
2810fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2811fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (len < IEEE80211_HDRLEN + 2)
2812fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2813fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2814623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt	mgmt = (const struct ieee80211_mgmt *) frame;
2815623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt	payload = frame + IEEE80211_HDRLEN;
2816fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	category = *payload++;
2817623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt	plen = len - IEEE80211_HDRLEN - 1;
2818fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2819fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
2820fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		" Category=%u DataLen=%d freq=%d MHz",
2821fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		MAC2STR(mgmt->sa), category, (int) plen, freq);
2822fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2823fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_IEEE80211R
2824fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (category == WLAN_ACTION_FT) {
2825fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		ft_rx_action(wpa_s, payload, plen);
2826fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2827fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2828fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
2829fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2830fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_IEEE80211W
2831fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_SME
2832fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (category == WLAN_ACTION_SA_QUERY) {
2833fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen);
2834fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2835fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2836fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_SME */
2837fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
2838fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2839fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_WNM
2840fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (mgmt->u.action.category == WLAN_ACTION_WNM) {
2841fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		ieee802_11_rx_wnm_action(wpa_s, mgmt, len);
2842fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2843fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2844fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_WNM */
2845fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2846fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_GAS
28471846323989242844f0e857458a8939fa5836429cDmitry Shmidt	if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC ||
28481846323989242844f0e857458a8939fa5836429cDmitry Shmidt	     mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) &&
2849fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid,
28501846323989242844f0e857458a8939fa5836429cDmitry Shmidt			 mgmt->u.action.category,
2851fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			 payload, plen, freq) == 0)
2852fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2853fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_GAS */
2854fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2855fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_TDLS
2856fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (category == WLAN_ACTION_PUBLIC && plen >= 4 &&
2857fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
2858fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG,
2859fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			"TDLS: Received Discovery Response from " MACSTR,
2860fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			MAC2STR(mgmt->sa));
2861fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2862fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2863fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_TDLS */
2864fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2865fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#ifdef CONFIG_INTERWORKING
2866fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (category == WLAN_ACTION_QOS && plen >= 1 &&
2867fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	    payload[0] == QOS_QOS_MAP_CONFIG) {
2868fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		const u8 *pos = payload + 1;
2869fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		size_t qlen = plen - 1;
2870fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
2871fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			MACSTR, MAC2STR(mgmt->sa));
2872fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 &&
2873fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		    qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET &&
2874fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		    pos[1] <= qlen - 2 && pos[1] >= 16)
2875fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpas_qos_map_set(wpa_s, pos + 2, pos[1]);
2876fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		return;
2877fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	}
2878fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt#endif /* CONFIG_INTERWORKING */
2879fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2880fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
2881fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			   category, payload, plen, freq);
2882fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt}
2883fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2884fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2885cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtstatic void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s,
2886cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt					     union wpa_event_data *event)
2887cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt{
2888cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2889cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpa_supplicant *ifs;
2890cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
2891cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	struct wpa_freq_range_list *list;
2892cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	char *str = NULL;
2893cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2894cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	list = &event->freq_range;
2895cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2896cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (list->num)
2897cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		str = freq_range_list_str(list);
2898cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AVOID_FREQ "ranges=%s",
2899cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		str ? str : "");
2900cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2901cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#ifdef CONFIG_P2P
2902cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	if (freq_range_list_parse(&wpa_s->global->p2p_go_avoid_freq, str)) {
2903cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_dbg(wpa_s, MSG_ERROR, "%s: Failed to parse freq range",
2904cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			__func__);
2905cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	} else {
2906cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Update channel list based on frequency avoid event");
2907cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpas_p2p_update_channel_list(wpa_s);
2908cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
2909cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2910cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
2911cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		int freq;
2912cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (!ifs->current_ssid ||
2913cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		    !ifs->current_ssid->p2p_group ||
2914cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		    (ifs->current_ssid->mode != WPAS_MODE_P2P_GO &&
2915cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		     ifs->current_ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION))
2916cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			continue;
2917cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2918cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		freq = ifs->current_ssid->frequency;
2919cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		if (!freq_range_list_includes(list, freq)) {
2920cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			wpa_dbg(ifs, MSG_DEBUG, "P2P GO operating frequency %d MHz in safe range",
2921cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt				freq);
2922cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			continue;
2923cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		}
2924cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2925cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_dbg(ifs, MSG_DEBUG, "P2P GO operating in unsafe frequency %d MHz",
2926cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt			freq);
2927cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		/* TODO: Consider using CSA or removing the group within
2928cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		 * wpa_supplicant */
2929cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_msg(ifs, MSG_INFO, P2P_EVENT_REMOVE_AND_REFORM_GROUP);
2930cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	}
2931cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt#endif /* CONFIG_P2P */
2932cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2933cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	os_free(str);
2934cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt}
2935cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
2936cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt
29378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_supplicant_event(void *ctx, enum wpa_event_type event,
29388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			  union wpa_event_data *data)
29398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
29408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct wpa_supplicant *wpa_s = ctx;
29418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
29438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    event != EVENT_INTERFACE_ENABLED &&
29441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    event != EVENT_INTERFACE_STATUS &&
29451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    event != EVENT_SCHED_SCAN_STOPPED) {
29461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG,
29471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			"Ignore event %s (%d) while interface is disabled",
29481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			event_to_string(event), event);
29498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
29508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
29518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
29531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
29541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int level = MSG_DEBUG;
29551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
295604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
29571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		const struct ieee80211_hdr *hdr;
29581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		u16 fc;
29591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
29601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		fc = le_to_host16(hdr->frame_control);
29611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
29621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
29631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			level = MSG_EXCESSIVE;
29641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
29651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
29661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	wpa_dbg(wpa_s, level, "Event %s (%d) received",
29671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		event_to_string(event), event);
29681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
29691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
29708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
29718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	switch (event) {
29728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_AUTH:
29738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sme_event_auth(wpa_s, data);
29748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_ASSOC:
29768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_assoc(wpa_s, data);
29778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_DISASSOC:
2979c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpas_event_disassoc(wpa_s,
2980c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				    data ? &data->disassoc_info : NULL);
2981c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		break;
29828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_DEAUTH:
2983c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt		wpas_event_deauth(wpa_s,
2984c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				  data ? &data->deauth_info : NULL);
29858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_MICHAEL_MIC_FAILURE:
29878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_michael_mic_failure(wpa_s, data);
29888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
29898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_SCAN_PROCESSING
2990fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	case EVENT_SCAN_STARTED:
2991fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		os_get_reltime(&wpa_s->scan_start_time);
2992fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (wpa_s->own_scan_requested) {
2993fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			struct os_reltime diff;
2994fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
2995fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			os_reltime_sub(&wpa_s->scan_start_time,
2996fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				       &wpa_s->scan_trigger_time, &diff);
2997fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds",
2998fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				diff.sec, diff.usec);
2999fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_s->own_scan_requested = 0;
3000fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_s->own_scan_running = 1;
3001fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
3002fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			    wpa_s->manual_scan_use_id) {
3003661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				wpa_msg_ctrl(wpa_s, MSG_INFO,
3004661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt					     WPA_EVENT_SCAN_STARTED "id=%u",
3005661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt					     wpa_s->manual_scan_id);
3006fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			} else {
3007661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt				wpa_msg_ctrl(wpa_s, MSG_INFO,
3008661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt					     WPA_EVENT_SCAN_STARTED);
3009fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
3010fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		} else {
3011fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
3012fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_s->external_scan_running = 1;
3013661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt			wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
3014fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
3015fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		break;
30168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_SCAN_RESULTS:
3017fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		if (os_reltime_initialized(&wpa_s->scan_start_time)) {
3018fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			struct os_reltime now, diff;
3019fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			os_get_reltime(&now);
3020fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			os_reltime_sub(&now, &wpa_s->scan_start_time, &diff);
3021fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_s->scan_start_time.sec = 0;
3022fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_s->scan_start_time.usec = 0;
3023fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "Scan completed in %ld.%06ld seconds",
3024fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				diff.sec, diff.usec);
3025fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		}
30268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_scan_results(wpa_s, data);
3027fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->own_scan_running = 0;
3028fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		wpa_s->external_scan_running = 0;
3029fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt		radio_work_check_next(wpa_s);
30308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_SCAN_PROCESSING */
30328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_ASSOCINFO:
30338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_associnfo(wpa_s, data);
30348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_STATUS:
30368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_interface_status(wpa_s, data);
30378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_PMKID_CANDIDATE:
30398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_pmkid_candidate(wpa_s, data);
30408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_PEERKEY
30428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_STKSTART:
30438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_stkstart(wpa_s, data);
30448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_PEERKEY */
30468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS
30478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_TDLS:
30488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_tdls(wpa_s, data);
30498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS */
3051a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#ifdef CONFIG_WNM
305261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	case EVENT_WNM:
305361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_supplicant_event_wnm(wpa_s, data);
305461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		break;
3055a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt#endif /* CONFIG_WNM */
30568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211R
30578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_FT_RESPONSE:
30588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_ft_response(wpa_s, data);
30598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
30618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IBSS_RSN
30628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_IBSS_RSN_START:
30638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_ibss_rsn_start(wpa_s, data);
30648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IBSS_RSN */
30668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_ASSOC_REJECT:
30678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->assoc_reject.bssid)
30688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
30698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"bssid=" MACSTR	" status_code=%u",
30708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				MAC2STR(data->assoc_reject.bssid),
30718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->assoc_reject.status_code);
30728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		else
30738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
30748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"status_code=%u",
30758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->assoc_reject.status_code);
30768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
30778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sme_event_assoc_reject(wpa_s, data);
3078b485b188f853a4ec5342c2ea49705b545b2caf3dJeff Johnson		else {
3079d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			const u8 *bssid = data->assoc_reject.bssid;
3080d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			if (bssid == NULL || is_zero_ether_addr(bssid))
3081d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt				bssid = wpa_s->pending_bssid;
3082d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpas_connection_failed(wpa_s, bssid);
3083d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			wpa_supplicant_mark_disassoc(wpa_s);
3084d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
30858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_AUTH_TIMED_OUT:
30878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
30888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sme_event_auth_timed_out(wpa_s, data);
30898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_ASSOC_TIMED_OUT:
30918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
30928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sme_event_assoc_timed_out(wpa_s, data);
30938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
30948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_TX_STATUS:
30958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS dst=" MACSTR
30968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			" type=%d stype=%d",
30978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MAC2STR(data->tx_status.dst),
30988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->tx_status.type, data->tx_status.stype);
30991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_AP
31008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface == NULL) {
31011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_OFFCHANNEL
31028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
31038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->tx_status.stype == WLAN_FC_STYPE_ACTION)
31041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				offchannel_send_action_tx_status(
31058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					wpa_s, data->tx_status.dst,
31068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->tx_status.data,
31078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->tx_status.data_len,
31088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->tx_status.ack ?
31091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					OFFCHANNEL_SEND_ACTION_SUCCESS :
31101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					OFFCHANNEL_SEND_ACTION_NO_ACK);
31111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_OFFCHANNEL */
31128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_AP */
31151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_OFFCHANNEL
31168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
31178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
31188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
31198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Catch TX status events for Action frames we sent via group
31208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * interface in GO mode.
31218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
31228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
31238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
31248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(wpa_s->parent->pending_action_dst,
31258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			      data->tx_status.dst, ETH_ALEN) == 0) {
31261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			offchannel_send_action_tx_status(
31278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_s->parent, data->tx_status.dst,
31288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->tx_status.data,
31298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->tx_status.data_len,
31308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				data->tx_status.ack ?
31311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				OFFCHANNEL_SEND_ACTION_SUCCESS :
31321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				OFFCHANNEL_SEND_ACTION_NO_ACK);
31338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_OFFCHANNEL */
31361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_AP
31378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		switch (data->tx_status.type) {
31388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_FC_TYPE_MGMT:
31398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ap_mgmt_tx_cb(wpa_s, data->tx_status.data,
31408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      data->tx_status.data_len,
31418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      data->tx_status.stype,
31428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      data->tx_status.ack);
31438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		case WLAN_FC_TYPE_DATA:
31458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ap_tx_status(wpa_s, data->tx_status.dst,
31468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     data->tx_status.data,
31478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     data->tx_status.data_len,
31488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     data->tx_status.ack);
31498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
31511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_AP */
31521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
31531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_AP
31541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case EVENT_EAPOL_TX_STATUS:
31551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst,
31561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   data->eapol_tx_status.data,
31571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   data->eapol_tx_status.data_len,
31581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				   data->eapol_tx_status.ack);
31591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
31601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case EVENT_DRIVER_CLIENT_POLL_OK:
31611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ap_client_poll_ok(wpa_s, data->client_poll.addr);
31628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
31638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_RX_FROM_UNKNOWN:
31648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface == NULL)
31658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
31661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr,
31671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				       data->rx_from_unknown.wds);
31688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
316904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EVENT_CH_SWITCH:
317004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!data)
317104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
317204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (!wpa_s->ap_iface) {
317304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch "
317404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				"event in non-AP mode");
317504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			break;
317604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
317704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
317804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
317904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				  data->ch_switch.ht_enabled,
318004f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				  data->ch_switch.ch_offset,
318104f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				  data->ch_switch.ch_width,
318204f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				  data->ch_switch.cf1,
318304f534e89ed127da4077485376f24debc50d80d5Dmitry Shmidt				  data->ch_switch.cf2);
318404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		break;
3185c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_AP */
318604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	case EVENT_RX_MGMT: {
318704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		u16 fc, stype;
318804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		const struct ieee80211_mgmt *mgmt;
318904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3190818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#ifdef CONFIG_TESTING_OPTIONS
3191818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		if (wpa_s->ext_mgmt_frame_handling) {
3192818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			struct rx_mgmt *rx = &data->rx_mgmt;
3193818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			size_t hex_len = 2 * rx->frame_len + 1;
3194818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			char *hex = os_malloc(hex_len);
3195818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			if (hex) {
3196818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				wpa_snprintf_hex(hex, hex_len,
3197818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt						 rx->frame, rx->frame_len);
3198818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				wpa_msg(wpa_s, MSG_INFO, "MGMT-RX freq=%d datarate=%u ssi_signal=%d %s",
3199818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					rx->freq, rx->datarate, rx->ssi_signal,
3200818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt					hex);
3201818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt				os_free(hex);
3202818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			}
3203818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt			break;
3204818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt		}
3205818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt#endif /* CONFIG_TESTING_OPTIONS */
3206818ea489ef32dcdc7c098d8a336d6e1dd8996112Dmitry Shmidt
320704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		mgmt = (const struct ieee80211_mgmt *)
320804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			data->rx_mgmt.frame;
320904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		fc = le_to_host16(mgmt->frame_control);
321004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		stype = WLAN_FC_GET_STYPE(fc);
321104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
3212c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_AP
32138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface == NULL) {
3214c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_AP */
32158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
32168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (stype == WLAN_FC_STYPE_PROBE_REQ &&
32178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    data->rx_mgmt.frame_len > 24) {
32188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *src = mgmt->sa;
32198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				const u8 *ie = mgmt->u.probe_req.variable;
32208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				size_t ie_len = data->rx_mgmt.frame_len -
32218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					(mgmt->u.probe_req.variable -
32228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					 data->rx_mgmt.frame);
322304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				wpas_p2p_probe_req_rx(
322404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					wpa_s, src, mgmt->da,
322504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					mgmt->bssid, ie, ie_len,
322604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					data->rx_mgmt.ssi_signal);
32278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				break;
32288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
32298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
3230c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_IBSS_RSN
3231c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			if (stype == WLAN_FC_STYPE_AUTH &&
3232c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			    data->rx_mgmt.frame_len >= 30) {
3233c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				wpa_supplicant_event_ibss_auth(wpa_s, data);
3234c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt				break;
3235c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt			}
3236c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_IBSS_RSN */
3237fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
3238fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			if (stype == WLAN_FC_STYPE_ACTION) {
3239fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				wpas_event_rx_mgmt_action(
3240623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt					wpa_s, data->rx_mgmt.frame,
3241623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt					data->rx_mgmt.frame_len,
3242fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt					data->rx_mgmt.freq);
3243fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt				break;
3244fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt			}
3245fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt
32468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
32478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				"management frame in non-AP mode");
32488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
3249c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#ifdef CONFIG_AP
32508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
325104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
325204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (stype == WLAN_FC_STYPE_PROBE_REQ &&
325304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		    data->rx_mgmt.frame_len > 24) {
325404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			const u8 *ie = mgmt->u.probe_req.variable;
325504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			size_t ie_len = data->rx_mgmt.frame_len -
325604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				(mgmt->u.probe_req.variable -
325704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				 data->rx_mgmt.frame);
325804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
325904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da,
326004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 mgmt->bssid, ie, ie_len,
326104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					 data->rx_mgmt.ssi_signal);
326204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
326304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
32648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ap_mgmt_rx(wpa_s, &data->rx_mgmt);
3265c2ebb4b85d69b65f552fee71ac68f44e8d87b39eDmitry Shmidt#endif /* CONFIG_AP */
32668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
326704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
32688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_RX_PROBE_REQ:
32698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (data->rx_probe_req.sa == NULL ||
32708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    data->rx_probe_req.ie == NULL)
32718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
32728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
32738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface) {
32748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_probe_req_rx(wpa_s->ap_iface->bss[0],
32758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     data->rx_probe_req.sa,
32761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					     data->rx_probe_req.da,
32771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					     data->rx_probe_req.bssid,
32788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					     data->rx_probe_req.ie,
327904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     data->rx_probe_req.ie_len,
328004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt					     data->rx_probe_req.ssi_signal);
32818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			break;
32828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
32838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
32848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa,
32851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      data->rx_probe_req.da,
32861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				      data->rx_probe_req.bssid,
32878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      data->rx_probe_req.ie,
328804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      data->rx_probe_req.ie_len,
328904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				      data->rx_probe_req.ssi_signal);
32908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
32918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_REMAIN_ON_CHANNEL:
32921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_OFFCHANNEL
32931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		offchannel_remain_on_channel_cb(
32941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s, data->remain_on_channel.freq,
32951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			data->remain_on_channel.duration);
32961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_OFFCHANNEL */
32978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_remain_on_channel_cb(
32988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s, data->remain_on_channel.freq,
32998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->remain_on_channel.duration);
33008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_CANCEL_REMAIN_ON_CHANNEL:
33021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_OFFCHANNEL
33031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		offchannel_cancel_remain_on_channel_cb(
33041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_s, data->remain_on_channel.freq);
33051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_OFFCHANNEL */
33068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_cancel_remain_on_channel_cb(
33078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s, data->remain_on_channel.freq);
33088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_EAPOL_RX:
33108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
33118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->eapol_rx.data,
33128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					data->eapol_rx.data_len);
33138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_SIGNAL_CHANGE:
33157dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE
33167dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			"above=%d signal=%d noise=%d txrate=%d",
33177dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			data->signal_change.above_threshold,
33187dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			data->signal_change.current_signal,
33197dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			data->signal_change.current_noise,
33207dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			data->signal_change.current_txrate);
33218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		bgscan_notify_signal_change(
33228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_s, data->signal_change.above_threshold,
33238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->signal_change.current_signal,
33248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->signal_change.current_noise,
33258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->signal_change.current_txrate);
33268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_ENABLED:
33288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
33298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
33301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wpa_supplicant_update_mac_addr(wpa_s);
3331df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt			if (wpa_s->p2p_mgmt) {
3332df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt				wpa_supplicant_set_state(wpa_s,
3333df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt							 WPA_DISCONNECTED);
3334df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt				break;
3335df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt			}
3336df5a7e4c5c64890c2425bb47d665bbce4992b676Dmitry Shmidt
33378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
33388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (!wpa_s->ap_iface) {
33398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_supplicant_set_state(wpa_s,
33408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 WPA_DISCONNECTED);
33418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_supplicant_req_scan(wpa_s, 0, 0);
33428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			} else
33438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_supplicant_set_state(wpa_s,
33448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							 WPA_COMPLETED);
33458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* CONFIG_AP */
33468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
33478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_supplicant_req_scan(wpa_s, 0, 0);
33488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
33498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
33508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_DISABLED:
33528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled");
335301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt#ifdef CONFIG_P2P
335401904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO ||
335501904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		    (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group &&
335601904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		     wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)) {
335701904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			/*
335801904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 * The interface was externally disabled. Remove
335901904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 * it assuming an external entity will start a
336001904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 * new session if needed.
336101904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			 */
336201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			wpas_p2p_disconnect(wpa_s);
336301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt			break;
336401904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt		}
33656dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt		if (wpa_s->p2p_scan_work && wpa_s->global->p2p &&
33666dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt		    p2p_in_progress(wpa_s->global->p2p) > 1) {
33676dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt			/* This radio work will be cancelled, so clear P2P
33686dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt			 * state as well.
33696dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt			 */
33706dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt			p2p_stop_find(wpa_s->global->p2p);
33716dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt		}
337201904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt#endif /* CONFIG_P2P */
337301904cfafd75a70b9f29c0220b90bdef45595491Dmitry Shmidt
33747832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (wpa_s->wpa_state >= WPA_AUTHENTICATING) {
33757832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			/*
33767832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			 * Indicate disconnection to keep ctrl_iface events
33777832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			 * consistent.
33787832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			 */
33797832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			wpa_supplicant_event_disassoc(
33807832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt				wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1);
33817832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		}
33828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_mark_disassoc(wpa_s);
3383bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt		radio_remove_works(wpa_s, NULL, 0);
3384bd14a57187b024f49f5b9ace55ef457d8d04650aDmitry Shmidt
33858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
33868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_CHANNEL_LIST_CHANGED:
33887dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt		wpa_supplicant_update_channel_list(
33897dba0e5708da7276a43a44cf479aa743564e15b9Dmitry Shmidt			wpa_s, &data->channel_list_changed);
33908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_INTERFACE_UNAVAILABLE:
33928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_interface_unavailable(wpa_s);
33938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
33948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_BEST_CHANNEL:
33958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_dbg(wpa_s, MSG_DEBUG, "Best channel event received "
33968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			"(%d %d %d)",
33978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->best_chan.freq_24, data->best_chan.freq_5,
33988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			data->best_chan.freq_overall);
33998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->best_24_freq = data->best_chan.freq_24;
34008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->best_5_freq = data->best_chan.freq_5;
34018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_s->best_overall_freq = data->best_chan.freq_overall;
34028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24,
34038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      data->best_chan.freq_5,
34048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					      data->best_chan.freq_overall);
34058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_UNPROT_DEAUTH:
34078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_unprot_deauth(wpa_s,
34088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						   &data->unprot_deauth);
34098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_UNPROT_DISASSOC:
34118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_supplicant_event_unprot_disassoc(wpa_s,
34128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						     &data->unprot_disassoc);
34138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_STATION_LOW_ACK:
34158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_AP
34168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (wpa_s->ap_iface && data)
34178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0],
34188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						  data->low_ack.addr);
34198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_AP */
34201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TDLS
34211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (data)
342243cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt			wpa_tdls_disable_unreachable_link(wpa_s->wpa,
342343cb578dfe2c492257636f6234a24178ed27789eDmitry Shmidt							  data->low_ack.addr);
34241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TDLS */
34258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	case EVENT_IBSS_PEER_LOST:
34278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IBSS_RSN
34288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ibss_rsn_stop(wpa_s->ibss_rsn, data->ibss_peer_lost.peer);
34298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IBSS_RSN */
34308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case EVENT_DRIVER_GTK_REKEY:
34321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (os_memcmp(data->driver_gtk_rekey.bssid,
34331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			      wpa_s->bssid, ETH_ALEN))
34341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
34351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (!wpa_s->wpa)
34361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
34371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_sm_update_replay_ctr(wpa_s->wpa,
34381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					 data->driver_gtk_rekey.replay_ctr);
34391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
34401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case EVENT_SCHED_SCAN_STOPPED:
34411846323989242844f0e857458a8939fa5836429cDmitry Shmidt		wpa_s->pno = 0;
34421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_s->sched_scanning = 0;
34431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_supplicant_notify_scanning(wpa_s, 0);
34441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
34461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			break;
34471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
34481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		/*
34491846323989242844f0e857458a8939fa5836429cDmitry Shmidt		 * Start a new sched scan to continue searching for more SSIDs
34501846323989242844f0e857458a8939fa5836429cDmitry Shmidt		 * either if timed out or PNO schedule scan is pending.
34511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		 */
34529866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		if (wpa_s->sched_scan_timed_out) {
34539866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt			wpa_supplicant_req_sched_scan(wpa_s);
34549866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt		} else if (wpa_s->pno_sched_pending) {
34559866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt			wpa_s->pno_sched_pending = 0;
34569866086a955d00e237cc8df3722e7dff75c02532Dmitry Shmidt			wpas_start_pno(wpa_s);
34571846323989242844f0e857458a8939fa5836429cDmitry Shmidt		}
34581846323989242844f0e857458a8939fa5836429cDmitry Shmidt
34591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
34601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	case EVENT_WPS_BUTTON_PUSHED:
34611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
34621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpas_wps_start_pbc(wpa_s, NULL, 0);
34631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
34641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		break;
3465cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	case EVENT_AVOID_FREQUENCIES:
3466cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		wpa_supplicant_notify_avoid_freq(wpa_s, data);
3467cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt		break;
3468f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt	case EVENT_CONNECT_FAILED_REASON:
3469f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#ifdef CONFIG_AP
3470f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		if (!wpa_s->ap_iface || !data)
3471f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			break;
3472f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		hostapd_event_connect_failed_reason(
3473f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			wpa_s->ap_iface->bss[0],
3474f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			data->connect_failed_reason.addr,
3475f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt			data->connect_failed_reason.code);
3476f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#endif /* CONFIG_AP */
3477f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt		break;
34788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	default:
34798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
34808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		break;
34818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
34828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3483