xref: /netbsd-src/external/bsd/wpa/dist/wpa_supplicant/sme.c (revision 96fc3e30a7c3f7bba53384bf41dad5f78306fac4)
1 /*
2  * wpa_supplicant - SME
3  * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14 
15 #include "includes.h"
16 
17 #include "common.h"
18 #include "utils/eloop.h"
19 #include "common/ieee802_11_defs.h"
20 #include "common/ieee802_11_common.h"
21 #include "eapol_supp/eapol_supp_sm.h"
22 #include "common/wpa_common.h"
23 #include "rsn_supp/wpa.h"
24 #include "rsn_supp/pmksa_cache.h"
25 #include "config.h"
26 #include "wpa_supplicant_i.h"
27 #include "driver_i.h"
28 #include "wpas_glue.h"
29 #include "wps_supplicant.h"
30 #include "p2p_supplicant.h"
31 #include "notify.h"
32 #include "blacklist.h"
33 #include "bss.h"
34 #include "scan.h"
35 #include "sme.h"
36 
37 #define SME_AUTH_TIMEOUT 5
38 #define SME_ASSOC_TIMEOUT 5
39 
40 static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
41 static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
42 #ifdef CONFIG_IEEE80211W
43 static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
44 #endif /* CONFIG_IEEE80211W */
45 
46 
47 void sme_authenticate(struct wpa_supplicant *wpa_s,
48 		      struct wpa_bss *bss, struct wpa_ssid *ssid)
49 {
50 	struct wpa_driver_auth_params params;
51 	struct wpa_ssid *old_ssid;
52 #ifdef CONFIG_IEEE80211R
53 	const u8 *ie;
54 #endif /* CONFIG_IEEE80211R */
55 #ifdef CONFIG_IEEE80211R
56 	const u8 *md = NULL;
57 #endif /* CONFIG_IEEE80211R */
58 	int i, bssid_changed;
59 
60 	if (bss == NULL) {
61 		wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
62 			"the network");
63 		return;
64 	}
65 
66 	wpa_s->current_bss = bss;
67 
68 	os_memset(&params, 0, sizeof(params));
69 	wpa_s->reassociate = 0;
70 
71 	params.freq = bss->freq;
72 	params.bssid = bss->bssid;
73 	params.ssid = bss->ssid;
74 	params.ssid_len = bss->ssid_len;
75 	params.p2p = ssid->p2p_group;
76 
77 	if (wpa_s->sme.ssid_len != params.ssid_len ||
78 	    os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
79 		wpa_s->sme.prev_bssid_set = 0;
80 
81 	wpa_s->sme.freq = params.freq;
82 	os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
83 	wpa_s->sme.ssid_len = params.ssid_len;
84 
85 	params.auth_alg = WPA_AUTH_ALG_OPEN;
86 #ifdef IEEE8021X_EAPOL
87 	if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
88 		if (ssid->leap) {
89 			if (ssid->non_leap == 0)
90 				params.auth_alg = WPA_AUTH_ALG_LEAP;
91 			else
92 				params.auth_alg |= WPA_AUTH_ALG_LEAP;
93 		}
94 	}
95 #endif /* IEEE8021X_EAPOL */
96 	wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
97 		params.auth_alg);
98 	if (ssid->auth_alg) {
99 		params.auth_alg = ssid->auth_alg;
100 		wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
101 			"0x%x", params.auth_alg);
102 	}
103 
104 	for (i = 0; i < NUM_WEP_KEYS; i++) {
105 		if (ssid->wep_key_len[i])
106 			params.wep_key[i] = ssid->wep_key[i];
107 		params.wep_key_len[i] = ssid->wep_key_len[i];
108 	}
109 	params.wep_tx_keyidx = ssid->wep_tx_keyidx;
110 
111 	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
112 	os_memset(wpa_s->bssid, 0, ETH_ALEN);
113 	os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
114 	if (bssid_changed)
115 		wpas_notify_bssid_changed(wpa_s);
116 
117 	if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
118 	     wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
119 	    (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK |
120 			       WPA_KEY_MGMT_FT_IEEE8021X |
121 			       WPA_KEY_MGMT_FT_PSK |
122 			       WPA_KEY_MGMT_IEEE8021X_SHA256 |
123 			       WPA_KEY_MGMT_PSK_SHA256))) {
124 		int try_opportunistic;
125 		try_opportunistic = ssid->proactive_key_caching &&
126 			(ssid->proto & WPA_PROTO_RSN);
127 		if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
128 					    wpa_s->current_ssid,
129 					    try_opportunistic) == 0)
130 			eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
131 		wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
132 		if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
133 					      wpa_s->sme.assoc_req_ie,
134 					      &wpa_s->sme.assoc_req_ie_len)) {
135 			wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
136 				"key management and encryption suites");
137 			return;
138 		}
139 	} else if (ssid->key_mgmt &
140 		   (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X |
141 		    WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK |
142 		    WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 |
143 		    WPA_KEY_MGMT_IEEE8021X_SHA256)) {
144 		wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
145 		if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
146 					      wpa_s->sme.assoc_req_ie,
147 					      &wpa_s->sme.assoc_req_ie_len)) {
148 			wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
149 				"key management and encryption suites (no "
150 				"scan results)");
151 			return;
152 		}
153 #ifdef CONFIG_WPS
154 	} else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
155 		struct wpabuf *wps_ie;
156 		wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
157 		if (wps_ie && wpabuf_len(wps_ie) <=
158 		    sizeof(wpa_s->sme.assoc_req_ie)) {
159 			wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
160 			os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
161 				  wpa_s->sme.assoc_req_ie_len);
162 		} else
163 			wpa_s->sme.assoc_req_ie_len = 0;
164 		wpabuf_free(wps_ie);
165 		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
166 #endif /* CONFIG_WPS */
167 	} else {
168 		wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
169 		wpa_s->sme.assoc_req_ie_len = 0;
170 	}
171 
172 #ifdef CONFIG_IEEE80211R
173 	ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
174 	if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
175 		md = ie + 2;
176 	wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
177 	if (md) {
178 		/* Prepare for the next transition */
179 		wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
180 	}
181 
182 	if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK |
183 				    WPA_KEY_MGMT_FT_IEEE8021X)) {
184 		if (wpa_s->sme.assoc_req_ie_len + 5 <
185 		    sizeof(wpa_s->sme.assoc_req_ie)) {
186 			struct rsn_mdie *mdie;
187 			u8 *pos = wpa_s->sme.assoc_req_ie +
188 				wpa_s->sme.assoc_req_ie_len;
189 			*pos++ = WLAN_EID_MOBILITY_DOMAIN;
190 			*pos++ = sizeof(*mdie);
191 			mdie = (struct rsn_mdie *) pos;
192 			os_memcpy(mdie->mobility_domain, md,
193 				  MOBILITY_DOMAIN_ID_LEN);
194 			mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
195 			wpa_s->sme.assoc_req_ie_len += 5;
196 		}
197 
198 		if (wpa_s->sme.ft_used &&
199 		    os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
200 		    wpa_sm_has_ptk(wpa_s->wpa)) {
201 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
202 				"over-the-air");
203 			params.auth_alg = WPA_AUTH_ALG_FT;
204 			params.ie = wpa_s->sme.ft_ies;
205 			params.ie_len = wpa_s->sme.ft_ies_len;
206 		}
207 	}
208 #endif /* CONFIG_IEEE80211R */
209 
210 #ifdef CONFIG_IEEE80211W
211 	wpa_s->sme.mfp = ssid->ieee80211w;
212 	if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
213 		const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
214 		struct wpa_ie_data _ie;
215 		if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
216 		    _ie.capabilities &
217 		    (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
218 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
219 				"MFP: require MFP");
220 			wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
221 		}
222 	}
223 #endif /* CONFIG_IEEE80211W */
224 
225 #ifdef CONFIG_P2P
226 	if (wpa_s->global->p2p) {
227 		u8 *pos;
228 		size_t len;
229 		int res;
230 		pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
231 		len = sizeof(wpa_s->sme.assoc_req_ie) -
232 			wpa_s->sme.assoc_req_ie_len;
233 		res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
234 					    ssid->p2p_group);
235 		if (res >= 0)
236 			wpa_s->sme.assoc_req_ie_len += res;
237 	}
238 #endif /* CONFIG_P2P */
239 
240 #ifdef CONFIG_INTERWORKING
241 	if (wpa_s->conf->interworking) {
242 		u8 *pos = wpa_s->sme.assoc_req_ie;
243 		if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
244 			pos += 2 + pos[1];
245 		os_memmove(pos + 6, pos,
246 			   wpa_s->sme.assoc_req_ie_len -
247 			   (pos - wpa_s->sme.assoc_req_ie));
248 		wpa_s->sme.assoc_req_ie_len += 6;
249 		*pos++ = WLAN_EID_EXT_CAPAB;
250 		*pos++ = 4;
251 		*pos++ = 0x00;
252 		*pos++ = 0x00;
253 		*pos++ = 0x00;
254 		*pos++ = 0x80; /* Bit 31 - Interworking */
255 	}
256 #endif /* CONFIG_INTERWORKING */
257 
258 	wpa_supplicant_cancel_sched_scan(wpa_s);
259 	wpa_supplicant_cancel_scan(wpa_s);
260 
261 	wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
262 		" (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
263 		wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
264 
265 	wpa_clear_keys(wpa_s, bss->bssid);
266 	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
267 	old_ssid = wpa_s->current_ssid;
268 	wpa_s->current_ssid = ssid;
269 	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
270 	wpa_supplicant_initiate_eapol(wpa_s);
271 	if (old_ssid != wpa_s->current_ssid)
272 		wpas_notify_network_changed(wpa_s);
273 
274 	wpa_s->sme.auth_alg = params.auth_alg;
275 	if (wpa_drv_authenticate(wpa_s, &params) < 0) {
276 		wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
277 			"driver failed");
278 		wpas_connection_failed(wpa_s, bss->bssid);
279 		wpa_supplicant_mark_disassoc(wpa_s);
280 		return;
281 	}
282 
283 	eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
284 			       NULL);
285 
286 	/*
287 	 * Association will be started based on the authentication event from
288 	 * the driver.
289 	 */
290 }
291 
292 
293 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
294 {
295 	struct wpa_ssid *ssid = wpa_s->current_ssid;
296 
297 	if (ssid == NULL) {
298 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
299 			"when network is not selected");
300 		return;
301 	}
302 
303 	if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
304 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
305 			"when not in authenticating state");
306 		return;
307 	}
308 
309 	if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
310 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
311 			"unexpected peer " MACSTR,
312 			MAC2STR(data->auth.peer));
313 		return;
314 	}
315 
316 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
317 		" auth_type=%d status_code=%d",
318 		MAC2STR(data->auth.peer), data->auth.auth_type,
319 		data->auth.status_code);
320 	wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
321 		    data->auth.ies, data->auth.ies_len);
322 
323 	eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
324 
325 	if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
326 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status "
327 			"code %d)", data->auth.status_code);
328 
329 		if (data->auth.status_code !=
330 		    WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
331 		    wpa_s->sme.auth_alg == data->auth.auth_type ||
332 		    wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
333 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
334 			return;
335 		}
336 
337 		switch (data->auth.auth_type) {
338 		case WLAN_AUTH_OPEN:
339 			wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
340 
341 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
342 			wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
343 						 wpa_s->current_ssid);
344 			return;
345 
346 		case WLAN_AUTH_SHARED_KEY:
347 			wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
348 
349 			wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
350 			wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
351 						 wpa_s->current_ssid);
352 			return;
353 
354 		default:
355 			return;
356 		}
357 	}
358 
359 #ifdef CONFIG_IEEE80211R
360 	if (data->auth.auth_type == WLAN_AUTH_FT) {
361 		union wpa_event_data edata;
362 		os_memset(&edata, 0, sizeof(edata));
363 		edata.ft_ies.ies = data->auth.ies;
364 		edata.ft_ies.ies_len = data->auth.ies_len;
365 		os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN);
366 		wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata);
367 	}
368 #endif /* CONFIG_IEEE80211R */
369 
370 	sme_associate(wpa_s, ssid->mode, data->auth.peer,
371 		      data->auth.auth_type);
372 }
373 
374 
375 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
376 		   const u8 *bssid, u16 auth_type)
377 {
378 	struct wpa_driver_associate_params params;
379 	struct ieee802_11_elems elems;
380 
381 	os_memset(&params, 0, sizeof(params));
382 	params.bssid = bssid;
383 	params.ssid = wpa_s->sme.ssid;
384 	params.ssid_len = wpa_s->sme.ssid_len;
385 	params.freq = wpa_s->sme.freq;
386 	params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
387 		wpa_s->sme.assoc_req_ie : NULL;
388 	params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
389 	params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
390 	params.group_suite = cipher_suite2driver(wpa_s->group_cipher);
391 #ifdef CONFIG_IEEE80211R
392 	if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
393 		params.wpa_ie = wpa_s->sme.ft_ies;
394 		params.wpa_ie_len = wpa_s->sme.ft_ies_len;
395 	}
396 #endif /* CONFIG_IEEE80211R */
397 	params.mode = mode;
398 	params.mgmt_frame_protection = wpa_s->sme.mfp;
399 	if (wpa_s->sme.prev_bssid_set)
400 		params.prev_bssid = wpa_s->sme.prev_bssid;
401 
402 	wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
403 		" (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
404 		params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
405 		params.freq);
406 
407 	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
408 
409 	if (params.wpa_ie == NULL ||
410 	    ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
411 	    < 0) {
412 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
413 		os_memset(&elems, 0, sizeof(elems));
414 	}
415 	if (elems.rsn_ie) {
416 		params.wpa_proto = WPA_PROTO_RSN;
417 		wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
418 					elems.rsn_ie_len + 2);
419 	} else if (elems.wpa_ie) {
420 		params.wpa_proto = WPA_PROTO_WPA;
421 		wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
422 					elems.wpa_ie_len + 2);
423 	} else
424 		wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
425 	if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
426 		params.p2p = 1;
427 
428 	if (wpa_s->parent->set_sta_uapsd)
429 		params.uapsd = wpa_s->parent->sta_uapsd;
430 	else
431 		params.uapsd = -1;
432 
433 	if (wpa_drv_associate(wpa_s, &params) < 0) {
434 		wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
435 			"driver failed");
436 		wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
437 		os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
438 		return;
439 	}
440 
441 	eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
442 			       NULL);
443 }
444 
445 
446 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
447 		      const u8 *ies, size_t ies_len)
448 {
449 	if (md == NULL || ies == NULL) {
450 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
451 		os_free(wpa_s->sme.ft_ies);
452 		wpa_s->sme.ft_ies = NULL;
453 		wpa_s->sme.ft_ies_len = 0;
454 		wpa_s->sme.ft_used = 0;
455 		return 0;
456 	}
457 
458 	os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
459 	wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
460 	os_free(wpa_s->sme.ft_ies);
461 	wpa_s->sme.ft_ies = os_malloc(ies_len);
462 	if (wpa_s->sme.ft_ies == NULL)
463 		return -1;
464 	os_memcpy(wpa_s->sme.ft_ies, ies, ies_len);
465 	wpa_s->sme.ft_ies_len = ies_len;
466 	return 0;
467 }
468 
469 
470 static void sme_deauth(struct wpa_supplicant *wpa_s)
471 {
472 	int bssid_changed;
473 
474 	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
475 
476 	if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
477 				   WLAN_REASON_DEAUTH_LEAVING) < 0) {
478 		wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
479 			"failed");
480 	}
481 	wpa_s->sme.prev_bssid_set = 0;
482 
483 	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
484 	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
485 	os_memset(wpa_s->bssid, 0, ETH_ALEN);
486 	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
487 	if (bssid_changed)
488 		wpas_notify_bssid_changed(wpa_s);
489 }
490 
491 
492 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
493 			    union wpa_event_data *data)
494 {
495 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
496 		"status code %d", MAC2STR(wpa_s->pending_bssid),
497 		data->assoc_reject.status_code);
498 
499 	eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
500 
501 	/*
502 	 * For now, unconditionally terminate the previous authentication. In
503 	 * theory, this should not be needed, but mac80211 gets quite confused
504 	 * if the authentication is left pending.. Some roaming cases might
505 	 * benefit from using the previous authentication, so this could be
506 	 * optimized in the future.
507 	 */
508 	sme_deauth(wpa_s);
509 }
510 
511 
512 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
513 			      union wpa_event_data *data)
514 {
515 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
516 	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
517 	wpa_supplicant_mark_disassoc(wpa_s);
518 }
519 
520 
521 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
522 			       union wpa_event_data *data)
523 {
524 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
525 	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
526 	wpa_supplicant_mark_disassoc(wpa_s);
527 }
528 
529 
530 void sme_event_disassoc(struct wpa_supplicant *wpa_s,
531 			union wpa_event_data *data)
532 {
533 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
534 	if (wpa_s->sme.prev_bssid_set) {
535 		/*
536 		 * cfg80211/mac80211 can get into somewhat confused state if
537 		 * the AP only disassociates us and leaves us in authenticated
538 		 * state. For now, force the state to be cleared to avoid
539 		 * confusing errors if we try to associate with the AP again.
540 		 */
541 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
542 			"driver state");
543 		wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
544 				       WLAN_REASON_DEAUTH_LEAVING);
545 	}
546 }
547 
548 
549 static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
550 {
551 	struct wpa_supplicant *wpa_s = eloop_ctx;
552 	if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
553 		wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
554 		sme_deauth(wpa_s);
555 	}
556 }
557 
558 
559 static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
560 {
561 	struct wpa_supplicant *wpa_s = eloop_ctx;
562 	if (wpa_s->wpa_state == WPA_ASSOCIATING) {
563 		wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
564 		sme_deauth(wpa_s);
565 	}
566 }
567 
568 
569 void sme_state_changed(struct wpa_supplicant *wpa_s)
570 {
571 	/* Make sure timers are cleaned up appropriately. */
572 	if (wpa_s->wpa_state != WPA_ASSOCIATING)
573 		eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
574 	if (wpa_s->wpa_state != WPA_AUTHENTICATING)
575 		eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
576 }
577 
578 
579 void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
580 				       const u8 *prev_pending_bssid)
581 {
582 	/*
583 	 * mac80211-workaround to force deauth on failed auth cmd,
584 	 * requires us to remain in authenticating state to allow the
585 	 * second authentication attempt to be continued properly.
586 	 */
587 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
588 		"to proceed after disconnection event");
589 	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
590 	os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
591 
592 	/*
593 	 * Re-arm authentication timer in case auth fails for whatever reason.
594 	 */
595 	eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
596 	eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
597 			       NULL);
598 }
599 
600 
601 void sme_deinit(struct wpa_supplicant *wpa_s)
602 {
603 	os_free(wpa_s->sme.ft_ies);
604 	wpa_s->sme.ft_ies = NULL;
605 	wpa_s->sme.ft_ies_len = 0;
606 #ifdef CONFIG_IEEE80211W
607 	sme_stop_sa_query(wpa_s);
608 #endif /* CONFIG_IEEE80211W */
609 
610 	eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
611 	eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
612 }
613 
614 
615 #ifdef CONFIG_IEEE80211W
616 
617 static const unsigned int sa_query_max_timeout = 1000;
618 static const unsigned int sa_query_retry_timeout = 201;
619 
620 static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
621 {
622 	u32 tu;
623 	struct os_time now, passed;
624 	os_get_time(&now);
625 	os_time_sub(&now, &wpa_s->sme.sa_query_start, &passed);
626 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
627 	if (sa_query_max_timeout < tu) {
628 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
629 		sme_stop_sa_query(wpa_s);
630 		wpa_supplicant_deauthenticate(
631 			wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
632 		return 1;
633 	}
634 
635 	return 0;
636 }
637 
638 
639 static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
640 				  const u8 *trans_id)
641 {
642 	u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN];
643 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
644 		MACSTR, MAC2STR(wpa_s->bssid));
645 	wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
646 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
647 	req[0] = WLAN_ACTION_SA_QUERY;
648 	req[1] = WLAN_SA_QUERY_REQUEST;
649 	os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
650 	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
651 				wpa_s->own_addr, wpa_s->bssid,
652 				req, sizeof(req), 0) < 0)
653 		wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
654 			"Request");
655 }
656 
657 
658 static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
659 {
660 	struct wpa_supplicant *wpa_s = eloop_ctx;
661 	unsigned int timeout, sec, usec;
662 	u8 *trans_id, *nbuf;
663 
664 	if (wpa_s->sme.sa_query_count > 0 &&
665 	    sme_check_sa_query_timeout(wpa_s))
666 		return;
667 
668 	nbuf = os_realloc(wpa_s->sme.sa_query_trans_id,
669 			  (wpa_s->sme.sa_query_count + 1) *
670 			  WLAN_SA_QUERY_TR_ID_LEN);
671 	if (nbuf == NULL)
672 		return;
673 	if (wpa_s->sme.sa_query_count == 0) {
674 		/* Starting a new SA Query procedure */
675 		os_get_time(&wpa_s->sme.sa_query_start);
676 	}
677 	trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
678 	wpa_s->sme.sa_query_trans_id = nbuf;
679 	wpa_s->sme.sa_query_count++;
680 
681 	os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN);
682 
683 	timeout = sa_query_retry_timeout;
684 	sec = ((timeout / 1000) * 1024) / 1000;
685 	usec = (timeout % 1000) * 1024;
686 	eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
687 
688 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
689 		wpa_s->sme.sa_query_count);
690 
691 	sme_send_sa_query_req(wpa_s, trans_id);
692 }
693 
694 
695 static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
696 {
697 	sme_sa_query_timer(wpa_s, NULL);
698 }
699 
700 
701 void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
702 {
703 	eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
704 	os_free(wpa_s->sme.sa_query_trans_id);
705 	wpa_s->sme.sa_query_trans_id = NULL;
706 	wpa_s->sme.sa_query_count = 0;
707 }
708 
709 
710 void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
711 				 const u8 *da, u16 reason_code)
712 {
713 	struct wpa_ssid *ssid;
714 
715 	if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
716 		return;
717 	if (wpa_s->wpa_state != WPA_COMPLETED)
718 		return;
719 	ssid = wpa_s->current_ssid;
720 	if (ssid == NULL || ssid->ieee80211w == 0)
721 		return;
722 	if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
723 		return;
724 	if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
725 	    reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
726 		return;
727 	if (wpa_s->sme.sa_query_count > 0)
728 		return;
729 
730 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
731 		"possible AP/STA state mismatch - trigger SA Query");
732 	sme_start_sa_query(wpa_s);
733 }
734 
735 
736 void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
737 		     const u8 *data, size_t len)
738 {
739 	int i;
740 
741 	if (wpa_s->sme.sa_query_trans_id == NULL ||
742 	    len < 1 + WLAN_SA_QUERY_TR_ID_LEN ||
743 	    data[0] != WLAN_SA_QUERY_RESPONSE)
744 		return;
745 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
746 		MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
747 
748 	if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
749 		return;
750 
751 	for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
752 		if (os_memcmp(wpa_s->sme.sa_query_trans_id +
753 			      i * WLAN_SA_QUERY_TR_ID_LEN,
754 			      data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
755 			break;
756 	}
757 
758 	if (i >= wpa_s->sme.sa_query_count) {
759 		wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
760 			"transaction identifier found");
761 		return;
762 	}
763 
764 	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
765 		"from " MACSTR, MAC2STR(sa));
766 	sme_stop_sa_query(wpa_s);
767 }
768 
769 #endif /* CONFIG_IEEE80211W */
770