blob: 7c0d2e8f44736ae8e04fa82524f05d7677f4fc23 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - Driver event processing
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003 * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "eapol_supp/eapol_supp_sm.h"
13#include "rsn_supp/wpa.h"
14#include "eloop.h"
15#include "config.h"
16#include "l2_packet/l2_packet.h"
17#include "wpa_supplicant_i.h"
18#include "driver_i.h"
19#include "pcsc_funcs.h"
20#include "rsn_supp/preauth.h"
21#include "rsn_supp/pmksa_cache.h"
22#include "common/wpa_ctrl.h"
23#include "eap_peer/eap.h"
24#include "ap/hostapd.h"
25#include "p2p/p2p.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070026#include "wnm_sta.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "notify.h"
28#include "common/ieee802_11_defs.h"
29#include "common/ieee802_11_common.h"
30#include "crypto/random.h"
31#include "blacklist.h"
32#include "wpas_glue.h"
33#include "wps_supplicant.h"
34#include "ibss_rsn.h"
35#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080036#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037#include "p2p_supplicant.h"
38#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070039#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040#include "ap.h"
41#include "bss.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080043#include "offchannel.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070044#include "interworking.h"
45
46
Dmitry Shmidt34af3062013-07-11 10:46:32 -070047#ifndef CONFIG_NO_SCAN_PROCESSING
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070048static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
49 int new_scan);
Dmitry Shmidt34af3062013-07-11 10:46:32 -070050#endif /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -080051
52
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070053static int wpas_temp_disabled(struct wpa_supplicant *wpa_s,
54 struct wpa_ssid *ssid)
55{
56 struct os_time now;
57
58 if (ssid == NULL || ssid->disabled_until.sec == 0)
59 return 0;
60
61 os_get_time(&now);
62 if (ssid->disabled_until.sec > now.sec)
63 return ssid->disabled_until.sec - now.sec;
64
65 wpas_clear_temp_disabled(wpa_s, ssid, 0);
66
67 return 0;
68}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070069
70
71static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
72{
73 struct wpa_ssid *ssid, *old_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070074 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070075
76 if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid)
77 return 0;
78
79 wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association "
80 "information");
81 ssid = wpa_supplicant_get_ssid(wpa_s);
82 if (ssid == NULL) {
83 wpa_msg(wpa_s, MSG_INFO,
84 "No network configuration found for the current AP");
85 return -1;
86 }
87
Dmitry Shmidt04949592012-07-19 12:16:46 -070088 if (wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070089 wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is disabled");
90 return -1;
91 }
92
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080093 if (disallowed_bssid(wpa_s, wpa_s->bssid) ||
94 disallowed_ssid(wpa_s, ssid->ssid, ssid->ssid_len)) {
95 wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS is disallowed");
96 return -1;
97 }
98
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099 res = wpas_temp_disabled(wpa_s, ssid);
100 if (res > 0) {
101 wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is temporarily "
102 "disabled for %d second(s)", res);
103 return -1;
104 }
105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106 wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the "
107 "current AP");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800108 if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700109 u8 wpa_ie[80];
110 size_t wpa_ie_len = sizeof(wpa_ie);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800111 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
112 wpa_ie, &wpa_ie_len) < 0)
113 wpa_dbg(wpa_s, MSG_DEBUG, "Could not set WPA suites");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114 } else {
115 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
116 }
117
118 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid)
119 eapol_sm_invalidate_cached_session(wpa_s->eapol);
120 old_ssid = wpa_s->current_ssid;
121 wpa_s->current_ssid = ssid;
122 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
123 wpa_supplicant_initiate_eapol(wpa_s);
124 if (old_ssid != wpa_s->current_ssid)
125 wpas_notify_network_changed(wpa_s);
126
127 return 0;
128}
129
130
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800131void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700132{
133 struct wpa_supplicant *wpa_s = eloop_ctx;
134
135 if (wpa_s->countermeasures) {
136 wpa_s->countermeasures = 0;
137 wpa_drv_set_countermeasures(wpa_s, 0);
138 wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped");
139 wpa_supplicant_req_scan(wpa_s, 0, 0);
140 }
141}
142
143
144void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
145{
146 int bssid_changed;
147
Dmitry Shmidt04949592012-07-19 12:16:46 -0700148 wnm_bss_keep_alive_deinit(wpa_s);
149
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150#ifdef CONFIG_IBSS_RSN
151 ibss_rsn_deinit(wpa_s->ibss_rsn);
152 wpa_s->ibss_rsn = NULL;
153#endif /* CONFIG_IBSS_RSN */
154
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700155#ifdef CONFIG_AP
156 wpa_supplicant_ap_deinit(wpa_s);
157#endif /* CONFIG_AP */
158
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700159 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
160 return;
161
162 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800163#ifdef ANDROID
Dmitry Shmidt43007fd2011-04-11 15:58:40 -0700164 wpa_s->conf->ap_scan = DEFAULT_AP_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800165#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700166 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
167 os_memset(wpa_s->bssid, 0, ETH_ALEN);
168 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700169#ifdef CONFIG_SME
170 wpa_s->sme.prev_bssid_set = 0;
171#endif /* CONFIG_SME */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800172#ifdef CONFIG_P2P
173 os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
174#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700175 wpa_s->current_bss = NULL;
176 wpa_s->assoc_freq = 0;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700177#ifdef CONFIG_IEEE80211R
178#ifdef CONFIG_SME
179 if (wpa_s->sme.ft_ies)
180 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
181#endif /* CONFIG_SME */
182#endif /* CONFIG_IEEE80211R */
183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700184 if (bssid_changed)
185 wpas_notify_bssid_changed(wpa_s);
186
187 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
188 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
189 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
190 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
191 wpa_s->ap_ies_from_associnfo = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700192 wpa_s->current_ssid = NULL;
193 wpa_s->key_mgmt = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194}
195
196
197static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s)
198{
199 struct wpa_ie_data ie;
200 int pmksa_set = -1;
201 size_t i;
202
203 if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 ||
204 ie.pmkid == NULL)
205 return;
206
207 for (i = 0; i < ie.num_pmkid; i++) {
208 pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
209 ie.pmkid + i * PMKID_LEN,
210 NULL, NULL, 0);
211 if (pmksa_set == 0) {
212 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
213 break;
214 }
215 }
216
217 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from "
218 "PMKSA cache", pmksa_set == 0 ? "" : "not ");
219}
220
221
222static void wpa_supplicant_event_pmkid_candidate(struct wpa_supplicant *wpa_s,
223 union wpa_event_data *data)
224{
225 if (data == NULL) {
226 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: No data in PMKID candidate "
227 "event");
228 return;
229 }
230 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR
231 " index=%d preauth=%d",
232 MAC2STR(data->pmkid_candidate.bssid),
233 data->pmkid_candidate.index,
234 data->pmkid_candidate.preauth);
235
236 pmksa_candidate_add(wpa_s->wpa, data->pmkid_candidate.bssid,
237 data->pmkid_candidate.index,
238 data->pmkid_candidate.preauth);
239}
240
241
242static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s)
243{
244 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
245 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
246 return 0;
247
248#ifdef IEEE8021X_EAPOL
249 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
250 wpa_s->current_ssid &&
251 !(wpa_s->current_ssid->eapol_flags &
252 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
253 EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) {
254 /* IEEE 802.1X, but not using dynamic WEP keys (i.e., either
255 * plaintext or static WEP keys). */
256 return 0;
257 }
258#endif /* IEEE8021X_EAPOL */
259
260 return 1;
261}
262
263
264/**
265 * wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC
266 * @wpa_s: pointer to wpa_supplicant data
267 * @ssid: Configuration data for the network
268 * Returns: 0 on success, -1 on failure
269 *
270 * This function is called when starting authentication with a network that is
271 * configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA).
272 */
273int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
274 struct wpa_ssid *ssid)
275{
276#ifdef IEEE8021X_EAPOL
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800277#ifdef PCSC_FUNCS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700278 int aka = 0, sim = 0, type;
279
280 if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL)
281 return 0;
282
283 if (ssid->eap.eap_methods == NULL) {
284 sim = 1;
285 aka = 1;
286 } else {
287 struct eap_method_type *eap = ssid->eap.eap_methods;
288 while (eap->vendor != EAP_VENDOR_IETF ||
289 eap->method != EAP_TYPE_NONE) {
290 if (eap->vendor == EAP_VENDOR_IETF) {
291 if (eap->method == EAP_TYPE_SIM)
292 sim = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700293 else if (eap->method == EAP_TYPE_AKA ||
294 eap->method == EAP_TYPE_AKA_PRIME)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700295 aka = 1;
296 }
297 eap++;
298 }
299 }
300
301 if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL)
302 sim = 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700303 if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL &&
304 eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME) ==
305 NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700306 aka = 0;
307
308 if (!sim && !aka) {
309 wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to "
310 "use SIM, but neither EAP-SIM nor EAP-AKA are "
311 "enabled");
312 return 0;
313 }
314
315 wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM "
316 "(sim=%d aka=%d) - initialize PCSC", sim, aka);
317 if (sim && aka)
318 type = SCARD_TRY_BOTH;
319 else if (aka)
320 type = SCARD_USIM_ONLY;
321 else
322 type = SCARD_GSM_SIM_ONLY;
323
Dmitry Shmidt04949592012-07-19 12:16:46 -0700324 wpa_s->scard = scard_init(type, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 if (wpa_s->scard == NULL) {
326 wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
327 "(pcsc-lite)");
328 return -1;
329 }
330 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
331 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800332#endif /* PCSC_FUNCS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333#endif /* IEEE8021X_EAPOL */
334
335 return 0;
336}
337
338
339#ifndef CONFIG_NO_SCAN_PROCESSING
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700340static int wpa_supplicant_match_privacy(struct wpa_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700341 struct wpa_ssid *ssid)
342{
343 int i, privacy = 0;
344
345 if (ssid->mixed_cell)
346 return 1;
347
348#ifdef CONFIG_WPS
349 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
350 return 1;
351#endif /* CONFIG_WPS */
352
353 for (i = 0; i < NUM_WEP_KEYS; i++) {
354 if (ssid->wep_key_len[i]) {
355 privacy = 1;
356 break;
357 }
358 }
359#ifdef IEEE8021X_EAPOL
360 if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
361 ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
362 EAPOL_FLAG_REQUIRE_KEY_BROADCAST))
363 privacy = 1;
364#endif /* IEEE8021X_EAPOL */
365
Jouni Malinen75ecf522011-06-27 15:19:46 -0700366 if (wpa_key_mgmt_wpa(ssid->key_mgmt))
367 privacy = 1;
368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700369 if (bss->caps & IEEE80211_CAP_PRIVACY)
370 return privacy;
371 return !privacy;
372}
373
374
375static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
376 struct wpa_ssid *ssid,
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700377 struct wpa_bss *bss)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700378{
379 struct wpa_ie_data ie;
380 int proto_match = 0;
381 const u8 *rsn_ie, *wpa_ie;
382 int ret;
383 int wep_ok;
384
385 ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss);
386 if (ret >= 0)
387 return ret;
388
389 /* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */
390 wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) &&
391 (((ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
392 ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) ||
393 (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA));
394
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700395 rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700396 while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) {
397 proto_match++;
398
399 if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
400 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - parse "
401 "failed");
402 break;
403 }
404
405 if (wep_ok &&
406 (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
407 {
408 wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
409 "in RSN IE");
410 return 1;
411 }
412
413 if (!(ie.proto & ssid->proto)) {
414 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - proto "
415 "mismatch");
416 break;
417 }
418
419 if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
420 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - PTK "
421 "cipher mismatch");
422 break;
423 }
424
425 if (!(ie.group_cipher & ssid->group_cipher)) {
426 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - GTK "
427 "cipher mismatch");
428 break;
429 }
430
431 if (!(ie.key_mgmt & ssid->key_mgmt)) {
432 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - key mgmt "
433 "mismatch");
434 break;
435 }
436
437#ifdef CONFIG_IEEE80211W
438 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800439 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
440 wpa_s->conf->pmf : ssid->ieee80211w) ==
441 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt "
443 "frame protection");
444 break;
445 }
446#endif /* CONFIG_IEEE80211W */
447
448 wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE");
449 return 1;
450 }
451
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700452 wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700453 while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
454 proto_match++;
455
456 if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) {
457 wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse "
458 "failed");
459 break;
460 }
461
462 if (wep_ok &&
463 (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)))
464 {
465 wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN "
466 "in WPA IE");
467 return 1;
468 }
469
470 if (!(ie.proto & ssid->proto)) {
471 wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto "
472 "mismatch");
473 break;
474 }
475
476 if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) {
477 wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK "
478 "cipher mismatch");
479 break;
480 }
481
482 if (!(ie.group_cipher & ssid->group_cipher)) {
483 wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK "
484 "cipher mismatch");
485 break;
486 }
487
488 if (!(ie.key_mgmt & ssid->key_mgmt)) {
489 wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt "
490 "mismatch");
491 break;
492 }
493
494 wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE");
495 return 1;
496 }
497
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700498 if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie &&
499 !rsn_ie) {
500 wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X");
501 return 1;
502 }
503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700504 if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) &&
505 wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) {
506 wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match");
507 return 0;
508 }
509
510 if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) {
511 wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2");
512 return 1;
513 }
514
515 wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with "
516 "WPA/WPA2");
517
518 return 0;
519}
520
521
522static int freq_allowed(int *freqs, int freq)
523{
524 int i;
525
526 if (freqs == NULL)
527 return 1;
528
529 for (i = 0; freqs[i]; i++)
530 if (freqs[i] == freq)
531 return 1;
532 return 0;
533}
534
535
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800536static int ht_supported(const struct hostapd_hw_modes *mode)
537{
538 if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
539 /*
540 * The driver did not indicate whether it supports HT. Assume
541 * it does to avoid connection issues.
542 */
543 return 1;
544 }
545
546 /*
547 * IEEE Std 802.11n-2009 20.1.1:
548 * An HT non-AP STA shall support all EQM rates for one spatial stream.
549 */
550 return mode->mcs_set[0] == 0xff;
551}
552
553
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700554static int vht_supported(const struct hostapd_hw_modes *mode)
555{
556 if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
557 /*
558 * The driver did not indicate whether it supports VHT. Assume
559 * it does to avoid connection issues.
560 */
561 return 1;
562 }
563
564 /*
565 * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
566 * TODO: Verify if this complies with the standard
567 */
568 return (mode->vht_mcs_set[0] & 0x3) != 3;
569}
570
571
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700572static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800573{
574 const struct hostapd_hw_modes *mode = NULL, *modes;
575 const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES };
576 const u8 *rate_ie;
577 int i, j, k;
578
579 if (bss->freq == 0)
580 return 1; /* Cannot do matching without knowing band */
581
582 modes = wpa_s->hw.modes;
583 if (modes == NULL) {
584 /*
585 * The driver does not provide any additional information
586 * about the utilized hardware, so allow the connection attempt
587 * to continue.
588 */
589 return 1;
590 }
591
592 for (i = 0; i < wpa_s->hw.num_modes; i++) {
593 for (j = 0; j < modes[i].num_channels; j++) {
594 int freq = modes[i].channels[j].freq;
595 if (freq == bss->freq) {
596 if (mode &&
597 mode->mode == HOSTAPD_MODE_IEEE80211G)
598 break; /* do not allow 802.11b replace
599 * 802.11g */
600 mode = &modes[i];
601 break;
602 }
603 }
604 }
605
606 if (mode == NULL)
607 return 0;
608
609 for (i = 0; i < (int) sizeof(scan_ie); i++) {
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700610 rate_ie = wpa_bss_get_ie(bss, scan_ie[i]);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800611 if (rate_ie == NULL)
612 continue;
613
614 for (j = 2; j < rate_ie[1] + 2; j++) {
615 int flagged = !!(rate_ie[j] & 0x80);
616 int r = (rate_ie[j] & 0x7f) * 5;
617
618 /*
619 * IEEE Std 802.11n-2009 7.3.2.2:
620 * The new BSS Membership selector value is encoded
621 * like a legacy basic rate, but it is not a rate and
622 * only indicates if the BSS members are required to
623 * support the mandatory features of Clause 20 [HT PHY]
624 * in order to join the BSS.
625 */
626 if (flagged && ((rate_ie[j] & 0x7f) ==
627 BSS_MEMBERSHIP_SELECTOR_HT_PHY)) {
628 if (!ht_supported(mode)) {
629 wpa_dbg(wpa_s, MSG_DEBUG,
630 " hardware does not support "
631 "HT PHY");
632 return 0;
633 }
634 continue;
635 }
636
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700637 /* There's also a VHT selector for 802.11ac */
638 if (flagged && ((rate_ie[j] & 0x7f) ==
639 BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) {
640 if (!vht_supported(mode)) {
641 wpa_dbg(wpa_s, MSG_DEBUG,
642 " hardware does not support "
643 "VHT PHY");
644 return 0;
645 }
646 continue;
647 }
648
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800649 if (!flagged)
650 continue;
651
652 /* check for legacy basic rates */
653 for (k = 0; k < mode->num_rates; k++) {
654 if (mode->rates[k] == r)
655 break;
656 }
657 if (k == mode->num_rates) {
658 /*
659 * IEEE Std 802.11-2007 7.3.2.2 demands that in
660 * order to join a BSS all required rates
661 * have to be supported by the hardware.
662 */
663 wpa_dbg(wpa_s, MSG_DEBUG, " hardware does "
664 "not support required rate %d.%d Mbps",
665 r / 10, r % 10);
666 return 0;
667 }
668 }
669 }
670
671 return 1;
672}
673
674
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800675static int bss_is_dmg(struct wpa_bss *bss)
676{
677 return bss->freq > 45000;
678}
679
680
681/*
682 * Test whether BSS is in an ESS.
683 * This is done differently in DMG (60 GHz) and non-DMG bands
684 */
685static int bss_is_ess(struct wpa_bss *bss)
686{
687 if (bss_is_dmg(bss)) {
688 return (bss->caps & IEEE80211_CAP_DMG_MASK) ==
689 IEEE80211_CAP_DMG_AP;
690 }
691
692 return ((bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) ==
693 IEEE80211_CAP_ESS);
694}
695
696
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700698 int i, struct wpa_bss *bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 struct wpa_ssid *group)
700{
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700701 u8 wpa_ie_len, rsn_ie_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702 int wpa;
703 struct wpa_blacklist *e;
704 const u8 *ie;
705 struct wpa_ssid *ssid;
706
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700707 ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708 wpa_ie_len = ie ? ie[1] : 0;
709
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700710 ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 rsn_ie_len = ie ? ie[1] : 0;
712
713 wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
714 "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s",
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700715 i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716 wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700717 wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718
719 e = wpa_blacklist_get(wpa_s, bss->bssid);
720 if (e) {
721 int limit = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700722 if (wpa_supplicant_enabled_networks(wpa_s) == 1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700723 /*
724 * When only a single network is enabled, we can
725 * trigger blacklisting on the first failure. This
726 * should not be done with multiple enabled networks to
727 * avoid getting forced to move into a worse ESS on
728 * single error if there are no other BSSes of the
729 * current ESS.
730 */
731 limit = 0;
732 }
733 if (e->count > limit) {
734 wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
735 "(count=%d limit=%d)", e->count, limit);
736 return NULL;
737 }
738 }
739
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700740 if (bss->ssid_len == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741 wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known");
742 return NULL;
743 }
744
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800745 if (disallowed_bssid(wpa_s, bss->bssid)) {
746 wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed");
747 return NULL;
748 }
749
750 if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) {
751 wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed");
752 return NULL;
753 }
754
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755 wpa = wpa_ie_len > 0 || rsn_ie_len > 0;
756
757 for (ssid = group; ssid; ssid = ssid->pnext) {
758 int check_ssid = wpa ? 1 : (ssid->ssid_len != 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700759 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760
Dmitry Shmidt04949592012-07-19 12:16:46 -0700761 if (wpas_network_disabled(wpa_s, ssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762 wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled");
763 continue;
764 }
765
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700766 res = wpas_temp_disabled(wpa_s, ssid);
767 if (res > 0) {
768 wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled "
769 "temporarily for %d second(s)", res);
770 continue;
771 }
772
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773#ifdef CONFIG_WPS
774 if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) {
775 wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted "
776 "(WPS)");
777 continue;
778 }
779
780 if (wpa && ssid->ssid_len == 0 &&
781 wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
782 check_ssid = 0;
783
784 if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
785 /* Only allow wildcard SSID match if an AP
786 * advertises active WPS operation that matches
787 * with our mode. */
788 check_ssid = 1;
789 if (ssid->ssid_len == 0 &&
790 wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss))
791 check_ssid = 0;
792 }
793#endif /* CONFIG_WPS */
794
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800795 if (ssid->bssid_set && ssid->ssid_len == 0 &&
796 os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0)
797 check_ssid = 0;
798
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700799 if (check_ssid &&
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700800 (bss->ssid_len != ssid->ssid_len ||
801 os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch");
803 continue;
804 }
805
806 if (ssid->bssid_set &&
807 os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) {
808 wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch");
809 continue;
810 }
811
812 if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss))
813 continue;
814
815 if (!wpa &&
816 !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) &&
817 !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) &&
818 !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) {
819 wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network "
820 "not allowed");
821 continue;
822 }
823
Jouni Malinen75ecf522011-06-27 15:19:46 -0700824 if (!wpa_supplicant_match_privacy(bss, ssid)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825 wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy "
826 "mismatch");
827 continue;
828 }
829
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800830 if (!bss_is_ess(bss)) {
831 wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 continue;
833 }
834
835 if (!freq_allowed(ssid->freq_list, bss->freq)) {
836 wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not "
837 "allowed");
838 continue;
839 }
840
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800841 if (!rate_match(wpa_s, bss)) {
842 wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do "
843 "not match");
844 continue;
845 }
846
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847#ifdef CONFIG_P2P
848 /*
849 * TODO: skip the AP if its P2P IE has Group Formation
850 * bit set in the P2P Group Capability Bitmap and we
851 * are not in Group Formation with that device.
852 */
853#endif /* CONFIG_P2P */
854
855 /* Matching configuration found */
856 return ssid;
857 }
858
859 /* No matching configuration found */
860 return NULL;
861}
862
863
864static struct wpa_bss *
865wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866 struct wpa_ssid *group,
867 struct wpa_ssid **selected_ssid)
868{
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700869 unsigned int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700870
871 wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d",
872 group->priority);
873
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700874 for (i = 0; i < wpa_s->last_scan_res_used; i++) {
875 struct wpa_bss *bss = wpa_s->last_scan_res[i];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876 *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group);
877 if (!*selected_ssid)
878 continue;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879 wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
880 " ssid='%s'",
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700881 MAC2STR(bss->bssid),
882 wpa_ssid_txt(bss->ssid, bss->ssid_len));
883 return bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884 }
885
886 return NULL;
887}
888
889
Dmitry Shmidt444d5672013-04-01 13:08:44 -0700890struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
891 struct wpa_ssid **selected_ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892{
893 struct wpa_bss *selected = NULL;
894 int prio;
895
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700896 if (wpa_s->last_scan_res == NULL ||
897 wpa_s->last_scan_res_used == 0)
898 return NULL; /* no scan results from last update */
899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900 while (selected == NULL) {
901 for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
902 selected = wpa_supplicant_select_bss(
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700903 wpa_s, wpa_s->conf->pssid[prio],
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700904 selected_ssid);
905 if (selected)
906 break;
907 }
908
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800909 if (selected == NULL && wpa_s->blacklist &&
910 !wpa_s->countermeasures) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911 wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear "
912 "blacklist and try again");
913 wpa_blacklist_clear(wpa_s);
914 wpa_s->blacklist_cleared++;
915 } else if (selected == NULL)
916 break;
917 }
918
919 return selected;
920}
921
922
923static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
924 int timeout_sec, int timeout_usec)
925{
Dmitry Shmidt04949592012-07-19 12:16:46 -0700926 if (!wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927 /*
928 * No networks are enabled; short-circuit request so
929 * we don't wait timeout seconds before transitioning
930 * to INACTIVE state.
931 */
Dmitry Shmidtaa532512012-09-24 10:35:31 -0700932 wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request "
933 "since there are no enabled networks");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700934 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
Dmitry Shmidtaa532512012-09-24 10:35:31 -0700935#ifdef CONFIG_P2P
936 wpa_s->sta_scan_pending = 0;
937#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700938 return;
939 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800940
941 wpa_s->scan_for_connection = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942 wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec);
943}
944
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800945
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700946int wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800947 struct wpa_bss *selected,
948 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700949{
950 if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) {
951 wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP
952 "PBC session overlap");
953#ifdef CONFIG_P2P
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800954 if (wpas_p2p_notif_pbc_overlap(wpa_s) == 1)
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700955 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956#endif /* CONFIG_P2P */
957
958#ifdef CONFIG_WPS
959 wpas_wps_cancel(wpa_s);
960#endif /* CONFIG_WPS */
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700961 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 }
963
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700964 wpa_msg(wpa_s, MSG_DEBUG,
965 "Considering connect request: reassociate: %d selected: "
966 MACSTR " bssid: " MACSTR " pending: " MACSTR
967 " wpa_state: %s ssid=%p current_ssid=%p",
968 wpa_s->reassociate, MAC2STR(selected->bssid),
969 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
970 wpa_supplicant_state_txt(wpa_s->wpa_state),
971 ssid, wpa_s->current_ssid);
972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973 /*
974 * Do not trigger new association unless the BSSID has changed or if
975 * reassociation is requested. If we are in process of associating with
976 * the selected BSSID, do not trigger new attempt.
977 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800978 if (wpa_s->reassociate ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 &&
980 ((wpa_s->wpa_state != WPA_ASSOCIATING &&
981 wpa_s->wpa_state != WPA_AUTHENTICATING) ||
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700982 (!is_zero_ether_addr(wpa_s->pending_bssid) &&
983 os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) !=
984 0) ||
985 (is_zero_ether_addr(wpa_s->pending_bssid) &&
986 ssid != wpa_s->current_ssid)))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987 if (wpa_supplicant_scard_init(wpa_s, ssid)) {
988 wpa_supplicant_req_new_scan(wpa_s, 10, 0);
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700989 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700990 }
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700991 wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR,
992 MAC2STR(selected->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 wpa_supplicant_associate(wpa_s, selected, ssid);
994 } else {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700995 wpa_dbg(wpa_s, MSG_DEBUG, "Already associated or trying to "
996 "connect with the selected AP");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700997 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800998
Dmitry Shmidt44da0252011-08-23 12:30:30 -0700999 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000}
1001
1002
1003static struct wpa_ssid *
1004wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s)
1005{
1006 int prio;
1007 struct wpa_ssid *ssid;
1008
1009 for (prio = 0; prio < wpa_s->conf->num_prio; prio++) {
1010 for (ssid = wpa_s->conf->pssid[prio]; ssid; ssid = ssid->pnext)
1011 {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001012 if (wpas_network_disabled(wpa_s, ssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 continue;
1014 if (ssid->mode == IEEE80211_MODE_IBSS ||
1015 ssid->mode == IEEE80211_MODE_AP)
1016 return ssid;
1017 }
1018 }
1019 return NULL;
1020}
1021
1022
1023/* TODO: move the rsn_preauth_scan_result*() to be called from notify.c based
1024 * on BSS added and BSS changed events */
1025static void wpa_supplicant_rsn_preauth_scan_results(
Jouni Malinen87fd2792011-05-16 18:35:42 +03001026 struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027{
Jouni Malinen87fd2792011-05-16 18:35:42 +03001028 struct wpa_bss *bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001029
1030 if (rsn_preauth_scan_results(wpa_s->wpa) < 0)
1031 return;
1032
Jouni Malinen87fd2792011-05-16 18:35:42 +03001033 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 const u8 *ssid, *rsn;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035
Jouni Malinen87fd2792011-05-16 18:35:42 +03001036 ssid = wpa_bss_get_ie(bss, WLAN_EID_SSID);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037 if (ssid == NULL)
1038 continue;
1039
Jouni Malinen87fd2792011-05-16 18:35:42 +03001040 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001041 if (rsn == NULL)
1042 continue;
1043
Jouni Malinen87fd2792011-05-16 18:35:42 +03001044 rsn_preauth_scan_result(wpa_s->wpa, bss->bssid, ssid, rsn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045 }
1046
1047}
1048
1049
1050static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s,
1051 struct wpa_bss *selected,
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001052 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001053{
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001054 struct wpa_bss *current_bss = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001055 int min_diff;
1056
1057 if (wpa_s->reassociate)
1058 return 1; /* explicit request to reassociate */
1059 if (wpa_s->wpa_state < WPA_ASSOCIATED)
1060 return 1; /* we are not associated; continue */
1061 if (wpa_s->current_ssid == NULL)
1062 return 1; /* unknown current SSID */
1063 if (wpa_s->current_ssid != ssid)
1064 return 1; /* different network block */
1065
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001066 if (wpas_driver_bss_selection(wpa_s))
1067 return 0; /* Driver-based roaming */
1068
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001069 if (wpa_s->current_ssid->ssid)
1070 current_bss = wpa_bss_get(wpa_s, wpa_s->bssid,
1071 wpa_s->current_ssid->ssid,
1072 wpa_s->current_ssid->ssid_len);
1073 if (!current_bss)
1074 current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075
1076 if (!current_bss)
1077 return 1; /* current BSS not seen in scan results */
1078
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001079 if (current_bss == selected)
1080 return 0;
1081
1082 if (selected->last_update_idx > current_bss->last_update_idx)
1083 return 1; /* current BSS not seen in the last scan */
1084
Dmitry Shmidt9e077672012-04-13 10:07:27 -07001085#ifndef CONFIG_NO_ROAMING
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001086 wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation");
1087 wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR " level=%d",
1088 MAC2STR(current_bss->bssid), current_bss->level);
1089 wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR " level=%d",
1090 MAC2STR(selected->bssid), selected->level);
1091
1092 if (wpa_s->current_ssid->bssid_set &&
1093 os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) ==
1094 0) {
1095 wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS "
1096 "has preferred BSSID");
1097 return 1;
1098 }
1099
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001100 if (current_bss->level < 0 && current_bss->level > selected->level) {
1101 wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
1102 "signal level");
1103 return 0;
1104 }
1105
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 min_diff = 2;
1107 if (current_bss->level < 0) {
1108 if (current_bss->level < -85)
1109 min_diff = 1;
1110 else if (current_bss->level < -80)
1111 min_diff = 2;
1112 else if (current_bss->level < -75)
1113 min_diff = 3;
1114 else if (current_bss->level < -70)
1115 min_diff = 4;
1116 else
1117 min_diff = 5;
1118 }
1119 if (abs(current_bss->level - selected->level) < min_diff) {
1120 wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
1121 "in signal level");
1122 return 0;
1123 }
1124
1125 return 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001126#else /* CONFIG_NO_ROAMING */
Dmitry Shmidtefdec2e2011-08-16 11:55:46 -07001127 return 0;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001128#endif /* CONFIG_NO_ROAMING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129}
1130
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001131
Jouni Malinen89ca7022012-09-14 13:03:12 -07001132/* Return != 0 if no scan results could be fetched or if scan results should not
Dmitry Shmidt04949592012-07-19 12:16:46 -07001133 * be shared with other virtual interfaces. */
Dmitry Shmidtf6c92c42012-01-26 12:57:43 -08001134static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001135 union wpa_event_data *data,
1136 int own_request)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 struct wpa_scan_results *scan_res;
1139 int ap = 0;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001140#ifndef CONFIG_NO_RANDOM_POOL
1141 size_t i, num;
1142#endif /* CONFIG_NO_RANDOM_POOL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001143
1144#ifdef CONFIG_AP
1145 if (wpa_s->ap_iface)
1146 ap = 1;
1147#endif /* CONFIG_AP */
1148
1149 wpa_supplicant_notify_scanning(wpa_s, 0);
1150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001151#ifdef CONFIG_P2P
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001152 if (own_request && wpa_s->global->p2p_cb_on_scan_complete &&
Jouni Malinendc7b7132012-09-14 12:53:47 -07001153 !wpa_s->global->p2p_disabled &&
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001154 wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending &&
1155 !wpa_s->scan_res_handler) {
Jouni Malinendc7b7132012-09-14 12:53:47 -07001156 wpa_s->global->p2p_cb_on_scan_complete = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001157 if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
1158 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation "
1159 "stopped scan processing");
Jouni Malinenfa08f9e2012-09-13 18:05:55 -07001160 wpa_s->sta_scan_pending = 1;
1161 wpa_supplicant_req_scan(wpa_s, 5, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001162 return -1;
1163 }
1164 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001165 wpa_s->sta_scan_pending = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001166#endif /* CONFIG_P2P */
1167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168 scan_res = wpa_supplicant_get_scan_results(wpa_s,
1169 data ? &data->scan_info :
1170 NULL, 1);
1171 if (scan_res == NULL) {
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001172 if (wpa_s->conf->ap_scan == 2 || ap ||
1173 wpa_s->scan_res_handler == scan_only_handler)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 return -1;
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001175 if (!own_request)
1176 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
1178 "scanning again");
1179 wpa_supplicant_req_new_scan(wpa_s, 1, 0);
1180 return -1;
1181 }
1182
1183#ifndef CONFIG_NO_RANDOM_POOL
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 num = scan_res->num;
1185 if (num > 10)
1186 num = 10;
1187 for (i = 0; i < num; i++) {
1188 u8 buf[5];
1189 struct wpa_scan_res *res = scan_res->res[i];
1190 buf[0] = res->bssid[5];
1191 buf[1] = res->qual & 0xff;
1192 buf[2] = res->noise & 0xff;
1193 buf[3] = res->level & 0xff;
1194 buf[4] = res->tsf & 0xff;
1195 random_add_randomness(buf, sizeof(buf));
1196 }
1197#endif /* CONFIG_NO_RANDOM_POOL */
1198
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001199 if (own_request && wpa_s->scan_res_handler) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001200 void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
1201 struct wpa_scan_results *scan_res);
1202
1203 scan_res_handler = wpa_s->scan_res_handler;
1204 wpa_s->scan_res_handler = NULL;
1205 scan_res_handler(wpa_s, scan_res);
1206
1207 wpa_scan_results_free(scan_res);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001208 return -2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209 }
1210
1211 if (ap) {
1212 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode");
1213#ifdef CONFIG_AP
1214 if (wpa_s->ap_iface->scan_cb)
1215 wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
1216#endif /* CONFIG_AP */
1217 wpa_scan_results_free(scan_res);
1218 return 0;
1219 }
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001220
Dmitry Shmidt04949592012-07-19 12:16:46 -07001221 wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available");
1222 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);
1223 wpas_notify_scan_results(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224
1225 wpas_notify_scan_done(wpa_s, 1);
1226
Dmitry Shmidt04949592012-07-19 12:16:46 -07001227 if (sme_proc_obss_scan(wpa_s) > 0) {
1228 wpa_scan_results_free(scan_res);
1229 return 0;
1230 }
1231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001232 if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
1233 wpa_scan_results_free(scan_res);
1234 return 0;
1235 }
1236
Dmitry Shmidt04949592012-07-19 12:16:46 -07001237 if (autoscan_notify_scan(wpa_s, scan_res)) {
1238 wpa_scan_results_free(scan_res);
1239 return 0;
1240 }
1241
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001242 if (wpa_s->disconnected) {
1243 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1244 wpa_scan_results_free(scan_res);
1245 return 0;
1246 }
1247
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001248 if (!wpas_driver_bss_selection(wpa_s) &&
1249 bgscan_notify_scan(wpa_s, scan_res) == 1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001250 wpa_scan_results_free(scan_res);
1251 return 0;
1252 }
1253
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001254 wpas_wps_update_ap_info(wpa_s, scan_res);
1255
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001256 wpa_scan_results_free(scan_res);
1257
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001258 return wpas_select_network_from_last_scan(wpa_s, 1);
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001259}
1260
1261
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001262static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
1263 int new_scan)
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001264{
1265 struct wpa_bss *selected;
1266 struct wpa_ssid *ssid = NULL;
1267
1268 selected = wpa_supplicant_pick_network(wpa_s, &ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001269
1270 if (selected) {
1271 int skip;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -07001272 skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001273 if (skip) {
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001274 if (new_scan)
1275 wpa_supplicant_rsn_preauth_scan_results(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001276 return 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001277 }
1278
Dmitry Shmidt44da0252011-08-23 12:30:30 -07001279 if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001280 wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed");
Dmitry Shmidt44da0252011-08-23 12:30:30 -07001281 return -1;
1282 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001283 if (new_scan)
1284 wpa_supplicant_rsn_preauth_scan_results(wpa_s);
Jouni Malinen89ca7022012-09-14 13:03:12 -07001285 /*
1286 * Do not notify other virtual radios of scan results since we do not
1287 * want them to start other associations at the same time.
1288 */
1289 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001291 wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
1292 ssid = wpa_supplicant_pick_new_network(wpa_s);
1293 if (ssid) {
1294 wpa_dbg(wpa_s, MSG_DEBUG, "Setup a new network");
1295 wpa_supplicant_associate(wpa_s, NULL, ssid);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001296 if (new_scan)
1297 wpa_supplicant_rsn_preauth_scan_results(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 } else {
1299 int timeout_sec = wpa_s->scan_interval;
1300 int timeout_usec = 0;
1301#ifdef CONFIG_P2P
Dmitry Shmidt04949592012-07-19 12:16:46 -07001302 if (wpas_p2p_scan_no_go_seen(wpa_s) == 1)
1303 return 0;
1304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305 if (wpa_s->p2p_in_provisioning) {
1306 /*
1307 * Use shorter wait during P2P Provisioning
1308 * state to speed up group formation.
1309 */
1310 timeout_sec = 0;
1311 timeout_usec = 250000;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001312 wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
1313 timeout_usec);
1314 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 }
1316#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001317#ifdef CONFIG_INTERWORKING
1318 if (wpa_s->conf->auto_interworking &&
1319 wpa_s->conf->interworking &&
1320 wpa_s->conf->cred) {
1321 wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: "
1322 "start ANQP fetch since no matching "
1323 "networks found");
1324 wpa_s->network_select = 1;
1325 wpa_s->auto_network_select = 1;
1326 interworking_start_fetch_anqp(wpa_s);
Jouni Malinen89ca7022012-09-14 13:03:12 -07001327 return 1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001328 }
1329#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001330 if (wpa_supplicant_req_sched_scan(wpa_s))
1331 wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
1332 timeout_usec);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333 }
1334 }
1335 return 0;
1336}
1337
1338
1339static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
1340 union wpa_event_data *data)
1341{
1342 const char *rn, *rn2;
1343 struct wpa_supplicant *ifs;
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001344
1345 if (_wpa_supplicant_event_scan_results(wpa_s, data, 1) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 /*
1347 * If no scan results could be fetched, then no need to
1348 * notify those interfaces that did not actually request
Jouni Malinen89ca7022012-09-14 13:03:12 -07001349 * this scan. Similarly, if scan results started a new operation on this
1350 * interface, do not notify other interfaces to avoid concurrent
1351 * operations during a connection attempt.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001352 */
1353 return;
1354 }
1355
1356 /*
1357 * Check other interfaces to see if they have the same radio-name. If
1358 * so, they get updated with this same scan info.
1359 */
1360 if (!wpa_s->driver->get_radio_name)
1361 return;
1362
1363 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
1364 if (rn == NULL || rn[0] == '\0')
1365 return;
1366
1367 wpa_dbg(wpa_s, MSG_DEBUG, "Checking for other virtual interfaces "
1368 "sharing same radio (%s) in event_scan_results", rn);
1369
1370 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
1371 if (ifs == wpa_s || !ifs->driver->get_radio_name)
1372 continue;
1373
1374 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
1375 if (rn2 && os_strcmp(rn, rn2) == 0) {
1376 wpa_printf(MSG_DEBUG, "%s: Updating scan results from "
1377 "sibling", ifs->ifname);
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07001378 _wpa_supplicant_event_scan_results(ifs, data, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379 }
1380 }
1381}
1382
1383#endif /* CONFIG_NO_SCAN_PROCESSING */
1384
1385
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001386int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
1387{
1388#ifdef CONFIG_NO_SCAN_PROCESSING
1389 return -1;
1390#else /* CONFIG_NO_SCAN_PROCESSING */
1391 struct os_time now;
1392
1393 if (wpa_s->last_scan_res_used <= 0)
1394 return -1;
1395
1396 os_get_time(&now);
1397 if (now.sec - wpa_s->last_scan.sec > 5) {
1398 wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
1399 return -1;
1400 }
1401
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001402 return wpas_select_network_from_last_scan(wpa_s, 0);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001403#endif /* CONFIG_NO_SCAN_PROCESSING */
1404}
1405
Dmitry Shmidt04949592012-07-19 12:16:46 -07001406#ifdef CONFIG_WNM
1407
1408static void wnm_bss_keep_alive(void *eloop_ctx, void *sock_ctx)
1409{
1410 struct wpa_supplicant *wpa_s = eloop_ctx;
1411
1412 if (wpa_s->wpa_state < WPA_ASSOCIATED)
1413 return;
1414
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001415 if (!wpa_s->no_keep_alive) {
1416 wpa_printf(MSG_DEBUG, "WNM: Send keep-alive to AP " MACSTR,
1417 MAC2STR(wpa_s->bssid));
1418 /* TODO: could skip this if normal data traffic has been sent */
1419 /* TODO: Consider using some more appropriate data frame for
1420 * this */
1421 if (wpa_s->l2)
1422 l2_packet_send(wpa_s->l2, wpa_s->bssid, 0x0800,
1423 (u8 *) "", 0);
1424 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001425
1426#ifdef CONFIG_SME
1427 if (wpa_s->sme.bss_max_idle_period) {
1428 unsigned int msec;
1429 msec = wpa_s->sme.bss_max_idle_period * 1024; /* times 1000 */
1430 if (msec > 100)
1431 msec -= 100;
1432 eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
1433 wnm_bss_keep_alive, wpa_s, NULL);
1434 }
1435#endif /* CONFIG_SME */
1436}
1437
1438
1439static void wnm_process_assoc_resp(struct wpa_supplicant *wpa_s,
1440 const u8 *ies, size_t ies_len)
1441{
1442 struct ieee802_11_elems elems;
1443
1444 if (ies == NULL)
1445 return;
1446
1447 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
1448 return;
1449
1450#ifdef CONFIG_SME
1451 if (elems.bss_max_idle_period) {
1452 unsigned int msec;
1453 wpa_s->sme.bss_max_idle_period =
1454 WPA_GET_LE16(elems.bss_max_idle_period);
1455 wpa_printf(MSG_DEBUG, "WNM: BSS Max Idle Period: %u (* 1000 "
1456 "TU)%s", wpa_s->sme.bss_max_idle_period,
1457 (elems.bss_max_idle_period[2] & 0x01) ?
1458 " (protected keep-live required)" : "");
1459 if (wpa_s->sme.bss_max_idle_period == 0)
1460 wpa_s->sme.bss_max_idle_period = 1;
1461 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) {
1462 eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
1463 /* msec times 1000 */
1464 msec = wpa_s->sme.bss_max_idle_period * 1024;
1465 if (msec > 100)
1466 msec -= 100;
1467 eloop_register_timeout(msec / 1000, msec % 1000 * 1000,
1468 wnm_bss_keep_alive, wpa_s,
1469 NULL);
1470 }
1471 }
1472#endif /* CONFIG_SME */
1473}
1474
1475#endif /* CONFIG_WNM */
1476
1477
1478void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
1479{
1480#ifdef CONFIG_WNM
1481 eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL);
1482#endif /* CONFIG_WNM */
1483}
1484
1485
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
1487 union wpa_event_data *data)
1488{
1489 int l, len, found = 0, wpa_found, rsn_found;
1490 const u8 *p;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001491#ifdef CONFIG_IEEE80211R
1492 u8 bssid[ETH_ALEN];
1493#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494
1495 wpa_dbg(wpa_s, MSG_DEBUG, "Association info event");
1496 if (data->assoc_info.req_ies)
1497 wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies,
1498 data->assoc_info.req_ies_len);
1499 if (data->assoc_info.resp_ies) {
1500 wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies,
1501 data->assoc_info.resp_ies_len);
1502#ifdef CONFIG_TDLS
1503 wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies,
1504 data->assoc_info.resp_ies_len);
1505#endif /* CONFIG_TDLS */
Dmitry Shmidt04949592012-07-19 12:16:46 -07001506#ifdef CONFIG_WNM
1507 wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
1508 data->assoc_info.resp_ies_len);
1509#endif /* CONFIG_WNM */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510 }
1511 if (data->assoc_info.beacon_ies)
1512 wpa_hexdump(MSG_DEBUG, "beacon_ies",
1513 data->assoc_info.beacon_ies,
1514 data->assoc_info.beacon_ies_len);
1515 if (data->assoc_info.freq)
1516 wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz",
1517 data->assoc_info.freq);
1518
1519 p = data->assoc_info.req_ies;
1520 l = data->assoc_info.req_ies_len;
1521
1522 /* Go through the IEs and make a copy of the WPA/RSN IE, if present. */
1523 while (p && l >= 2) {
1524 len = p[1] + 2;
1525 if (len > l) {
1526 wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
1527 p, l);
1528 break;
1529 }
1530 if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
1531 (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
1532 (p[0] == WLAN_EID_RSN && p[1] >= 2)) {
1533 if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
1534 break;
1535 found = 1;
1536 wpa_find_assoc_pmkid(wpa_s);
1537 break;
1538 }
1539 l -= len;
1540 p += len;
1541 }
1542 if (!found && data->assoc_info.req_ies)
1543 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1544
1545#ifdef CONFIG_IEEE80211R
1546#ifdef CONFIG_SME
1547 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001548 if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
1549 wpa_ft_validate_reassoc_resp(wpa_s->wpa,
1550 data->assoc_info.resp_ies,
1551 data->assoc_info.resp_ies_len,
1552 bssid) < 0) {
1553 wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
1554 "Reassociation Response failed");
1555 wpa_supplicant_deauthenticate(
1556 wpa_s, WLAN_REASON_INVALID_IE);
1557 return -1;
1558 }
1559 }
1560
1561 p = data->assoc_info.resp_ies;
1562 l = data->assoc_info.resp_ies_len;
1563
1564#ifdef CONFIG_WPS_STRICT
1565 if (p && wpa_s->current_ssid &&
1566 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_WPS) {
1567 struct wpabuf *wps;
1568 wps = ieee802_11_vendor_ie_concat(p, l, WPS_IE_VENDOR_TYPE);
1569 if (wps == NULL) {
1570 wpa_msg(wpa_s, MSG_INFO, "WPS-STRICT: AP did not "
1571 "include WPS IE in (Re)Association Response");
1572 return -1;
1573 }
1574
1575 if (wps_validate_assoc_resp(wps) < 0) {
1576 wpabuf_free(wps);
1577 wpa_supplicant_deauthenticate(
1578 wpa_s, WLAN_REASON_INVALID_IE);
1579 return -1;
1580 }
1581 wpabuf_free(wps);
1582 }
1583#endif /* CONFIG_WPS_STRICT */
1584
1585 /* Go through the IEs and make a copy of the MDIE, if present. */
1586 while (p && l >= 2) {
1587 len = p[1] + 2;
1588 if (len > l) {
1589 wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
1590 p, l);
1591 break;
1592 }
1593 if (p[0] == WLAN_EID_MOBILITY_DOMAIN &&
1594 p[1] >= MOBILITY_DOMAIN_ID_LEN) {
1595 wpa_s->sme.ft_used = 1;
1596 os_memcpy(wpa_s->sme.mobility_domain, p + 2,
1597 MOBILITY_DOMAIN_ID_LEN);
1598 break;
1599 }
1600 l -= len;
1601 p += len;
1602 }
1603#endif /* CONFIG_SME */
1604
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001605 /* Process FT when SME is in the driver */
1606 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1607 wpa_ft_is_completed(wpa_s->wpa)) {
1608 if (wpa_drv_get_bssid(wpa_s, bssid) < 0 ||
1609 wpa_ft_validate_reassoc_resp(wpa_s->wpa,
1610 data->assoc_info.resp_ies,
1611 data->assoc_info.resp_ies_len,
1612 bssid) < 0) {
1613 wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of "
1614 "Reassociation Response failed");
1615 wpa_supplicant_deauthenticate(
1616 wpa_s, WLAN_REASON_INVALID_IE);
1617 return -1;
1618 }
1619 wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done");
1620 }
1621
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies,
1623 data->assoc_info.resp_ies_len);
1624#endif /* CONFIG_IEEE80211R */
1625
1626 /* WPA/RSN IE from Beacon/ProbeResp */
1627 p = data->assoc_info.beacon_ies;
1628 l = data->assoc_info.beacon_ies_len;
1629
1630 /* Go through the IEs and make a copy of the WPA/RSN IEs, if present.
1631 */
1632 wpa_found = rsn_found = 0;
1633 while (p && l >= 2) {
1634 len = p[1] + 2;
1635 if (len > l) {
1636 wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies",
1637 p, l);
1638 break;
1639 }
1640 if (!wpa_found &&
1641 p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
1642 os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) {
1643 wpa_found = 1;
1644 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len);
1645 }
1646
1647 if (!rsn_found &&
1648 p[0] == WLAN_EID_RSN && p[1] >= 2) {
1649 rsn_found = 1;
1650 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len);
1651 }
1652
1653 l -= len;
1654 p += len;
1655 }
1656
1657 if (!wpa_found && data->assoc_info.beacon_ies)
1658 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
1659 if (!rsn_found && data->assoc_info.beacon_ies)
1660 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
1661 if (wpa_found || rsn_found)
1662 wpa_s->ap_ies_from_associnfo = 1;
1663
Jouni Malinen87fd2792011-05-16 18:35:42 +03001664 if (wpa_s->assoc_freq && data->assoc_info.freq &&
1665 wpa_s->assoc_freq != data->assoc_info.freq) {
1666 wpa_printf(MSG_DEBUG, "Operating frequency changed from "
1667 "%u to %u MHz",
1668 wpa_s->assoc_freq, data->assoc_info.freq);
1669 wpa_supplicant_update_scan_results(wpa_s);
1670 }
1671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 wpa_s->assoc_freq = data->assoc_info.freq;
1673
1674 return 0;
1675}
1676
1677
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001678static struct wpa_bss * wpa_supplicant_get_new_bss(
1679 struct wpa_supplicant *wpa_s, const u8 *bssid)
1680{
1681 struct wpa_bss *bss = NULL;
1682 struct wpa_ssid *ssid = wpa_s->current_ssid;
1683
1684 if (ssid->ssid_len > 0)
1685 bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len);
1686 if (!bss)
1687 bss = wpa_bss_get_bssid(wpa_s, bssid);
1688
1689 return bss;
1690}
1691
1692
1693static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s)
1694{
1695 const u8 *bss_wpa = NULL, *bss_rsn = NULL;
1696
1697 if (!wpa_s->current_bss || !wpa_s->current_ssid)
1698 return -1;
1699
1700 if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt))
1701 return 0;
1702
1703 bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss,
1704 WPA_IE_VENDOR_TYPE);
1705 bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN);
1706
1707 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1708 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1709 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1710 bss_rsn ? 2 + bss_rsn[1] : 0))
1711 return -1;
1712
1713 return 0;
1714}
1715
1716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
1718 union wpa_event_data *data)
1719{
1720 u8 bssid[ETH_ALEN];
1721 int ft_completed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722
1723#ifdef CONFIG_AP
1724 if (wpa_s->ap_iface) {
1725 hostapd_notif_assoc(wpa_s->ap_iface->bss[0],
1726 data->assoc_info.addr,
1727 data->assoc_info.req_ies,
1728 data->assoc_info.req_ies_len,
1729 data->assoc_info.reassoc);
1730 return;
1731 }
1732#endif /* CONFIG_AP */
1733
1734 ft_completed = wpa_ft_is_completed(wpa_s->wpa);
1735 if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
1736 return;
1737
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001738 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
1739 wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001740 wpa_supplicant_deauthenticate(
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001741 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1742 return;
1743 }
1744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001746 if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747 wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID="
1748 MACSTR, MAC2STR(bssid));
1749 random_add_randomness(bssid, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750 os_memcpy(wpa_s->bssid, bssid, ETH_ALEN);
1751 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001752 wpas_notify_bssid_changed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753
1754 if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) {
1755 wpa_clear_keys(wpa_s, bssid);
1756 }
1757 if (wpa_supplicant_select_config(wpa_s) < 0) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001758 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1760 return;
1761 }
1762 if (wpa_s->current_ssid) {
1763 struct wpa_bss *bss = NULL;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001764
1765 bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
1766 if (!bss) {
1767 wpa_supplicant_update_scan_results(wpa_s);
1768
1769 /* Get the BSS from the new scan results */
1770 bss = wpa_supplicant_get_new_bss(wpa_s, bssid);
1771 }
1772
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773 if (bss)
1774 wpa_s->current_bss = bss;
1775 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001776
Dmitry Shmidt1e1c48d2013-02-14 16:44:44 -08001777#ifdef ANDROID
1778 if (wpa_s->conf->ap_scan == 1) {
1779#else
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001780 if (wpa_s->conf->ap_scan == 1 &&
1781 wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) {
Dmitry Shmidt1e1c48d2013-02-14 16:44:44 -08001782#endif
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001783 if (wpa_supplicant_assoc_update_ie(wpa_s) < 0)
1784 wpa_msg(wpa_s, MSG_WARNING,
1785 "WPA/RSN IEs not updated");
1786 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787 }
1788
1789#ifdef CONFIG_SME
1790 os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN);
1791 wpa_s->sme.prev_bssid_set = 1;
1792#endif /* CONFIG_SME */
1793
1794 wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid));
1795 if (wpa_s->current_ssid) {
1796 /* When using scanning (ap_scan=1), SIM PC/SC interface can be
1797 * initialized before association, but for other modes,
1798 * initialize PC/SC here, if the current configuration needs
1799 * smartcard or SIM/USIM. */
1800 wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid);
1801 }
1802 wpa_sm_notify_assoc(wpa_s->wpa, bssid);
1803 if (wpa_s->l2)
1804 l2_packet_notify_auth_start(wpa_s->l2);
1805
1806 /*
1807 * Set portEnabled first to FALSE in order to get EAP state machine out
1808 * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE
1809 * state machine may transit to AUTHENTICATING state based on obsolete
1810 * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to
1811 * AUTHENTICATED without ever giving chance to EAP state machine to
1812 * reset the state.
1813 */
1814 if (!ft_completed) {
1815 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
1816 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
1817 }
1818 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed)
1819 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
1820 /* 802.1X::portControl = Auto */
1821 eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE);
1822 wpa_s->eapol_received = 0;
1823 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1824 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE ||
1825 (wpa_s->current_ssid &&
1826 wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001827 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE &&
1828 (wpa_s->drv_flags &
1829 WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
1830 /*
1831 * Set the key after having received joined-IBSS event
1832 * from the driver.
1833 */
1834 wpa_supplicant_set_wpa_none_key(wpa_s,
1835 wpa_s->current_ssid);
1836 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837 wpa_supplicant_cancel_auth_timeout(wpa_s);
1838 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1839 } else if (!ft_completed) {
1840 /* Timeout for receiving the first EAPOL packet */
1841 wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
1842 }
1843 wpa_supplicant_cancel_scan(wpa_s);
1844
1845 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1846 wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
1847 /*
1848 * We are done; the driver will take care of RSN 4-way
1849 * handshake.
1850 */
1851 wpa_supplicant_cancel_auth_timeout(wpa_s);
1852 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1853 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
1854 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
1855 } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1856 wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
1857 /*
1858 * The driver will take care of RSN 4-way handshake, so we need
1859 * to allow EAPOL supplicant to complete its work without
1860 * waiting for WPA supplicant.
1861 */
1862 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
1863 } else if (ft_completed) {
1864 /*
1865 * FT protocol completed - make sure EAPOL state machine ends
1866 * up in authenticated.
1867 */
1868 wpa_supplicant_cancel_auth_timeout(wpa_s);
1869 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1870 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
1871 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
1872 }
1873
Jouni Malinena05074c2012-12-21 21:35:35 +02001874 wpa_s->last_eapol_matches_bssid = 0;
1875
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 if (wpa_s->pending_eapol_rx) {
1877 struct os_time now, age;
1878 os_get_time(&now);
1879 os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age);
1880 if (age.sec == 0 && age.usec < 100000 &&
1881 os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) ==
1882 0) {
1883 wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL "
1884 "frame that was received just before "
1885 "association notification");
1886 wpa_supplicant_rx_eapol(
1887 wpa_s, wpa_s->pending_eapol_rx_src,
1888 wpabuf_head(wpa_s->pending_eapol_rx),
1889 wpabuf_len(wpa_s->pending_eapol_rx));
1890 }
1891 wpabuf_free(wpa_s->pending_eapol_rx);
1892 wpa_s->pending_eapol_rx = NULL;
1893 }
1894
1895 if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1896 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001897 wpa_s->current_ssid &&
1898 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899 /* Set static WEP keys again */
1900 wpa_set_wep_keys(wpa_s, wpa_s->current_ssid);
1901 }
1902
1903#ifdef CONFIG_IBSS_RSN
1904 if (wpa_s->current_ssid &&
1905 wpa_s->current_ssid->mode == WPAS_MODE_IBSS &&
1906 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1907 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE &&
1908 wpa_s->ibss_rsn == NULL) {
1909 wpa_s->ibss_rsn = ibss_rsn_init(wpa_s);
1910 if (!wpa_s->ibss_rsn) {
1911 wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN");
1912 wpa_supplicant_deauthenticate(
1913 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1914 return;
1915 }
1916
1917 ibss_rsn_set_psk(wpa_s->ibss_rsn, wpa_s->current_ssid->psk);
1918 }
1919#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001920
1921 wpas_wps_notify_assoc(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922}
1923
1924
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001925static int disconnect_reason_recoverable(u16 reason_code)
1926{
1927 return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY ||
1928 reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA ||
1929 reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
1930}
1931
1932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001934 u16 reason_code,
1935 int locally_generated)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936{
1937 const u8 *bssid;
Jouni Malinen2b89da82012-08-31 22:04:41 +03001938
1939 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1940 /*
1941 * At least Host AP driver and a Prism3 card seemed to be
1942 * generating streams of disconnected events when configuring
1943 * IBSS for WPA-None. Ignore them for now.
1944 */
1945 return;
1946 }
1947
1948 bssid = wpa_s->bssid;
1949 if (is_zero_ether_addr(bssid))
1950 bssid = wpa_s->pending_bssid;
1951
1952 if (!is_zero_ether_addr(bssid) ||
1953 wpa_s->wpa_state >= WPA_AUTHENTICATING) {
1954 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
1955 " reason=%d%s",
1956 MAC2STR(bssid), reason_code,
1957 locally_generated ? " locally_generated=1" : "");
1958 }
1959}
1960
1961
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001962static int could_be_psk_mismatch(struct wpa_supplicant *wpa_s, u16 reason_code,
1963 int locally_generated)
1964{
1965 if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE ||
1966 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt))
1967 return 0; /* Not in 4-way handshake with PSK */
1968
1969 /*
1970 * It looks like connection was lost while trying to go through PSK
1971 * 4-way handshake. Filter out known disconnection cases that are caused
1972 * by something else than PSK mismatch to avoid confusing reports.
1973 */
1974
1975 if (locally_generated) {
1976 if (reason_code == WLAN_REASON_IE_IN_4WAY_DIFFERS)
1977 return 0;
1978 }
1979
1980 return 1;
1981}
1982
1983
Jouni Malinen2b89da82012-08-31 22:04:41 +03001984static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
1985 u16 reason_code,
1986 int locally_generated)
1987{
1988 const u8 *bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989 int authenticating;
1990 u8 prev_pending_bssid[ETH_ALEN];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001991 struct wpa_bss *fast_reconnect = NULL;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001992#ifndef CONFIG_NO_SCAN_PROCESSING
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001993 struct wpa_ssid *fast_reconnect_ssid = NULL;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001994#endif /* CONFIG_NO_SCAN_PROCESSING */
Jouni Malinenf8a26a82012-09-01 17:20:27 +03001995 struct wpa_ssid *last_ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996
1997 authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING;
1998 os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN);
1999
2000 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
2001 /*
2002 * At least Host AP driver and a Prism3 card seemed to be
2003 * generating streams of disconnected events when configuring
2004 * IBSS for WPA-None. Ignore them for now.
2005 */
2006 wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - ignore in "
2007 "IBSS/WPA-None mode");
2008 return;
2009 }
2010
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002011 if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012 wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
2013 "pre-shared key may be incorrect");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002014 wpas_auth_failed(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002016 if (!wpa_s->disconnected &&
2017 (!wpa_s->auto_reconnect_disabled ||
2018 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002019 wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
2020 "reconnect (wps=%d wpa_state=%d)",
2021 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
2022 wpa_s->wpa_state);
2023 if (wpa_s->wpa_state == WPA_COMPLETED &&
2024 wpa_s->current_ssid &&
2025 wpa_s->current_ssid->mode == WPAS_MODE_INFRA &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002026 !locally_generated &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002027 disconnect_reason_recoverable(reason_code)) {
2028 /*
2029 * It looks like the AP has dropped association with
2030 * us, but could allow us to get back in. Try to
2031 * reconnect to the same BSS without full scan to save
2032 * time for some common cases.
2033 */
2034 fast_reconnect = wpa_s->current_bss;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002035#ifndef CONFIG_NO_SCAN_PROCESSING
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002036 fast_reconnect_ssid = wpa_s->current_ssid;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002037#endif /* CONFIG_NO_SCAN_PROCESSING */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002038 } else if (wpa_s->wpa_state >= WPA_ASSOCIATING)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002039#ifdef ANDROID
Dmitry Shmidt43007fd2011-04-11 15:58:40 -07002040 wpa_supplicant_req_scan(wpa_s, 0, 500000);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002041#else
2042 wpa_supplicant_req_scan(wpa_s, 0, 100000);
2043#endif
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002044 else
2045 wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new "
2046 "immediate scan");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002048 wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 "try to re-connect");
2050 wpa_s->reassociate = 0;
2051 wpa_s->disconnected = 1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002052 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 }
2054 bssid = wpa_s->bssid;
2055 if (is_zero_ether_addr(bssid))
2056 bssid = wpa_s->pending_bssid;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002057 if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
2058 wpas_connection_failed(wpa_s, bssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002060 if (locally_generated)
2061 wpa_s->disconnect_reason = -reason_code;
2062 else
2063 wpa_s->disconnect_reason = reason_code;
2064 wpas_notify_disconnect_reason(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002065 if (wpa_supplicant_dynamic_keys(wpa_s)) {
2066 wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys");
2067 wpa_s->keys_cleared = 0;
2068 wpa_clear_keys(wpa_s, wpa_s->bssid);
2069 }
Jouni Malinenf8a26a82012-09-01 17:20:27 +03002070 last_ssid = wpa_s->current_ssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071 wpa_supplicant_mark_disassoc(wpa_s);
2072
Jouni Malinenf8a26a82012-09-01 17:20:27 +03002073 if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002074 sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
Jouni Malinenf8a26a82012-09-01 17:20:27 +03002075 wpa_s->current_ssid = last_ssid;
2076 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002077
2078 if (fast_reconnect) {
2079#ifndef CONFIG_NO_SCAN_PROCESSING
2080 wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS");
2081 if (wpa_supplicant_connect(wpa_s, fast_reconnect,
2082 fast_reconnect_ssid) < 0) {
2083 /* Recover through full scan */
2084 wpa_supplicant_req_scan(wpa_s, 0, 100000);
2085 }
2086#endif /* CONFIG_NO_SCAN_PROCESSING */
2087 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002088}
2089
2090
2091#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002092void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093{
2094 struct wpa_supplicant *wpa_s = eloop_ctx;
2095
2096 if (!wpa_s->pending_mic_error_report)
2097 return;
2098
2099 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Sending pending MIC error report");
2100 wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise);
2101 wpa_s->pending_mic_error_report = 0;
2102}
2103#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
2104
2105
2106static void
2107wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
2108 union wpa_event_data *data)
2109{
2110 int pairwise;
2111 struct os_time t;
2112
2113 wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected");
2114 pairwise = (data && data->michael_mic_failure.unicast);
2115 os_get_time(&t);
2116 if ((wpa_s->last_michael_mic_error &&
2117 t.sec - wpa_s->last_michael_mic_error <= 60) ||
2118 wpa_s->pending_mic_error_report) {
2119 if (wpa_s->pending_mic_error_report) {
2120 /*
2121 * Send the pending MIC error report immediately since
2122 * we are going to start countermeasures and AP better
2123 * do the same.
2124 */
2125 wpa_sm_key_request(wpa_s->wpa, 1,
2126 wpa_s->pending_mic_error_pairwise);
2127 }
2128
2129 /* Send the new MIC error report immediately since we are going
2130 * to start countermeasures and AP better do the same.
2131 */
2132 wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
2133
2134 /* initialize countermeasures */
2135 wpa_s->countermeasures = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002136
2137 wpa_blacklist_add(wpa_s, wpa_s->bssid);
2138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139 wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
2140
2141 /*
2142 * Need to wait for completion of request frame. We do not get
2143 * any callback for the message completion, so just wait a
2144 * short while and hope for the best. */
2145 os_sleep(0, 10000);
2146
2147 wpa_drv_set_countermeasures(wpa_s, 1);
2148 wpa_supplicant_deauthenticate(wpa_s,
2149 WLAN_REASON_MICHAEL_MIC_FAILURE);
2150 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures,
2151 wpa_s, NULL);
2152 eloop_register_timeout(60, 0,
2153 wpa_supplicant_stop_countermeasures,
2154 wpa_s, NULL);
2155 /* TODO: mark the AP rejected for 60 second. STA is
2156 * allowed to associate with another AP.. */
2157 } else {
2158#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
2159 if (wpa_s->mic_errors_seen) {
2160 /*
2161 * Reduce the effectiveness of Michael MIC error
2162 * reports as a means for attacking against TKIP if
2163 * more than one MIC failure is noticed with the same
2164 * PTK. We delay the transmission of the reports by a
2165 * random time between 0 and 60 seconds in order to
2166 * force the attacker wait 60 seconds before getting
2167 * the information on whether a frame resulted in a MIC
2168 * failure.
2169 */
2170 u8 rval[4];
2171 int sec;
2172
2173 if (os_get_random(rval, sizeof(rval)) < 0)
2174 sec = os_random() % 60;
2175 else
2176 sec = WPA_GET_BE32(rval) % 60;
2177 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Delay MIC error "
2178 "report %d seconds", sec);
2179 wpa_s->pending_mic_error_report = 1;
2180 wpa_s->pending_mic_error_pairwise = pairwise;
2181 eloop_cancel_timeout(
2182 wpa_supplicant_delayed_mic_error_report,
2183 wpa_s, NULL);
2184 eloop_register_timeout(
2185 sec, os_random() % 1000000,
2186 wpa_supplicant_delayed_mic_error_report,
2187 wpa_s, NULL);
2188 } else {
2189 wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
2190 }
2191#else /* CONFIG_DELAYED_MIC_ERROR_REPORT */
2192 wpa_sm_key_request(wpa_s->wpa, 1, pairwise);
2193#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
2194 }
2195 wpa_s->last_michael_mic_error = t.sec;
2196 wpa_s->mic_errors_seen++;
2197}
2198
2199
2200#ifdef CONFIG_TERMINATE_ONLASTIF
2201static int any_interfaces(struct wpa_supplicant *head)
2202{
2203 struct wpa_supplicant *wpa_s;
2204
2205 for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next)
2206 if (!wpa_s->interface_removed)
2207 return 1;
2208 return 0;
2209}
2210#endif /* CONFIG_TERMINATE_ONLASTIF */
2211
2212
2213static void
2214wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
2215 union wpa_event_data *data)
2216{
2217 if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0)
2218 return;
2219
2220 switch (data->interface_status.ievent) {
2221 case EVENT_INTERFACE_ADDED:
2222 if (!wpa_s->interface_removed)
2223 break;
2224 wpa_s->interface_removed = 0;
2225 wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was added");
2226 if (wpa_supplicant_driver_init(wpa_s) < 0) {
2227 wpa_msg(wpa_s, MSG_INFO, "Failed to initialize the "
2228 "driver after interface was added");
2229 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002230 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 break;
2232 case EVENT_INTERFACE_REMOVED:
2233 wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed");
2234 wpa_s->interface_removed = 1;
2235 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002236 wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 l2_packet_deinit(wpa_s->l2);
2238 wpa_s->l2 = NULL;
2239#ifdef CONFIG_IBSS_RSN
2240 ibss_rsn_deinit(wpa_s->ibss_rsn);
2241 wpa_s->ibss_rsn = NULL;
2242#endif /* CONFIG_IBSS_RSN */
2243#ifdef CONFIG_TERMINATE_ONLASTIF
2244 /* check if last interface */
2245 if (!any_interfaces(wpa_s->global->ifaces))
2246 eloop_terminate();
2247#endif /* CONFIG_TERMINATE_ONLASTIF */
2248 break;
2249 }
2250}
2251
2252
2253#ifdef CONFIG_PEERKEY
2254static void
2255wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
2256 union wpa_event_data *data)
2257{
2258 if (data == NULL)
2259 return;
2260 wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer);
2261}
2262#endif /* CONFIG_PEERKEY */
2263
2264
2265#ifdef CONFIG_TDLS
2266static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
2267 union wpa_event_data *data)
2268{
2269 if (data == NULL)
2270 return;
2271 switch (data->tdls.oper) {
2272 case TDLS_REQUEST_SETUP:
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002273 wpa_tdls_remove(wpa_s->wpa, data->tdls.peer);
2274 if (wpa_tdls_is_external_setup(wpa_s->wpa))
2275 wpa_tdls_start(wpa_s->wpa, data->tdls.peer);
2276 else
2277 wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, data->tdls.peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 break;
2279 case TDLS_REQUEST_TEARDOWN:
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002280 wpa_tdls_teardown_link(wpa_s->wpa, data->tdls.peer,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002281 data->tdls.reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002282 break;
2283 }
2284}
2285#endif /* CONFIG_TDLS */
2286
2287
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002288#ifdef CONFIG_WNM
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002289static void wpa_supplicant_event_wnm(struct wpa_supplicant *wpa_s,
2290 union wpa_event_data *data)
2291{
2292 if (data == NULL)
2293 return;
2294 switch (data->wnm.oper) {
2295 case WNM_OPER_SLEEP:
2296 wpa_printf(MSG_DEBUG, "Start sending WNM-Sleep Request "
2297 "(action=%d, intval=%d)",
2298 data->wnm.sleep_action, data->wnm.sleep_intval);
2299 ieee802_11_send_wnmsleep_req(wpa_s, data->wnm.sleep_action,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002300 data->wnm.sleep_intval, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002301 break;
2302 }
2303}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002304#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305
2306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307#ifdef CONFIG_IEEE80211R
2308static void
2309wpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s,
2310 union wpa_event_data *data)
2311{
2312 if (data == NULL)
2313 return;
2314
2315 if (wpa_ft_process_response(wpa_s->wpa, data->ft_ies.ies,
2316 data->ft_ies.ies_len,
2317 data->ft_ies.ft_action,
2318 data->ft_ies.target_ap,
2319 data->ft_ies.ric_ies,
2320 data->ft_ies.ric_ies_len) < 0) {
2321 /* TODO: prevent MLME/driver from trying to associate? */
2322 }
2323}
2324#endif /* CONFIG_IEEE80211R */
2325
2326
2327#ifdef CONFIG_IBSS_RSN
2328static void wpa_supplicant_event_ibss_rsn_start(struct wpa_supplicant *wpa_s,
2329 union wpa_event_data *data)
2330{
2331 struct wpa_ssid *ssid;
2332 if (wpa_s->wpa_state < WPA_ASSOCIATED)
2333 return;
2334 if (data == NULL)
2335 return;
2336 ssid = wpa_s->current_ssid;
2337 if (ssid == NULL)
2338 return;
2339 if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt))
2340 return;
2341
2342 ibss_rsn_start(wpa_s->ibss_rsn, data->ibss_rsn_start.peer);
2343}
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002344
2345
2346static void wpa_supplicant_event_ibss_auth(struct wpa_supplicant *wpa_s,
2347 union wpa_event_data *data)
2348{
2349 struct wpa_ssid *ssid = wpa_s->current_ssid;
2350
2351 if (ssid == NULL)
2352 return;
2353
2354 /* check if the ssid is correctly configured as IBSS/RSN */
2355 if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt))
2356 return;
2357
2358 ibss_rsn_handle_auth(wpa_s->ibss_rsn, data->rx_mgmt.frame,
2359 data->rx_mgmt.frame_len);
2360}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361#endif /* CONFIG_IBSS_RSN */
2362
2363
2364#ifdef CONFIG_IEEE80211R
2365static void ft_rx_action(struct wpa_supplicant *wpa_s, const u8 *data,
2366 size_t len)
2367{
2368 const u8 *sta_addr, *target_ap_addr;
2369 u16 status;
2370
2371 wpa_hexdump(MSG_MSGDUMP, "FT: RX Action", data, len);
2372 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
2373 return; /* only SME case supported for now */
2374 if (len < 1 + 2 * ETH_ALEN + 2)
2375 return;
2376 if (data[0] != 2)
2377 return; /* Only FT Action Response is supported for now */
2378 sta_addr = data + 1;
2379 target_ap_addr = data + 1 + ETH_ALEN;
2380 status = WPA_GET_LE16(data + 1 + 2 * ETH_ALEN);
2381 wpa_dbg(wpa_s, MSG_DEBUG, "FT: Received FT Action Response: STA "
2382 MACSTR " TargetAP " MACSTR " status %u",
2383 MAC2STR(sta_addr), MAC2STR(target_ap_addr), status);
2384
2385 if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) {
2386 wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR
2387 " in FT Action Response", MAC2STR(sta_addr));
2388 return;
2389 }
2390
2391 if (status) {
2392 wpa_dbg(wpa_s, MSG_DEBUG, "FT: FT Action Response indicates "
2393 "failure (status code %d)", status);
2394 /* TODO: report error to FT code(?) */
2395 return;
2396 }
2397
2398 if (wpa_ft_process_response(wpa_s->wpa, data + 1 + 2 * ETH_ALEN + 2,
2399 len - (1 + 2 * ETH_ALEN + 2), 1,
2400 target_ap_addr, NULL, 0) < 0)
2401 return;
2402
2403#ifdef CONFIG_SME
2404 {
2405 struct wpa_bss *bss;
2406 bss = wpa_bss_get_bssid(wpa_s, target_ap_addr);
2407 if (bss)
2408 wpa_s->sme.freq = bss->freq;
2409 wpa_s->sme.auth_alg = WPA_AUTH_ALG_FT;
2410 sme_associate(wpa_s, WPAS_MODE_INFRA, target_ap_addr,
2411 WLAN_AUTH_FT);
2412 }
2413#endif /* CONFIG_SME */
2414}
2415#endif /* CONFIG_IEEE80211R */
2416
2417
2418static void wpa_supplicant_event_unprot_deauth(struct wpa_supplicant *wpa_s,
2419 struct unprot_deauth *e)
2420{
2421#ifdef CONFIG_IEEE80211W
2422 wpa_printf(MSG_DEBUG, "Unprotected Deauthentication frame "
2423 "dropped: " MACSTR " -> " MACSTR
2424 " (reason code %u)",
2425 MAC2STR(e->sa), MAC2STR(e->da), e->reason_code);
2426 sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code);
2427#endif /* CONFIG_IEEE80211W */
2428}
2429
2430
2431static void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s,
2432 struct unprot_disassoc *e)
2433{
2434#ifdef CONFIG_IEEE80211W
2435 wpa_printf(MSG_DEBUG, "Unprotected Disassociation frame "
2436 "dropped: " MACSTR " -> " MACSTR
2437 " (reason code %u)",
2438 MAC2STR(e->sa), MAC2STR(e->da), e->reason_code);
2439 sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code);
2440#endif /* CONFIG_IEEE80211W */
2441}
2442
2443
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002444static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr,
2445 u16 reason_code, int locally_generated,
2446 const u8 *ie, size_t ie_len, int deauth)
2447{
2448#ifdef CONFIG_AP
2449 if (wpa_s->ap_iface && addr) {
2450 hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], addr);
2451 return;
2452 }
2453
2454 if (wpa_s->ap_iface) {
2455 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in AP mode");
2456 return;
2457 }
2458#endif /* CONFIG_AP */
2459
2460 wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated);
2461
2462 if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED ||
2463 ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2464 (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) &&
2465 eapol_sm_failed(wpa_s->eapol)))
2466 wpas_auth_failed(wpa_s);
2467
2468#ifdef CONFIG_P2P
2469 if (deauth && ie && ie_len > 0) {
2470 if (wpas_p2p_deauth_notif(wpa_s, addr, reason_code, ie, ie_len,
2471 locally_generated) > 0) {
2472 /*
2473 * The interface was removed, so cannot continue
2474 * processing any additional operations after this.
2475 */
2476 return;
2477 }
2478 }
2479#endif /* CONFIG_P2P */
2480
2481 wpa_supplicant_event_disassoc_finish(wpa_s, reason_code,
2482 locally_generated);
2483}
2484
2485
2486static void wpas_event_disassoc(struct wpa_supplicant *wpa_s,
2487 struct disassoc_info *info)
2488{
2489 u16 reason_code = 0;
2490 int locally_generated = 0;
2491 const u8 *addr = NULL;
2492 const u8 *ie = NULL;
2493 size_t ie_len = 0;
2494
2495 wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification");
2496
2497 if (info) {
2498 addr = info->addr;
2499 ie = info->ie;
2500 ie_len = info->ie_len;
2501 reason_code = info->reason_code;
2502 locally_generated = info->locally_generated;
2503 wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", reason_code,
2504 locally_generated ? " (locally generated)" : "");
2505 if (addr)
2506 wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
2507 MAC2STR(addr));
2508 wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)",
2509 ie, ie_len);
2510 }
2511
2512#ifdef CONFIG_AP
2513 if (wpa_s->ap_iface && info && info->addr) {
2514 hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], info->addr);
2515 return;
2516 }
2517
2518 if (wpa_s->ap_iface) {
2519 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in AP mode");
2520 return;
2521 }
2522#endif /* CONFIG_AP */
2523
2524#ifdef CONFIG_P2P
2525 if (info) {
2526 wpas_p2p_disassoc_notif(
2527 wpa_s, info->addr, reason_code, info->ie, info->ie_len,
2528 locally_generated);
2529 }
2530#endif /* CONFIG_P2P */
2531
2532 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
2533 sme_event_disassoc(wpa_s, info);
2534
2535 wpas_event_disconnect(wpa_s, addr, reason_code, locally_generated,
2536 ie, ie_len, 0);
2537}
2538
2539
2540static void wpas_event_deauth(struct wpa_supplicant *wpa_s,
2541 struct deauth_info *info)
2542{
2543 u16 reason_code = 0;
2544 int locally_generated = 0;
2545 const u8 *addr = NULL;
2546 const u8 *ie = NULL;
2547 size_t ie_len = 0;
2548
2549 wpa_dbg(wpa_s, MSG_DEBUG, "Deauthentication notification");
2550
2551 if (info) {
2552 addr = info->addr;
2553 ie = info->ie;
2554 ie_len = info->ie_len;
2555 reason_code = info->reason_code;
2556 locally_generated = info->locally_generated;
2557 wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s",
2558 reason_code,
2559 locally_generated ? " (locally generated)" : "");
2560 if (addr) {
2561 wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR,
2562 MAC2STR(addr));
2563 }
2564 wpa_hexdump(MSG_DEBUG, "Deauthentication frame IE(s)",
2565 ie, ie_len);
2566 }
2567
2568 wpa_reset_ft_completed(wpa_s->wpa);
2569
2570 wpas_event_disconnect(wpa_s, addr, reason_code,
2571 locally_generated, ie, ie_len, 1);
2572}
2573
2574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
2576 union wpa_event_data *data)
2577{
2578 struct wpa_supplicant *wpa_s = ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579
2580 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
2581 event != EVENT_INTERFACE_ENABLED &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002582 event != EVENT_INTERFACE_STATUS &&
2583 event != EVENT_SCHED_SCAN_STOPPED) {
2584 wpa_dbg(wpa_s, MSG_DEBUG,
2585 "Ignore event %s (%d) while interface is disabled",
2586 event_to_string(event), event);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 return;
2588 }
2589
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002590#ifndef CONFIG_NO_STDOUT_DEBUG
2591{
2592 int level = MSG_DEBUG;
2593
Dmitry Shmidt04949592012-07-19 12:16:46 -07002594 if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002595 const struct ieee80211_hdr *hdr;
2596 u16 fc;
2597 hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
2598 fc = le_to_host16(hdr->frame_control);
2599 if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
2600 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON)
2601 level = MSG_EXCESSIVE;
2602 }
2603
2604 wpa_dbg(wpa_s, level, "Event %s (%d) received",
2605 event_to_string(event), event);
2606}
2607#endif /* CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608
2609 switch (event) {
2610 case EVENT_AUTH:
2611 sme_event_auth(wpa_s, data);
2612 break;
2613 case EVENT_ASSOC:
2614 wpa_supplicant_event_assoc(wpa_s, data);
2615 break;
2616 case EVENT_DISASSOC:
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002617 wpas_event_disassoc(wpa_s,
2618 data ? &data->disassoc_info : NULL);
2619 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 case EVENT_DEAUTH:
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002621 wpas_event_deauth(wpa_s,
2622 data ? &data->deauth_info : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 break;
2624 case EVENT_MICHAEL_MIC_FAILURE:
2625 wpa_supplicant_event_michael_mic_failure(wpa_s, data);
2626 break;
2627#ifndef CONFIG_NO_SCAN_PROCESSING
2628 case EVENT_SCAN_RESULTS:
2629 wpa_supplicant_event_scan_results(wpa_s, data);
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07002630 if (wpa_s->wpa_state != WPA_AUTHENTICATING &&
2631 wpa_s->wpa_state != WPA_ASSOCIATING)
2632 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 break;
2634#endif /* CONFIG_NO_SCAN_PROCESSING */
2635 case EVENT_ASSOCINFO:
2636 wpa_supplicant_event_associnfo(wpa_s, data);
2637 break;
2638 case EVENT_INTERFACE_STATUS:
2639 wpa_supplicant_event_interface_status(wpa_s, data);
2640 break;
2641 case EVENT_PMKID_CANDIDATE:
2642 wpa_supplicant_event_pmkid_candidate(wpa_s, data);
2643 break;
2644#ifdef CONFIG_PEERKEY
2645 case EVENT_STKSTART:
2646 wpa_supplicant_event_stkstart(wpa_s, data);
2647 break;
2648#endif /* CONFIG_PEERKEY */
2649#ifdef CONFIG_TDLS
2650 case EVENT_TDLS:
2651 wpa_supplicant_event_tdls(wpa_s, data);
2652 break;
2653#endif /* CONFIG_TDLS */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002654#ifdef CONFIG_WNM
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 case EVENT_WNM:
2656 wpa_supplicant_event_wnm(wpa_s, data);
2657 break;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002658#endif /* CONFIG_WNM */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659#ifdef CONFIG_IEEE80211R
2660 case EVENT_FT_RESPONSE:
2661 wpa_supplicant_event_ft_response(wpa_s, data);
2662 break;
2663#endif /* CONFIG_IEEE80211R */
2664#ifdef CONFIG_IBSS_RSN
2665 case EVENT_IBSS_RSN_START:
2666 wpa_supplicant_event_ibss_rsn_start(wpa_s, data);
2667 break;
2668#endif /* CONFIG_IBSS_RSN */
2669 case EVENT_ASSOC_REJECT:
2670 if (data->assoc_reject.bssid)
2671 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
2672 "bssid=" MACSTR " status_code=%u",
2673 MAC2STR(data->assoc_reject.bssid),
2674 data->assoc_reject.status_code);
2675 else
2676 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
2677 "status_code=%u",
2678 data->assoc_reject.status_code);
2679 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
2680 sme_event_assoc_reject(wpa_s, data);
Jeff Johnsonb485b182012-10-21 18:19:27 -07002681 else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002682#ifdef ANDROID_P2P
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002683 if(!wpa_s->current_ssid) {
2684 wpa_printf(MSG_ERROR, "current_ssid == NULL");
2685 break;
2686 }
2687 /* If assoc reject is reported by the driver, then avoid
2688 * waiting for the authentication timeout. Cancel the
2689 * authentication timeout and retry the assoc.
2690 */
Jeff Johnsonb485b182012-10-21 18:19:27 -07002691 if(wpa_s->current_ssid->assoc_retry++ < 10) {
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002692 wpa_printf(MSG_ERROR, "Retrying assoc: %d ",
2693 wpa_s->current_ssid->assoc_retry);
Jeff Johnsonb485b182012-10-21 18:19:27 -07002694
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002695 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt98f9e762012-05-30 11:18:46 -07002696
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002697 /* Clear the states */
2698 wpa_sm_notify_disassoc(wpa_s->wpa);
2699 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2700
2701 wpa_s->reassociate = 1;
Jeff Johnsonb485b182012-10-21 18:19:27 -07002702 if (wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE) {
Dmitry Shmidt54cb0f62012-10-29 13:12:24 -07002703 const u8 *bl_bssid = data->assoc_reject.bssid;
2704 if (!bl_bssid || is_zero_ether_addr(bl_bssid))
2705 bl_bssid = wpa_s->pending_bssid;
2706 wpa_blacklist_add(wpa_s, bl_bssid);
Jeff Johnsonb485b182012-10-21 18:19:27 -07002707 wpa_supplicant_req_scan(wpa_s, 0, 0);
2708 } else {
2709 wpa_supplicant_req_scan(wpa_s, 1, 0);
2710 }
2711 } else if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002712 /* If we ASSOC_REJECT's hits threshold, disable the
2713 * network
2714 */
2715 wpa_printf(MSG_ERROR, "Assoc retry threshold reached. "
2716 "Disabling the network");
Irfan Sheriff2fb835a2012-06-18 09:39:07 -07002717 wpa_s->current_ssid->assoc_retry = 0;
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002718 wpa_supplicant_disable_network(wpa_s, wpa_s->current_ssid);
Irfan Sheriff2fb835a2012-06-18 09:39:07 -07002719 wpas_p2p_group_remove(wpa_s, wpa_s->ifname);
Irfan Sheriff7db4ef72012-06-18 09:39:07 -07002720 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002721#else
2722 const u8 *bssid = data->assoc_reject.bssid;
2723 if (bssid == NULL || is_zero_ether_addr(bssid))
2724 bssid = wpa_s->pending_bssid;
2725 wpas_connection_failed(wpa_s, bssid);
2726 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt98f9e762012-05-30 11:18:46 -07002727#endif /* ANDROID_P2P */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002728 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 break;
2730 case EVENT_AUTH_TIMED_OUT:
2731 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
2732 sme_event_auth_timed_out(wpa_s, data);
2733 break;
2734 case EVENT_ASSOC_TIMED_OUT:
2735 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
2736 sme_event_assoc_timed_out(wpa_s, data);
2737 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 case EVENT_TX_STATUS:
2739 wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS dst=" MACSTR
2740 " type=%d stype=%d",
2741 MAC2STR(data->tx_status.dst),
2742 data->tx_status.type, data->tx_status.stype);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002743#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744 if (wpa_s->ap_iface == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002745#ifdef CONFIG_OFFCHANNEL
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
2747 data->tx_status.stype == WLAN_FC_STYPE_ACTION)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002748 offchannel_send_action_tx_status(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 wpa_s, data->tx_status.dst,
2750 data->tx_status.data,
2751 data->tx_status.data_len,
2752 data->tx_status.ack ?
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002753 OFFCHANNEL_SEND_ACTION_SUCCESS :
2754 OFFCHANNEL_SEND_ACTION_NO_ACK);
2755#endif /* CONFIG_OFFCHANNEL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 break;
2757 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002758#endif /* CONFIG_AP */
2759#ifdef CONFIG_OFFCHANNEL
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002760 wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
2761 MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
2762 /*
2763 * Catch TX status events for Action frames we sent via group
2764 * interface in GO mode.
2765 */
2766 if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
2767 data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
2768 os_memcmp(wpa_s->parent->pending_action_dst,
2769 data->tx_status.dst, ETH_ALEN) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002770 offchannel_send_action_tx_status(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 wpa_s->parent, data->tx_status.dst,
2772 data->tx_status.data,
2773 data->tx_status.data_len,
2774 data->tx_status.ack ?
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002775 OFFCHANNEL_SEND_ACTION_SUCCESS :
2776 OFFCHANNEL_SEND_ACTION_NO_ACK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 break;
2778 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002779#endif /* CONFIG_OFFCHANNEL */
2780#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 switch (data->tx_status.type) {
2782 case WLAN_FC_TYPE_MGMT:
2783 ap_mgmt_tx_cb(wpa_s, data->tx_status.data,
2784 data->tx_status.data_len,
2785 data->tx_status.stype,
2786 data->tx_status.ack);
2787 break;
2788 case WLAN_FC_TYPE_DATA:
2789 ap_tx_status(wpa_s, data->tx_status.dst,
2790 data->tx_status.data,
2791 data->tx_status.data_len,
2792 data->tx_status.ack);
2793 break;
2794 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002795#endif /* CONFIG_AP */
2796 break;
2797#ifdef CONFIG_AP
2798 case EVENT_EAPOL_TX_STATUS:
2799 ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst,
2800 data->eapol_tx_status.data,
2801 data->eapol_tx_status.data_len,
2802 data->eapol_tx_status.ack);
2803 break;
2804 case EVENT_DRIVER_CLIENT_POLL_OK:
2805 ap_client_poll_ok(wpa_s, data->client_poll.addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 break;
2807 case EVENT_RX_FROM_UNKNOWN:
2808 if (wpa_s->ap_iface == NULL)
2809 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002810 ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr,
2811 data->rx_from_unknown.wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002813 case EVENT_CH_SWITCH:
2814 if (!data)
2815 break;
2816 if (!wpa_s->ap_iface) {
2817 wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch "
2818 "event in non-AP mode");
2819 break;
2820 }
2821
Dmitry Shmidt04949592012-07-19 12:16:46 -07002822 wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
2823 data->ch_switch.ht_enabled,
2824 data->ch_switch.ch_offset);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002825 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002826#endif /* CONFIG_AP */
2827#if defined(CONFIG_AP) || defined(CONFIG_IBSS_RSN)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002828 case EVENT_RX_MGMT: {
2829 u16 fc, stype;
2830 const struct ieee80211_mgmt *mgmt;
2831
2832 mgmt = (const struct ieee80211_mgmt *)
2833 data->rx_mgmt.frame;
2834 fc = le_to_host16(mgmt->frame_control);
2835 stype = WLAN_FC_GET_STYPE(fc);
2836
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002837#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 if (wpa_s->ap_iface == NULL) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002839#endif /* CONFIG_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841 if (stype == WLAN_FC_STYPE_PROBE_REQ &&
2842 data->rx_mgmt.frame_len > 24) {
2843 const u8 *src = mgmt->sa;
2844 const u8 *ie = mgmt->u.probe_req.variable;
2845 size_t ie_len = data->rx_mgmt.frame_len -
2846 (mgmt->u.probe_req.variable -
2847 data->rx_mgmt.frame);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002848 wpas_p2p_probe_req_rx(
2849 wpa_s, src, mgmt->da,
2850 mgmt->bssid, ie, ie_len,
2851 data->rx_mgmt.ssi_signal);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002852 break;
2853 }
2854#endif /* CONFIG_P2P */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002855#ifdef CONFIG_IBSS_RSN
2856 if (stype == WLAN_FC_STYPE_AUTH &&
2857 data->rx_mgmt.frame_len >= 30) {
2858 wpa_supplicant_event_ibss_auth(wpa_s, data);
2859 break;
2860 }
2861#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862 wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received "
2863 "management frame in non-AP mode");
2864 break;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002865#ifdef CONFIG_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07002867
2868 if (stype == WLAN_FC_STYPE_PROBE_REQ &&
2869 data->rx_mgmt.frame_len > 24) {
2870 const u8 *ie = mgmt->u.probe_req.variable;
2871 size_t ie_len = data->rx_mgmt.frame_len -
2872 (mgmt->u.probe_req.variable -
2873 data->rx_mgmt.frame);
2874
2875 wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da,
2876 mgmt->bssid, ie, ie_len,
2877 data->rx_mgmt.ssi_signal);
2878 }
2879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 ap_mgmt_rx(wpa_s, &data->rx_mgmt);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002881#endif /* CONFIG_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002882 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002883 }
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002884#endif /* CONFIG_AP || CONFIG_IBSS_RSN */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 case EVENT_RX_ACTION:
2886 wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR
2887 " Category=%u DataLen=%d freq=%d MHz",
2888 MAC2STR(data->rx_action.sa),
2889 data->rx_action.category, (int) data->rx_action.len,
2890 data->rx_action.freq);
2891#ifdef CONFIG_IEEE80211R
2892 if (data->rx_action.category == WLAN_ACTION_FT) {
2893 ft_rx_action(wpa_s, data->rx_action.data,
2894 data->rx_action.len);
2895 break;
2896 }
2897#endif /* CONFIG_IEEE80211R */
2898#ifdef CONFIG_IEEE80211W
2899#ifdef CONFIG_SME
2900 if (data->rx_action.category == WLAN_ACTION_SA_QUERY) {
2901 sme_sa_query_rx(wpa_s, data->rx_action.sa,
2902 data->rx_action.data,
2903 data->rx_action.len);
2904 break;
2905 }
2906#endif /* CONFIG_SME */
2907#endif /* CONFIG_IEEE80211W */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002908#ifdef CONFIG_WNM
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002909 if (data->rx_action.category == WLAN_ACTION_WNM) {
2910 ieee802_11_rx_wnm_action(wpa_s, &data->rx_action);
2911 break;
2912 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002913#endif /* CONFIG_WNM */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002914#ifdef CONFIG_GAS
2915 if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
2916 gas_query_rx(wpa_s->gas, data->rx_action.da,
2917 data->rx_action.sa, data->rx_action.bssid,
2918 data->rx_action.data, data->rx_action.len,
2919 data->rx_action.freq) == 0)
2920 break;
2921#endif /* CONFIG_GAS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002922#ifdef CONFIG_TDLS
2923 if (data->rx_action.category == WLAN_ACTION_PUBLIC &&
2924 data->rx_action.len >= 4 &&
2925 data->rx_action.data[0] == WLAN_TDLS_DISCOVERY_RESPONSE) {
2926 wpa_dbg(wpa_s, MSG_DEBUG, "TDLS: Received Discovery "
2927 "Response from " MACSTR,
2928 MAC2STR(data->rx_action.sa));
2929 break;
2930 }
2931#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002932#ifdef CONFIG_P2P
2933 wpas_p2p_rx_action(wpa_s, data->rx_action.da,
2934 data->rx_action.sa,
2935 data->rx_action.bssid,
2936 data->rx_action.category,
2937 data->rx_action.data,
2938 data->rx_action.len, data->rx_action.freq);
2939#endif /* CONFIG_P2P */
2940 break;
2941 case EVENT_RX_PROBE_REQ:
2942 if (data->rx_probe_req.sa == NULL ||
2943 data->rx_probe_req.ie == NULL)
2944 break;
2945#ifdef CONFIG_AP
2946 if (wpa_s->ap_iface) {
2947 hostapd_probe_req_rx(wpa_s->ap_iface->bss[0],
2948 data->rx_probe_req.sa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002949 data->rx_probe_req.da,
2950 data->rx_probe_req.bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 data->rx_probe_req.ie,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002952 data->rx_probe_req.ie_len,
2953 data->rx_probe_req.ssi_signal);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002954 break;
2955 }
2956#endif /* CONFIG_AP */
2957#ifdef CONFIG_P2P
2958 wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002959 data->rx_probe_req.da,
2960 data->rx_probe_req.bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 data->rx_probe_req.ie,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002962 data->rx_probe_req.ie_len,
2963 data->rx_probe_req.ssi_signal);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964#endif /* CONFIG_P2P */
2965 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 case EVENT_REMAIN_ON_CHANNEL:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002967#ifdef CONFIG_OFFCHANNEL
2968 offchannel_remain_on_channel_cb(
2969 wpa_s, data->remain_on_channel.freq,
2970 data->remain_on_channel.duration);
2971#endif /* CONFIG_OFFCHANNEL */
2972#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 wpas_p2p_remain_on_channel_cb(
2974 wpa_s, data->remain_on_channel.freq,
2975 data->remain_on_channel.duration);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002976#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 break;
2978 case EVENT_CANCEL_REMAIN_ON_CHANNEL:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002979#ifdef CONFIG_OFFCHANNEL
2980 offchannel_cancel_remain_on_channel_cb(
2981 wpa_s, data->remain_on_channel.freq);
2982#endif /* CONFIG_OFFCHANNEL */
2983#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 wpas_p2p_cancel_remain_on_channel_cb(
2985 wpa_s, data->remain_on_channel.freq);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002986#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002987 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002988#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002989 case EVENT_P2P_DEV_FOUND: {
2990 struct p2p_peer_info peer_info;
2991
2992 os_memset(&peer_info, 0, sizeof(peer_info));
2993 if (data->p2p_dev_found.dev_addr)
2994 os_memcpy(peer_info.p2p_device_addr,
2995 data->p2p_dev_found.dev_addr, ETH_ALEN);
2996 if (data->p2p_dev_found.pri_dev_type)
2997 os_memcpy(peer_info.pri_dev_type,
2998 data->p2p_dev_found.pri_dev_type,
2999 sizeof(peer_info.pri_dev_type));
3000 if (data->p2p_dev_found.dev_name)
3001 os_strlcpy(peer_info.device_name,
3002 data->p2p_dev_found.dev_name,
3003 sizeof(peer_info.device_name));
3004 peer_info.config_methods = data->p2p_dev_found.config_methods;
3005 peer_info.dev_capab = data->p2p_dev_found.dev_capab;
3006 peer_info.group_capab = data->p2p_dev_found.group_capab;
3007
3008 /*
3009 * FIX: new_device=1 is not necessarily correct. We should
3010 * maintain a P2P peer database in wpa_supplicant and update
3011 * this information based on whether the peer is truly new.
3012 */
3013 wpas_dev_found(wpa_s, data->p2p_dev_found.addr, &peer_info, 1);
3014 break;
3015 }
3016 case EVENT_P2P_GO_NEG_REQ_RX:
3017 wpas_go_neg_req_rx(wpa_s, data->p2p_go_neg_req_rx.src,
3018 data->p2p_go_neg_req_rx.dev_passwd_id);
3019 break;
3020 case EVENT_P2P_GO_NEG_COMPLETED:
3021 wpas_go_neg_completed(wpa_s, data->p2p_go_neg_completed.res);
3022 break;
3023 case EVENT_P2P_PROV_DISC_REQUEST:
3024 wpas_prov_disc_req(wpa_s, data->p2p_prov_disc_req.peer,
3025 data->p2p_prov_disc_req.config_methods,
3026 data->p2p_prov_disc_req.dev_addr,
3027 data->p2p_prov_disc_req.pri_dev_type,
3028 data->p2p_prov_disc_req.dev_name,
3029 data->p2p_prov_disc_req.supp_config_methods,
3030 data->p2p_prov_disc_req.dev_capab,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003031 data->p2p_prov_disc_req.group_capab,
3032 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003033 break;
3034 case EVENT_P2P_PROV_DISC_RESPONSE:
3035 wpas_prov_disc_resp(wpa_s, data->p2p_prov_disc_resp.peer,
3036 data->p2p_prov_disc_resp.config_methods);
3037 break;
3038 case EVENT_P2P_SD_REQUEST:
3039 wpas_sd_request(wpa_s, data->p2p_sd_req.freq,
3040 data->p2p_sd_req.sa,
3041 data->p2p_sd_req.dialog_token,
3042 data->p2p_sd_req.update_indic,
3043 data->p2p_sd_req.tlvs,
3044 data->p2p_sd_req.tlvs_len);
3045 break;
3046 case EVENT_P2P_SD_RESPONSE:
3047 wpas_sd_response(wpa_s, data->p2p_sd_resp.sa,
3048 data->p2p_sd_resp.update_indic,
3049 data->p2p_sd_resp.tlvs,
3050 data->p2p_sd_resp.tlvs_len);
3051 break;
3052#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003053 case EVENT_EAPOL_RX:
3054 wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src,
3055 data->eapol_rx.data,
3056 data->eapol_rx.data_len);
3057 break;
3058 case EVENT_SIGNAL_CHANGE:
3059 bgscan_notify_signal_change(
3060 wpa_s, data->signal_change.above_threshold,
3061 data->signal_change.current_signal,
3062 data->signal_change.current_noise,
3063 data->signal_change.current_txrate);
3064 break;
3065 case EVENT_INTERFACE_ENABLED:
3066 wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled");
3067 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003068 wpa_supplicant_update_mac_addr(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003069#ifdef CONFIG_AP
3070 if (!wpa_s->ap_iface) {
3071 wpa_supplicant_set_state(wpa_s,
3072 WPA_DISCONNECTED);
3073 wpa_supplicant_req_scan(wpa_s, 0, 0);
3074 } else
3075 wpa_supplicant_set_state(wpa_s,
3076 WPA_COMPLETED);
3077#else /* CONFIG_AP */
3078 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
3079 wpa_supplicant_req_scan(wpa_s, 0, 0);
3080#endif /* CONFIG_AP */
3081 }
3082 break;
3083 case EVENT_INTERFACE_DISABLED:
3084 wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled");
3085 wpa_supplicant_mark_disassoc(wpa_s);
3086 wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
3087 break;
3088 case EVENT_CHANNEL_LIST_CHANGED:
3089 if (wpa_s->drv_priv == NULL)
3090 break; /* Ignore event during drv initialization */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003091
3092 free_hw_features(wpa_s);
3093 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(
3094 wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags);
3095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003096#ifdef CONFIG_P2P
3097 wpas_p2p_update_channel_list(wpa_s);
3098#endif /* CONFIG_P2P */
3099 break;
3100 case EVENT_INTERFACE_UNAVAILABLE:
3101#ifdef CONFIG_P2P
3102 wpas_p2p_interface_unavailable(wpa_s);
3103#endif /* CONFIG_P2P */
3104 break;
3105 case EVENT_BEST_CHANNEL:
3106 wpa_dbg(wpa_s, MSG_DEBUG, "Best channel event received "
3107 "(%d %d %d)",
3108 data->best_chan.freq_24, data->best_chan.freq_5,
3109 data->best_chan.freq_overall);
3110 wpa_s->best_24_freq = data->best_chan.freq_24;
3111 wpa_s->best_5_freq = data->best_chan.freq_5;
3112 wpa_s->best_overall_freq = data->best_chan.freq_overall;
3113#ifdef CONFIG_P2P
3114 wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24,
3115 data->best_chan.freq_5,
3116 data->best_chan.freq_overall);
3117#endif /* CONFIG_P2P */
3118 break;
3119 case EVENT_UNPROT_DEAUTH:
3120 wpa_supplicant_event_unprot_deauth(wpa_s,
3121 &data->unprot_deauth);
3122 break;
3123 case EVENT_UNPROT_DISASSOC:
3124 wpa_supplicant_event_unprot_disassoc(wpa_s,
3125 &data->unprot_disassoc);
3126 break;
3127 case EVENT_STATION_LOW_ACK:
3128#ifdef CONFIG_AP
3129 if (wpa_s->ap_iface && data)
3130 hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0],
3131 data->low_ack.addr);
3132#endif /* CONFIG_AP */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003133#ifdef CONFIG_TDLS
3134 if (data)
3135 wpa_tdls_disable_link(wpa_s->wpa, data->low_ack.addr);
3136#endif /* CONFIG_TDLS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003137 break;
3138 case EVENT_IBSS_PEER_LOST:
3139#ifdef CONFIG_IBSS_RSN
3140 ibss_rsn_stop(wpa_s->ibss_rsn, data->ibss_peer_lost.peer);
3141#endif /* CONFIG_IBSS_RSN */
3142 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003143 case EVENT_DRIVER_GTK_REKEY:
3144 if (os_memcmp(data->driver_gtk_rekey.bssid,
3145 wpa_s->bssid, ETH_ALEN))
3146 break;
3147 if (!wpa_s->wpa)
3148 break;
3149 wpa_sm_update_replay_ctr(wpa_s->wpa,
3150 data->driver_gtk_rekey.replay_ctr);
3151 break;
3152 case EVENT_SCHED_SCAN_STOPPED:
3153 wpa_s->sched_scanning = 0;
3154 wpa_supplicant_notify_scanning(wpa_s, 0);
3155
3156 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
3157 break;
3158
3159 /*
3160 * If we timed out, start a new sched scan to continue
3161 * searching for more SSIDs.
3162 */
3163 if (wpa_s->sched_scan_timed_out)
3164 wpa_supplicant_req_sched_scan(wpa_s);
3165 break;
3166 case EVENT_WPS_BUTTON_PUSHED:
3167#ifdef CONFIG_WPS
3168 wpas_wps_start_pbc(wpa_s, NULL, 0);
3169#endif /* CONFIG_WPS */
3170 break;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003171 case EVENT_CONNECT_FAILED_REASON:
3172#ifdef CONFIG_AP
3173 if (!wpa_s->ap_iface || !data)
3174 break;
3175 hostapd_event_connect_failed_reason(
3176 wpa_s->ap_iface->bss[0],
3177 data->connect_failed_reason.addr,
3178 data->connect_failed_reason.code);
3179#endif /* CONFIG_AP */
3180 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003181 default:
3182 wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
3183 break;
3184 }
3185}