1 |
/* |
2 |
* WPA Supplicant - Driver event processing |
3 |
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> |
4 |
* |
5 |
* This software may be distributed under the terms of the BSD license. |
6 |
* See README for more details. |
7 |
*/ |
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" |
26 |
#include "wnm_sta.h" |
27 |
#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" |
36 |
#include "gas_query.h" |
37 |
#include "p2p_supplicant.h" |
38 |
#include "bgscan.h" |
39 |
#include "autoscan.h" |
40 |
#include "ap.h" |
41 |
#include "bss.h" |
42 |
#include "scan.h" |
43 |
#include "offchannel.h" |
44 |
#include "interworking.h" |
45 |
|
46 |
|
47 |
static int wpas_temp_disabled(struct wpa_supplicant *wpa_s, |
48 |
struct wpa_ssid *ssid) |
49 |
{ |
50 |
struct os_time now; |
51 |
|
52 |
if (ssid == NULL || ssid->disabled_until.sec == 0) |
53 |
return 0; |
54 |
|
55 |
os_get_time(&now); |
56 |
if (ssid->disabled_until.sec > now.sec) |
57 |
return ssid->disabled_until.sec - now.sec; |
58 |
|
59 |
wpas_clear_temp_disabled(wpa_s, ssid, 0); |
60 |
|
61 |
return 0; |
62 |
} |
63 |
|
64 |
|
65 |
static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) |
66 |
{ |
67 |
struct wpa_ssid *ssid, *old_ssid; |
68 |
int res; |
69 |
|
70 |
if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) |
71 |
return 0; |
72 |
|
73 |
wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association " |
74 |
"information"); |
75 |
ssid = wpa_supplicant_get_ssid(wpa_s); |
76 |
if (ssid == NULL) { |
77 |
wpa_msg(wpa_s, MSG_INFO, |
78 |
"No network configuration found for the current AP"); |
79 |
return -1; |
80 |
} |
81 |
|
82 |
if (wpas_network_disabled(wpa_s, ssid)) { |
83 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is disabled"); |
84 |
return -1; |
85 |
} |
86 |
|
87 |
if (disallowed_bssid(wpa_s, wpa_s->bssid) || |
88 |
disallowed_ssid(wpa_s, ssid->ssid, ssid->ssid_len)) { |
89 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS is disallowed"); |
90 |
return -1; |
91 |
} |
92 |
|
93 |
res = wpas_temp_disabled(wpa_s, ssid); |
94 |
if (res > 0) { |
95 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is temporarily " |
96 |
"disabled for %d second(s)", res); |
97 |
return -1; |
98 |
} |
99 |
|
100 |
wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the " |
101 |
"current AP"); |
102 |
if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { |
103 |
u8 wpa_ie[80]; |
104 |
size_t wpa_ie_len = sizeof(wpa_ie); |
105 |
wpa_supplicant_set_suites(wpa_s, NULL, ssid, |
106 |
wpa_ie, &wpa_ie_len); |
107 |
} else { |
108 |
wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); |
109 |
} |
110 |
|
111 |
if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) |
112 |
eapol_sm_invalidate_cached_session(wpa_s->eapol); |
113 |
old_ssid = wpa_s->current_ssid; |
114 |
wpa_s->current_ssid = ssid; |
115 |
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); |
116 |
wpa_supplicant_initiate_eapol(wpa_s); |
117 |
if (old_ssid != wpa_s->current_ssid) |
118 |
wpas_notify_network_changed(wpa_s); |
119 |
|
120 |
return 0; |
121 |
} |
122 |
|
123 |
|
124 |
void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx) |
125 |
{ |
126 |
struct wpa_supplicant *wpa_s = eloop_ctx; |
127 |
|
128 |
if (wpa_s->countermeasures) { |
129 |
wpa_s->countermeasures = 0; |
130 |
wpa_drv_set_countermeasures(wpa_s, 0); |
131 |
wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped"); |
132 |
wpa_supplicant_req_scan(wpa_s, 0, 0); |
133 |
} |
134 |
} |
135 |
|
136 |
|
137 |
void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) |
138 |
{ |
139 |
int bssid_changed; |
140 |
|
141 |
wnm_bss_keep_alive_deinit(wpa_s); |
142 |
|
143 |
#ifdef CONFIG_IBSS_RSN |
144 |
ibss_rsn_deinit(wpa_s->ibss_rsn); |
145 |
wpa_s->ibss_rsn = NULL; |
146 |
#endif /* CONFIG_IBSS_RSN */ |
147 |
|
148 |
#ifdef CONFIG_AP |
149 |
wpa_supplicant_ap_deinit(wpa_s); |
150 |
#endif /* CONFIG_AP */ |
151 |
|
152 |
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) |
153 |
return; |
154 |
|
155 |
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); |
156 |
bssid_changed = !is_zero_ether_addr(wpa_s->bssid); |
157 |
os_memset(wpa_s->bssid, 0, ETH_ALEN); |
158 |
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); |
159 |
#ifdef CONFIG_SME |
160 |
wpa_s->sme.prev_bssid_set = 0; |
161 |
#endif /* CONFIG_SME */ |
162 |
#ifdef CONFIG_P2P |
163 |
os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); |
164 |
#endif /* CONFIG_P2P */ |
165 |
wpa_s->current_bss = NULL; |
166 |
wpa_s->assoc_freq = 0; |
167 |
#ifdef CONFIG_IEEE80211R |
168 |
#ifdef CONFIG_SME |
169 |
if (wpa_s->sme.ft_ies) |
170 |
sme_update_ft_ies(wpa_s, NULL, NULL, 0); |
171 |
#endif /* CONFIG_SME */ |
172 |
#endif /* CONFIG_IEEE80211R */ |
173 |
|
174 |
if (bssid_changed) |
175 |
wpas_notify_bssid_changed(wpa_s); |
176 |
|
177 |
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); |
178 |
eapol_sm_notify_portValid(wpa_s->eapol, FALSE); |
179 |
if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) |
180 |
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); |
181 |
wpa_s->ap_ies_from_associnfo = 0; |
182 |
wpa_s->current_ssid = NULL; |
183 |
wpa_s->key_mgmt = 0; |
184 |
wpa_s->wnmsleep_used = 0; |
185 |
} |
186 |
|
187 |
|
188 |
static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) |
189 |
{ |
190 |
struct wpa_ie_data ie; |
191 |
int pmksa_set = -1; |
192 |
size_t i; |
193 |
|
194 |
if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 || |
195 |
ie.pmkid == NULL) |
196 |
return; |
197 |
|
198 |
for (i = 0; i < ie.num_pmkid; i++) { |
199 |
pmksa_set = pmksa_cache_set_current(wpa_s->wpa, |
200 |
ie.pmkid + i * PMKID_LEN, |
201 |
NULL, NULL, 0); |
202 |
if (pmksa_set == 0) { |
203 |
eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); |
204 |
break; |
205 |
} |
206 |
} |
207 |
|
208 |
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from " |
209 |
"PMKSA cache", pmksa_set == 0 ? "" : "not "); |
210 |
} |
211 |
|
212 |
|
213 |
static void wpa_supplicant_event_pmkid_candidate(struct wpa_supplicant *wpa_s, |
214 |
union wpa_event_data *data) |
215 |
{ |
216 |
if (data == NULL) { |
217 |
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: No data in PMKID candidate " |
218 |
"event"); |
219 |
return; |
220 |
} |
221 |
wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR |
222 |
" index=%d preauth=%d", |
223 |
MAC2STR(data->pmkid_candidate.bssid), |
224 |
data->pmkid_candidate.index, |
225 |
data->pmkid_candidate.preauth); |
226 |
|
227 |
pmksa_candidate_add(wpa_s->wpa, data->pmkid_candidate.bssid, |
228 |
data->pmkid_candidate.index, |
229 |
data->pmkid_candidate.preauth); |
230 |
} |
231 |
|
232 |
|
233 |
static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s) |
234 |
{ |
235 |
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || |
236 |
wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) |
237 |
return 0; |
238 |
|
239 |
#ifdef IEEE8021X_EAPOL |
240 |
if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA && |
241 |
wpa_s->current_ssid && |
242 |
!(wpa_s->current_ssid->eapol_flags & |
243 |
(EAPOL_FLAG_REQUIRE_KEY_UNICAST | |
244 |
EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { |
245 |
/* IEEE 802.1X, but not using dynamic WEP keys (i.e., either |
246 |
* plaintext or static WEP keys). */ |
247 |
return 0; |
248 |
} |
249 |
#endif /* IEEE8021X_EAPOL */ |
250 |
|
251 |
return 1; |
252 |
} |
253 |
|
254 |
|
255 |
/** |
256 |
* wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC |
257 |
* @wpa_s: pointer to wpa_supplicant data |
258 |
* @ssid: Configuration data for the network |
259 |
* Returns: 0 on success, -1 on failure |
260 |
* |
261 |
* This function is called when starting authentication with a network that is |
262 |
* configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA). |
263 |
*/ |
264 |
int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, |
265 |
struct wpa_ssid *ssid) |
266 |
{ |
267 |
#ifdef IEEE8021X_EAPOL |
268 |
#ifdef PCSC_FUNCS |
269 |
int aka = 0, sim = 0, type; |
270 |
|
271 |
if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL) |
272 |
return 0; |
273 |
|
274 |
if (ssid->eap.eap_methods == NULL) { |
275 |
sim = 1; |
276 |
aka = 1; |
277 |
} else { |
278 |
struct eap_method_type *eap = ssid->eap.eap_methods; |
279 |
while (eap->vendor != EAP_VENDOR_IETF || |
280 |
eap->method != EAP_TYPE_NONE) { |
281 |
if (eap->vendor == EAP_VENDOR_IETF) { |
282 |
if (eap->method == EAP_TYPE_SIM) |
283 |
sim = 1; |
284 |
else if (eap->method == EAP_TYPE_AKA || |
285 |
eap->method == EAP_TYPE_AKA_PRIME) |
286 |
aka = 1; |
287 |
} |
288 |
eap++; |
289 |
} |
290 |
} |
291 |
|
292 |
if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL) |
293 |
sim = 0; |
294 |
if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL && |
295 |
eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME) == |
296 |
NULL) |
297 |
aka = 0; |
298 |
|
299 |
if (!sim && !aka) { |
300 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to " |
301 |
"use SIM, but neither EAP-SIM nor EAP-AKA are " |
302 |
"enabled"); |
303 |
return 0; |
304 |
} |
305 |
|
306 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM " |
307 |
"(sim=%d aka=%d) - initialize PCSC", sim, aka); |
308 |
if (sim && aka) |
309 |
type = SCARD_TRY_BOTH; |
310 |
else if (aka) |
311 |
type = SCARD_USIM_ONLY; |
312 |
else |
313 |
type = SCARD_GSM_SIM_ONLY; |
314 |
|
315 |
wpa_s->scard = scard_init(type, NULL); |
316 |
if (wpa_s->scard == NULL) { |
317 |
wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM " |
318 |
"(pcsc-lite)"); |
319 |
return -1; |
320 |
} |
321 |
wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard); |
322 |
eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); |
323 |
#endif /* PCSC_FUNCS */ |
324 |
#endif /* IEEE8021X_EAPOL */ |
325 |
|
326 |
return 0; |
327 |
} |
328 |
|
329 |
|
330 |
#ifndef CONFIG_NO_SCAN_PROCESSING |
331 |
static int wpa_supplicant_match_privacy(struct wpa_bss *bss, |
332 |
struct wpa_ssid *ssid) |
333 |
{ |
334 |
int i, privacy = 0; |
335 |
|
336 |
if (ssid->mixed_cell) |
337 |
return 1; |
338 |
|
339 |
#ifdef CONFIG_WPS |
340 |
if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) |
341 |
return 1; |
342 |
#endif /* CONFIG_WPS */ |
343 |
|
344 |
for (i = 0; i < NUM_WEP_KEYS; i++) { |
345 |
if (ssid->wep_key_len[i]) { |
346 |
privacy = 1; |
347 |
break; |
348 |
} |
349 |
} |
350 |
#ifdef IEEE8021X_EAPOL |
351 |
if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && |
352 |
ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | |
353 |
EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) |
354 |
privacy = 1; |
355 |
#endif /* IEEE8021X_EAPOL */ |
356 |
|
357 |
if (wpa_key_mgmt_wpa(ssid->key_mgmt)) |
358 |
privacy = 1; |
359 |
|
360 |
if (bss->caps & IEEE80211_CAP_PRIVACY) |
361 |
return privacy; |
362 |
return !privacy; |
363 |
} |
364 |
|
365 |
|
366 |
static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, |
367 |
struct wpa_ssid *ssid, |
368 |
struct wpa_bss *bss) |
369 |
{ |
370 |
struct wpa_ie_data ie; |
371 |
int proto_match = 0; |
372 |
const u8 *rsn_ie, *wpa_ie; |
373 |
int ret; |
374 |
int wep_ok; |
375 |
|
376 |
ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss); |
377 |
if (ret >= 0) |
378 |
return ret; |
379 |
|
380 |
/* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */ |
381 |
wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) && |
382 |
(((ssid->key_mgmt & WPA_KEY_MGMT_NONE) && |
383 |
ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) || |
384 |
(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); |
385 |
|
386 |
rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); |
387 |
while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) { |
388 |
proto_match++; |
389 |
|
390 |
if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) { |
391 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - parse " |
392 |
"failed"); |
393 |
break; |
394 |
} |
395 |
|
396 |
if (wep_ok && |
397 |
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) |
398 |
{ |
399 |
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN " |
400 |
"in RSN IE"); |
401 |
return 1; |
402 |
} |
403 |
|
404 |
if (!(ie.proto & ssid->proto)) { |
405 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - proto " |
406 |
"mismatch"); |
407 |
break; |
408 |
} |
409 |
|
410 |
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { |
411 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - PTK " |
412 |
"cipher mismatch"); |
413 |
break; |
414 |
} |
415 |
|
416 |
if (!(ie.group_cipher & ssid->group_cipher)) { |
417 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - GTK " |
418 |
"cipher mismatch"); |
419 |
break; |
420 |
} |
421 |
|
422 |
if (!(ie.key_mgmt & ssid->key_mgmt)) { |
423 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - key mgmt " |
424 |
"mismatch"); |
425 |
break; |
426 |
} |
427 |
|
428 |
#ifdef CONFIG_IEEE80211W |
429 |
if (!(ie.capabilities & WPA_CAPABILITY_MFPC) && |
430 |
(ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? |
431 |
wpa_s->conf->pmf : ssid->ieee80211w) == |
432 |
MGMT_FRAME_PROTECTION_REQUIRED) { |
433 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt " |
434 |
"frame protection"); |
435 |
break; |
436 |
} |
437 |
#endif /* CONFIG_IEEE80211W */ |
438 |
|
439 |
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE"); |
440 |
return 1; |
441 |
} |
442 |
|
443 |
wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); |
444 |
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) { |
445 |
proto_match++; |
446 |
|
447 |
if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) { |
448 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse " |
449 |
"failed"); |
450 |
break; |
451 |
} |
452 |
|
453 |
if (wep_ok && |
454 |
(ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) |
455 |
{ |
456 |
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN " |
457 |
"in WPA IE"); |
458 |
return 1; |
459 |
} |
460 |
|
461 |
if (!(ie.proto & ssid->proto)) { |
462 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto " |
463 |
"mismatch"); |
464 |
break; |
465 |
} |
466 |
|
467 |
if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { |
468 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK " |
469 |
"cipher mismatch"); |
470 |
break; |
471 |
} |
472 |
|
473 |
if (!(ie.group_cipher & ssid->group_cipher)) { |
474 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK " |
475 |
"cipher mismatch"); |
476 |
break; |
477 |
} |
478 |
|
479 |
if (!(ie.key_mgmt & ssid->key_mgmt)) { |
480 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt " |
481 |
"mismatch"); |
482 |
break; |
483 |
} |
484 |
|
485 |
wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE"); |
486 |
return 1; |
487 |
} |
488 |
|
489 |
if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie && |
490 |
!rsn_ie) { |
491 |
wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X"); |
492 |
return 1; |
493 |
} |
494 |
|
495 |
if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) && |
496 |
wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) { |
497 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match"); |
498 |
return 0; |
499 |
} |
500 |
|
501 |
if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) { |
502 |
wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2"); |
503 |
return 1; |
504 |
} |
505 |
|
506 |
wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with " |
507 |
"WPA/WPA2"); |
508 |
|
509 |
return 0; |
510 |
} |
511 |
|
512 |
|
513 |
static int freq_allowed(int *freqs, int freq) |
514 |
{ |
515 |
int i; |
516 |
|
517 |
if (freqs == NULL) |
518 |
return 1; |
519 |
|
520 |
for (i = 0; freqs[i]; i++) |
521 |
if (freqs[i] == freq) |
522 |
return 1; |
523 |
return 0; |
524 |
} |
525 |
|
526 |
|
527 |
static int ht_supported(const struct hostapd_hw_modes *mode) |
528 |
{ |
529 |
if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { |
530 |
/* |
531 |
* The driver did not indicate whether it supports HT. Assume |
532 |
* it does to avoid connection issues. |
533 |
*/ |
534 |
return 1; |
535 |
} |
536 |
|
537 |
/* |
538 |
* IEEE Std 802.11n-2009 20.1.1: |
539 |
* An HT non-AP STA shall support all EQM rates for one spatial stream. |
540 |
*/ |
541 |
return mode->mcs_set[0] == 0xff; |
542 |
} |
543 |
|
544 |
|
545 |
static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) |
546 |
{ |
547 |
const struct hostapd_hw_modes *mode = NULL, *modes; |
548 |
const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES }; |
549 |
const u8 *rate_ie; |
550 |
int i, j, k; |
551 |
|
552 |
if (bss->freq == 0) |
553 |
return 1; /* Cannot do matching without knowing band */ |
554 |
|
555 |
modes = wpa_s->hw.modes; |
556 |
if (modes == NULL) { |
557 |
/* |
558 |
* The driver does not provide any additional information |
559 |
* about the utilized hardware, so allow the connection attempt |
560 |
* to continue. |
561 |
*/ |
562 |
return 1; |
563 |
} |
564 |
|
565 |
for (i = 0; i < wpa_s->hw.num_modes; i++) { |
566 |
for (j = 0; j < modes[i].num_channels; j++) { |
567 |
int freq = modes[i].channels[j].freq; |
568 |
if (freq == bss->freq) { |
569 |
if (mode && |
570 |
mode->mode == HOSTAPD_MODE_IEEE80211G) |
571 |
break; /* do not allow 802.11b replace |
572 |
* 802.11g */ |
573 |
mode = &modes[i]; |
574 |
break; |
575 |
} |
576 |
} |
577 |
} |
578 |
|
579 |
if (mode == NULL) |
580 |
return 0; |
581 |
|
582 |
for (i = 0; i < (int) sizeof(scan_ie); i++) { |
583 |
rate_ie = wpa_bss_get_ie(bss, scan_ie[i]); |
584 |
if (rate_ie == NULL) |
585 |
continue; |
586 |
|
587 |
for (j = 2; j < rate_ie[1] + 2; j++) { |
588 |
int flagged = !!(rate_ie[j] & 0x80); |
589 |
int r = (rate_ie[j] & 0x7f) * 5; |
590 |
|
591 |
/* |
592 |
* IEEE Std 802.11n-2009 7.3.2.2: |
593 |
* The new BSS Membership selector value is encoded |
594 |
* like a legacy basic rate, but it is not a rate and |
595 |
* only indicates if the BSS members are required to |
596 |
* support the mandatory features of Clause 20 [HT PHY] |
597 |
* in order to join the BSS. |
598 |
*/ |
599 |
if (flagged && ((rate_ie[j] & 0x7f) == |
600 |
BSS_MEMBERSHIP_SELECTOR_HT_PHY)) { |
601 |
if (!ht_supported(mode)) { |
602 |
wpa_dbg(wpa_s, MSG_DEBUG, |
603 |
" hardware does not support " |
604 |
"HT PHY"); |
605 |
return 0; |
606 |
} |
607 |
continue; |
608 |
} |
609 |
|
610 |
if (!flagged) |
611 |
continue; |
612 |
|
613 |
/* check for legacy basic rates */ |
614 |
for (k = 0; k < mode->num_rates; k++) { |
615 |
if (mode->rates[k] == r) |
616 |
break; |
617 |
} |
618 |
if (k == mode->num_rates) { |
619 |
/* |
620 |
* IEEE Std 802.11-2007 7.3.2.2 demands that in |
621 |
* order to join a BSS all required rates |
622 |
* have to be supported by the hardware. |
623 |
*/ |
624 |
wpa_dbg(wpa_s, MSG_DEBUG, " hardware does " |
625 |
"not support required rate %d.%d Mbps", |
626 |
r / 10, r % 10); |
627 |
return 0; |
628 |
} |
629 |
} |
630 |
} |
631 |
|
632 |
return 1; |
633 |
} |
634 |
|
635 |
|
636 |
static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, |
637 |
int i, struct wpa_bss *bss, |
638 |
struct wpa_ssid *group) |
639 |
{ |
640 |
u8 wpa_ie_len, rsn_ie_len; |
641 |
int wpa; |
642 |
struct wpa_blacklist *e; |
643 |
const u8 *ie; |
644 |
struct wpa_ssid *ssid; |
645 |
|
646 |
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); |
647 |
wpa_ie_len = ie ? ie[1] : 0; |
648 |
|
649 |
ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); |
650 |
rsn_ie_len = ie ? ie[1] : 0; |
651 |
|
652 |
wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " |
653 |
"wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s", |
654 |
i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), |
655 |
wpa_ie_len, rsn_ie_len, bss->caps, bss->level, |
656 |
wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : ""); |
657 |
|
658 |
e = wpa_blacklist_get(wpa_s, bss->bssid); |
659 |
if (e) { |
660 |
int limit = 1; |
661 |
if (wpa_supplicant_enabled_networks(wpa_s) == 1) { |
662 |
/* |
663 |
* When only a single network is enabled, we can |
664 |
* trigger blacklisting on the first failure. This |
665 |
* should not be done with multiple enabled networks to |
666 |
* avoid getting forced to move into a worse ESS on |
667 |
* single error if there are no other BSSes of the |
668 |
* current ESS. |
669 |
*/ |
670 |
limit = 0; |
671 |
} |
672 |
if (e->count > limit) { |
673 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " |
674 |
"(count=%d limit=%d)", e->count, limit); |
675 |
return NULL; |
676 |
} |
677 |
} |
678 |
|
679 |
if (bss->ssid_len == 0) { |
680 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); |
681 |
return NULL; |
682 |
} |
683 |
|
684 |
if (disallowed_bssid(wpa_s, bss->bssid)) { |
685 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed"); |
686 |
return NULL; |
687 |
} |
688 |
|
689 |
if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { |
690 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); |
691 |
return NULL; |
692 |
} |
693 |
|
694 |
wpa = wpa_ie_len > 0 || rsn_ie_len > 0; |
695 |
|
696 |
for (ssid = group; ssid; ssid = ssid->pnext) { |
697 |
int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); |
698 |
int res; |
699 |
|
700 |
if (wpas_network_disabled(wpa_s, ssid)) { |
701 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); |
702 |
continue; |
703 |
} |
704 |
|
705 |
res = wpas_temp_disabled(wpa_s, ssid); |
706 |
if (res > 0) { |
707 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled " |
708 |
"temporarily for %d second(s)", res); |
709 |
continue; |
710 |
} |
711 |
|
712 |
#ifdef CONFIG_WPS |
713 |
if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { |
714 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " |
715 |
"(WPS)"); |
716 |
continue; |
717 |
} |
718 |
|
719 |
if (wpa && ssid->ssid_len == 0 && |
720 |
wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) |
721 |
check_ssid = 0; |
722 |
|
723 |
if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { |
724 |
/* Only allow wildcard SSID match if an AP |
725 |
* advertises active WPS operation that matches |
726 |
* with our mode. */ |
727 |
check_ssid = 1; |
728 |
if (ssid->ssid_len == 0 && |
729 |
wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) |
730 |
check_ssid = 0; |
731 |
} |
732 |
#endif /* CONFIG_WPS */ |
733 |
|
734 |
if (ssid->bssid_set && ssid->ssid_len == 0 && |
735 |
os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) |
736 |
check_ssid = 0; |
737 |
|
738 |
if (check_ssid && |
739 |
(bss->ssid_len != ssid->ssid_len || |
740 |
os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) { |
741 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); |
742 |
continue; |
743 |
} |
744 |
|
745 |
if (ssid->bssid_set && |
746 |
os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { |
747 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch"); |
748 |
continue; |
749 |
} |
750 |
|
751 |
if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) |
752 |
continue; |
753 |
|
754 |
if (!wpa && |
755 |
!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && |
756 |
!(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && |
757 |
!(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { |
758 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network " |
759 |
"not allowed"); |
760 |
continue; |
761 |
} |
762 |
|
763 |
if (!wpa_supplicant_match_privacy(bss, ssid)) { |
764 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy " |
765 |
"mismatch"); |
766 |
continue; |
767 |
} |
768 |
|
769 |
if (bss->caps & IEEE80211_CAP_IBSS) { |
770 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - IBSS (adhoc) " |
771 |
"network"); |
772 |
continue; |
773 |
} |
774 |
|
775 |
if (!freq_allowed(ssid->freq_list, bss->freq)) { |
776 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not " |
777 |
"allowed"); |
778 |
continue; |
779 |
} |
780 |
|
781 |
if (!rate_match(wpa_s, bss)) { |
782 |
wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do " |
783 |
"not match"); |
784 |
continue; |
785 |
} |
786 |
|
787 |
#ifdef CONFIG_P2P |
788 |
/* |
789 |
* TODO: skip the AP if its P2P IE has Group Formation |
790 |
* bit set in the P2P Group Capability Bitmap and we |
791 |
* are not in Group Formation with that device. |
792 |
*/ |
793 |
#endif /* CONFIG_P2P */ |
794 |
|
795 |
/* Matching configuration found */ |
796 |
return ssid; |
797 |
} |
798 |
|
799 |
/* No matching configuration found */ |
800 |
return NULL; |
801 |
} |
802 |
|
803 |
|
804 |
static struct wpa_bss * |
805 |
wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, |
806 |
struct wpa_ssid *group, |
807 |
struct wpa_ssid **selected_ssid) |
808 |
{ |
809 |
unsigned int i; |
810 |
|
811 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d", |
812 |
group->priority); |
813 |
|
814 |
for (i = 0; i < wpa_s->last_scan_res_used; i++) { |
815 |
struct wpa_bss *bss = wpa_s->last_scan_res[i]; |
816 |
*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group); |
817 |
if (!*selected_ssid) |
818 |
continue; |
819 |
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR |
820 |
" ssid='%s'", |
821 |
MAC2STR(bss->bssid), |
822 |
wpa_ssid_txt(bss->ssid, bss->ssid_len)); |
823 |
return bss; |
824 |
} |
825 |
|
826 |
return NULL; |
827 |
} |
828 |
|
829 |
|
830 |
static struct wpa_bss * |
831 |
wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, |
832 |
struct wpa_ssid **selected_ssid) |
833 |
{ |
834 |
struct wpa_bss *selected = NULL; |
835 |
int prio; |
836 |
|
837 |
if (wpa_s->last_scan_res == NULL || |
838 |
wpa_s->last_scan_res_used == 0) |
839 |
return NULL; /* no scan results from last update */ |
840 |
|
841 |
while (selected == NULL) { |
842 |
for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { |
843 |
selected = wpa_supplicant_select_bss( |
844 |
wpa_s, wpa_s->conf->pssid[prio], |
845 |
selected_ssid); |
846 |
if (selected) |
847 |
break; |
848 |
} |
849 |
|
850 |
if (selected == NULL && wpa_s->blacklist && |
851 |
!wpa_s->countermeasures) { |
852 |
wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear " |
853 |
"blacklist and try again"); |
854 |
wpa_blacklist_clear(wpa_s); |
855 |
wpa_s->blacklist_cleared++; |
856 |
} else if (selected == NULL) |
857 |
break; |
858 |
} |
859 |
|
860 |
return selected; |
861 |
} |
862 |
|
863 |
|
864 |
static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, |
865 |
int timeout_sec, int timeout_usec) |
866 |
{ |
867 |
if (!wpa_supplicant_enabled_networks(wpa_s)) { |
868 |
/* |
869 |
* No networks are enabled; short-circuit request so |
870 |
* we don't wait timeout seconds before transitioning |
871 |
* to INACTIVE state. |
872 |
*/ |
873 |
wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request " |
874 |
"since there are no enabled networks"); |
875 |
wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); |
876 |
#ifdef CONFIG_P2P |
877 |
wpa_s->sta_scan_pending = 0; |
878 |
#endif /* CONFIG_P2P */ |
879 |
return; |
880 |
} |
881 |
|
882 |
wpa_s->scan_for_connection = 1; |
883 |
wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec); |
884 |
} |
885 |
|
886 |
|
887 |
int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, |
888 |
struct wpa_bss *selected, |
889 |
struct wpa_ssid *ssid) |
890 |
{ |
891 |
if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { |
892 |
wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP |
893 |
"PBC session overlap"); |
894 |
#ifdef CONFIG_P2P |
895 |
if (wpas_p2p_notif_pbc_overlap(wpa_s) == 1) |
896 |
return -1; |
897 |
#endif /* CONFIG_P2P */ |
898 |
|
899 |
#ifdef CONFIG_WPS |
900 |
wpas_wps_cancel(wpa_s); |
901 |
#endif /* CONFIG_WPS */ |
902 |
return -1; |
903 |
} |
904 |
|
905 |
/* |
906 |
* Do not trigger new association unless the BSSID has changed or if |
907 |
* reassociation is requested. If we are in process of associating with |
908 |
* the selected BSSID, do not trigger new attempt. |
909 |
*/ |
910 |
if (wpa_s->reassociate || |
911 |
(os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && |
912 |
((wpa_s->wpa_state != WPA_ASSOCIATING && |
913 |
wpa_s->wpa_state != WPA_AUTHENTICATING) || |
914 |
os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) != |
915 |
0))) { |
916 |
if (wpa_supplicant_scard_init(wpa_s, ssid)) { |
917 |
wpa_supplicant_req_new_scan(wpa_s, 10, 0); |
918 |
return 0; |
919 |
} |
920 |
wpa_msg(wpa_s, MSG_DEBUG, "Request association: " |
921 |
"reassociate: %d selected: "MACSTR " bssid: " MACSTR |
922 |
" pending: " MACSTR " wpa_state: %s", |
923 |
wpa_s->reassociate, MAC2STR(selected->bssid), |
924 |
MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), |
925 |
wpa_supplicant_state_txt(wpa_s->wpa_state)); |
926 |
wpa_supplicant_associate(wpa_s, selected, ssid); |
927 |
} else { |
928 |
wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with the " |
929 |
"selected AP"); |
930 |
} |
931 |
|
932 |
return 0; |
933 |
} |
934 |
|
935 |
|
936 |
static struct wpa_ssid * |
937 |
wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) |
938 |
{ |
939 |
int prio; |
940 |
struct wpa_ssid *ssid; |
941 |
|
942 |
for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { |
943 |
for (ssid = wpa_s->conf->pssid[prio]; ssid; ssid = ssid->pnext) |
944 |
{ |
945 |
if (wpas_network_disabled(wpa_s, ssid)) |
946 |
continue; |
947 |
if (ssid->mode == IEEE80211_MODE_IBSS || |
948 |
ssid->mode == IEEE80211_MODE_AP) |
949 |
return ssid; |
950 |
} |
951 |
} |
952 |
return NULL; |
953 |
} |
954 |
|
955 |
|
956 |
/* TODO: move the rsn_preauth_scan_result*() to be called from notify.c based |
957 |
* on BSS added and BSS changed events */ |
958 |
static void wpa_supplicant_rsn_preauth_scan_results( |
959 |
struct wpa_supplicant *wpa_s) |
960 |
{ |
961 |
struct wpa_bss *bss; |
962 |
|
963 |
if (rsn_preauth_scan_results(wpa_s->wpa) < 0) |
964 |
return; |
965 |
|
966 |
dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { |
967 |
const u8 *ssid, *rsn; |
968 |
|
969 |
ssid = wpa_bss_get_ie(bss, WLAN_EID_SSID); |
970 |
if (ssid == NULL) |
971 |
continue; |
972 |
|
973 |
rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); |
974 |
if (rsn == NULL) |
975 |
continue; |
976 |
|
977 |
rsn_preauth_scan_result(wpa_s->wpa, bss->bssid, ssid, rsn); |
978 |
} |
979 |
|
980 |
} |
981 |
|
982 |
|
983 |
static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, |
984 |
struct wpa_bss *selected, |
985 |
struct wpa_ssid *ssid) |
986 |
{ |
987 |
struct wpa_bss *current_bss = NULL; |
988 |
int min_diff; |
989 |
|
990 |
if (wpa_s->reassociate) |
991 |
return 1; /* explicit request to reassociate */ |
992 |
if (wpa_s->wpa_state < WPA_ASSOCIATED) |
993 |
return 1; /* we are not associated; continue */ |
994 |
if (wpa_s->current_ssid == NULL) |
995 |
return 1; /* unknown current SSID */ |
996 |
if (wpa_s->current_ssid != ssid) |
997 |
return 1; /* different network block */ |
998 |
|
999 |
if (wpas_driver_bss_selection(wpa_s)) |
1000 |
return 0; /* Driver-based roaming */ |
1001 |
|
1002 |
if (wpa_s->current_ssid->ssid) |
1003 |
current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, |
1004 |
wpa_s->current_ssid->ssid, |
1005 |
wpa_s->current_ssid->ssid_len); |
1006 |
if (!current_bss) |
1007 |
current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); |
1008 |
|
1009 |
if (!current_bss) |
1010 |
return 1; /* current BSS not seen in scan results */ |
1011 |
|
1012 |
if (current_bss == selected) |
1013 |
return 0; |
1014 |
|
1015 |
if (selected->last_update_idx > current_bss->last_update_idx) |
1016 |
return 1; /* current BSS not seen in the last scan */ |
1017 |
|
1018 |
#ifndef CONFIG_NO_ROAMING |
1019 |
wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); |
1020 |
wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR " level=%d", |
1021 |
MAC2STR(current_bss->bssid), current_bss->level); |
1022 |
wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR " level=%d", |
1023 |
MAC2STR(selected->bssid), selected->level); |
1024 |
|
1025 |
if (wpa_s->current_ssid->bssid_set && |
1026 |
os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) == |
1027 |
0) { |
1028 |
wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS " |
1029 |
"has preferred BSSID"); |
1030 |
return 1; |
1031 |
} |
1032 |
|
1033 |
if (current_bss->level < 0 && current_bss->level > selected->level) { |
1034 |
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better " |
1035 |
"signal level"); |
1036 |
return 0; |
1037 |
} |
1038 |
|
1039 |
min_diff = 2; |
1040 |
if (current_bss->level < 0) { |
1041 |
if (current_bss->level < -85) |
1042 |
min_diff = 1; |
1043 |
else if (current_bss->level < -80) |
1044 |
min_diff = 2; |
1045 |
else if (current_bss->level < -75) |
1046 |
min_diff = 3; |
1047 |
else if (current_bss->level < -70) |
1048 |
min_diff = 4; |
1049 |
else |
1050 |
min_diff = 5; |
1051 |
} |
1052 |
if (abs(current_bss->level - selected->level) < min_diff) { |
1053 |
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference " |
1054 |
"in signal level"); |
1055 |
return 0; |
1056 |
} |
1057 |
|
1058 |
return 1; |
1059 |
#else /* CONFIG_NO_ROAMING */ |
1060 |
return 0; |
1061 |
#endif /* CONFIG_NO_ROAMING */ |
1062 |
} |
1063 |
|
1064 |
|
1065 |
/* Return != 0 if no scan results could be fetched or if scan results should not |
1066 |
* be shared with other virtual interfaces. */ |
1067 |
static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, |
1068 |
union wpa_event_data *data) |
1069 |
{ |
1070 |
struct wpa_scan_results *scan_res; |
1071 |
int ap = 0; |
1072 |
#ifndef CONFIG_NO_RANDOM_POOL |
1073 |
size_t i, num; |
1074 |
#endif /* CONFIG_NO_RANDOM_POOL */ |
1075 |
|
1076 |
#ifdef CONFIG_AP |
1077 |
if (wpa_s->ap_iface) |
1078 |
ap = 1; |
1079 |
#endif /* CONFIG_AP */ |
1080 |
|
1081 |
wpa_supplicant_notify_scanning(wpa_s, 0); |
1082 |
|
1083 |
#ifdef CONFIG_P2P |
1084 |
if (wpa_s->global->p2p_cb_on_scan_complete && |
1085 |
!wpa_s->global->p2p_disabled && |
1086 |
wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending && |
1087 |
!wpa_s->scan_res_handler) { |
1088 |
wpa_s->global->p2p_cb_on_scan_complete = 0; |
1089 |
if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { |
1090 |
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " |
1091 |
"stopped scan processing"); |
1092 |
wpa_s->sta_scan_pending = 1; |
1093 |
wpa_supplicant_req_scan(wpa_s, 5, 0); |
1094 |
return -1; |
1095 |
} |
1096 |
} |
1097 |
wpa_s->sta_scan_pending = 0; |
1098 |
#endif /* CONFIG_P2P */ |
1099 |
|
1100 |
scan_res = wpa_supplicant_get_scan_results(wpa_s, |
1101 |
data ? &data->scan_info : |
1102 |
NULL, 1); |
1103 |
if (scan_res == NULL) { |
1104 |
if (wpa_s->conf->ap_scan == 2 || ap) |
1105 |
return -1; |
1106 |
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try " |
1107 |
"scanning again"); |
1108 |
wpa_supplicant_req_new_scan(wpa_s, 1, 0); |
1109 |
return -1; |
1110 |
} |
1111 |
|
1112 |
#ifndef CONFIG_NO_RANDOM_POOL |
1113 |
num = scan_res->num; |
1114 |
if (num > 10) |
1115 |
num = 10; |
1116 |
for (i = 0; i < num; i++) { |
1117 |
u8 buf[5]; |
1118 |
struct wpa_scan_res *res = scan_res->res[i]; |
1119 |
buf[0] = res->bssid[5]; |
1120 |
buf[1] = res->qual & 0xff; |
1121 |
buf[2] = res->noise & 0xff; |
1122 |
buf[3] = res->level & 0xff; |
1123 |
buf[4] = res->tsf & 0xff; |
1124 |
random_add_randomness(buf, sizeof(buf)); |
1125 |
} |
1126 |
#endif /* CONFIG_NO_RANDOM_POOL */ |
1127 |
|
1128 |
if (wpa_s->scan_res_handler) { |
1129 |
void (*scan_res_handler)(struct wpa_supplicant *wpa_s, |
1130 |
struct wpa_scan_results *scan_res); |
1131 |
|
1132 |
scan_res_handler = wpa_s->scan_res_handler; |
1133 |
wpa_s->scan_res_handler = NULL; |
1134 |
scan_res_handler(wpa_s, scan_res); |
1135 |
|
1136 |
wpa_scan_results_free(scan_res); |
1137 |
return -2; |
1138 |
} |
1139 |
|
1140 |
if (ap) { |
1141 |
wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); |
1142 |
#ifdef CONFIG_AP |
1143 |
if (wpa_s->ap_iface->scan_cb) |
1144 |
wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); |
1145 |
#endif /* CONFIG_AP */ |
1146 |
wpa_scan_results_free(scan_res); |
1147 |
return 0; |
1148 |
} |
1149 |
|
1150 |
wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available"); |
1151 |
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); |
1152 |
wpas_notify_scan_results(wpa_s); |
1153 |
|
1154 |
wpas_notify_scan_done(wpa_s, 1); |
1155 |
|
1156 |
if (sme_proc_obss_scan(wpa_s) > 0) { |
1157 |
wpa_scan_results_free(scan_res); |
1158 |
return 0; |
1159 |
} |
1160 |
|
1161 |
if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) { |
1162 |
wpa_scan_results_free(scan_res); |
1163 |
return 0; |
1164 |
} |
1165 |
|
1166 |
if (autoscan_notify_scan(wpa_s, scan_res)) { |
1167 |
wpa_scan_results_free(scan_res); |
1168 |
return 0; |
1169 |
} |
1170 |
|
1171 |
if (wpa_s->disconnected) { |
1172 |
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); |
1173 |
wpa_scan_results_free(scan_res); |
1174 |
return 0; |
1175 |
} |
1176 |
|
1177 |
if (!wpas_driver_bss_selection(wpa_s) && |
1178 |
bgscan_notify_scan(wpa_s, scan_res) == 1) { |
1179 |
wpa_scan_results_free(scan_res); |
1180 |
return 0; |
1181 |
} |
1182 |
|
1183 |
wpas_wps_update_ap_info(wpa_s, scan_res); |
1184 |
|
1185 |
wpa_scan_results_free(scan_res); |
1186 |
|
1187 |
return wpas_select_network_from_last_scan(wpa_s); |
1188 |
} |
1189 |
|
1190 |
|
1191 |
int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s) |
1192 |
{ |
1193 |
struct wpa_bss *selected; |
1194 |
struct wpa_ssid *ssid = NULL; |
1195 |
|
1196 |
selected = wpa_supplicant_pick_network(wpa_s, &ssid); |
1197 |
|
1198 |
if (selected) { |
1199 |
int skip; |
1200 |
skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid); |
1201 |
if (skip) { |
1202 |
wpa_supplicant_rsn_preauth_scan_results(wpa_s); |
1203 |
return 0; |
1204 |
} |
1205 |
|
1206 |
if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) { |
1207 |
wpa_dbg(wpa_s, MSG_DEBUG, "Connect failed"); |
1208 |
return -1; |
1209 |
} |
1210 |
wpa_supplicant_rsn_preauth_scan_results(wpa_s); |
1211 |
/* |
1212 |
* Do not notify other virtual radios of scan results since we do not |
1213 |
* want them to start other associations at the same time. |
1214 |
*/ |
1215 |
return 1; |
1216 |
} else { |
1217 |
wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found"); |
1218 |
ssid = wpa_supplicant_pick_new_network(wpa_s); |
1219 |
if (ssid) { |
1220 |
wpa_dbg(wpa_s, MSG_DEBUG, "Setup a new network"); |
1221 |
wpa_supplicant_associate(wpa_s, NULL, ssid); |
1222 |
wpa_supplicant_rsn_preauth_scan_results(wpa_s); |
1223 |
} else { |
1224 |
int timeout_sec = wpa_s->scan_interval; |
1225 |
int timeout_usec = 0; |
1226 |
#ifdef CONFIG_P2P |
1227 |
if (wpas_p2p_scan_no_go_seen(wpa_s) == 1) |
1228 |
return 0; |
1229 |
|
1230 |
if (wpa_s->p2p_in_provisioning) { |
1231 |
/* |
1232 |
* Use shorter wait during P2P Provisioning |
1233 |
* state to speed up group formation. |
1234 |
*/ |
1235 |
timeout_sec = 0; |
1236 |
timeout_usec = 250000; |
1237 |
wpa_supplicant_req_new_scan(wpa_s, timeout_sec, |
1238 |
timeout_usec); |
1239 |
return 0; |
1240 |
} |
1241 |
#endif /* CONFIG_P2P */ |
1242 |
#ifdef CONFIG_INTERWORKING |
1243 |
if (wpa_s->conf->auto_interworking && |
1244 |
wpa_s->conf->interworking && |
1245 |
wpa_s->conf->cred) { |
1246 |
wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: " |
1247 |
"start ANQP fetch since no matching " |
1248 |
"networks found"); |
1249 |
wpa_s->network_select = 1; |
1250 |
wpa_s->auto_network_select = 1; |
1251 |
interworking_start_fetch_anqp(wpa_s); |
1252 |
return 1; |
1253 |
} |
1254 |
#endif /* CONFIG_INTERWORKING */ |
1255 |
if (wpa_supplicant_req_sched_scan(wpa_s)) |
1256 |
wpa_supplicant_req_new_scan(wpa_s, timeout_sec, |
1257 |
timeout_usec); |
1258 |
} |
1259 |
} |
1260 |
return 0; |
1261 |
} |
1262 |
|
1263 |
|
1264 |
static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, |
1265 |
union wpa_event_data *data) |
1266 |
{ |
1267 |
const char *rn, *rn2; |
1268 |
struct wpa_supplicant *ifs; |
1269 |
|
1270 |
if (_wpa_supplicant_event_scan_results(wpa_s, data) != 0) { |
1271 |
/* |
1272 |
* If no scan results could be fetched, then no need to |
1273 |
* notify those interfaces that did not actually request |
1274 |
* this scan. Similarly, if scan results started a new operation on this |
1275 |
* interface, do not notify other interfaces to avoid concurrent |
1276 |
* operations during a connection attempt. |
1277 |
*/ |
1278 |
return; |
1279 |
} |
1280 |
|
1281 |
/* |
1282 |
* Check other interfaces to see if they have the same radio-name. If |
1283 |
* so, they get updated with this same scan info. |
1284 |
*/ |
1285 |
if (!wpa_s->driver->get_radio_name) |
1286 |
return; |
1287 |
|
1288 |
rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv); |
1289 |
if (rn == NULL || rn[0] == '\0') |
1290 |
return; |
1291 |
|
1292 |
wpa_dbg(wpa_s, MSG_DEBUG, "Checking for other virtual interfaces " |
1293 |
"sharing same radio (%s) in event_scan_results", rn); |
1294 |
|
1295 |
for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) { |
1296 |
if (ifs == wpa_s || !ifs->driver->get_radio_name) |
1297 |
continue; |
1298 |
|
1299 |
rn2 = ifs->driver->get_radio_name(ifs->drv_priv); |
1300 |
if (rn2 && os_strcmp(rn, rn2) == 0) { |
1301 |
wpa_printf(MSG_DEBUG, "%s: Updating scan results from " |
1302 |
"sibling", ifs->ifname); |
1303 |
_wpa_supplicant_event_scan_results(ifs, data); |
1304 |
} |
1305 |
} |
1306 |
} |
1307 |
|
1308 |
#endif /* CONFIG_NO_SCAN_PROCESSING */ |
1309 |
|
1310 |
|
1311 |
#ifdef CONFIG_WNM |
1312 |
|
1313 |
static void wnm_bss_keep_alive(void *eloop_ctx, void *sock_ctx) |
1314 |
{ |
1315 |
struct wpa_supplicant *wpa_s = eloop_ctx; |
1316 |
|
1317 |
if (wpa_s->wpa_state < WPA_ASSOCIATED) |
1318 |
return; |
1319 |
|
1320 |
if (!wpa_s->no_keep_alive) { |
1321 |
wpa_printf(MSG_DEBUG, "WNM: Send keep-alive to AP " MACSTR, |
1322 |
MAC2STR(wpa_s->bssid)); |
1323 |
/* TODO: could skip this if normal data traffic has been sent */ |
1324 |
/* TODO: Consider using some more appropriate data frame for |
1325 |
* this */ |
1326 |
if (wpa_s->l2) |
1327 |
l2_packet_send(wpa_s->l2, wpa_s->bssid, 0x0800, |
1328 |
(u8 *) "", 0); |
1329 |
} |
1330 |
|
1331 |
#ifdef CONFIG_SME |
1332 |
if (wpa_s->sme.bss_max_idle_period) { |
1333 |
unsigned int msec; |
1334 |
msec = wpa_s->sme.bss_max_idle_period * 1024; /* times 1000 */ |
1335 |
if (msec > 100) |
1336 |
msec -= 100; |
1337 |
eloop_register_timeout(msec / 1000, msec % 1000 * 1000, |
1338 |
wnm_bss_keep_alive, wpa_s, NULL); |
1339 |
} |
1340 |
#endif /* CONFIG_SME */ |
1341 |
} |
1342 |
|
1343 |
|
1344 |
static void wnm_process_assoc_resp(struct wpa_supplicant *wpa_s, |
1345 |
const u8 *ies, size_t ies_len) |
1346 |
{ |
1347 |
struct ieee802_11_elems elems; |
1348 |
|
1349 |
if (ies == NULL) |
1350 |
return; |
1351 |
|
1352 |
if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) |
1353 |
return; |
1354 |
|
1355 |
#ifdef CONFIG_SME |
1356 |
if (elems.bss_max_idle_period) { |
1357 |
unsigned int msec; |
1358 |
wpa_s->sme.bss_max_idle_period = |
1359 |
WPA_GET_LE16(elems.bss_max_idle_period); |
1360 |
wpa_printf(MSG_DEBUG, "WNM: BSS Max Idle Period: %u (* 1000 " |
1361 |
"TU)%s", wpa_s->sme.bss_max_idle_period, |
1362 |
(elems.bss_max_idle_period[2] & 0x01) ? |
1363 |
" (protected keep-live required)" : ""); |
1364 |
if (wpa_s->sme.bss_max_idle_period == 0) |
1365 |
wpa_s->sme.bss_max_idle_period = 1; |
1366 |
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) { |
1367 |
eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL); |
1368 |
/* msec times 1000 */ |
1369 |
msec = wpa_s->sme.bss_max_idle_period * 1024; |
1370 |
if (msec > 100) |
1371 |
msec -= 100; |
1372 |
eloop_register_timeout(msec / 1000, msec % 1000 * 1000, |
1373 |
wnm_bss_keep_alive, wpa_s, |
1374 |
NULL); |
1375 |
} |
1376 |
} |
1377 |
#endif /* CONFIG_SME */ |
1378 |
} |
1379 |
|
1380 |
#endif /* CONFIG_WNM */ |
1381 |
|
1382 |
|
1383 |
void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s) |
1384 |
{ |
1385 |
#ifdef CONFIG_WNM |
1386 |
eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL); |
1387 |
#endif /* CONFIG_WNM */ |
1388 |
} |
1389 |
|
1390 |
|
1391 |
static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, |
1392 |
union wpa_event_data *data) |
1393 |
{ |
1394 |
int l, len, found = 0, wpa_found, rsn_found; |
1395 |
const u8 *p; |
1396 |
|
1397 |
wpa_dbg(wpa_s, MSG_DEBUG, "Association info event"); |
1398 |
if (data->assoc_info.req_ies) |
1399 |
wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, |
1400 |
data->assoc_info.req_ies_len); |
1401 |
if (data->assoc_info.resp_ies) { |
1402 |
wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies, |
1403 |
data->assoc_info.resp_ies_len); |
1404 |
#ifdef CONFIG_TDLS |
1405 |
wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies, |
1406 |
data->assoc_info.resp_ies_len); |
1407 |
#endif /* CONFIG_TDLS */ |
1408 |
#ifdef CONFIG_WNM |
1409 |
wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, |
1410 |
data->assoc_info.resp_ies_len); |
1411 |
#endif /* CONFIG_WNM */ |
1412 |
} |
1413 |
if (data->assoc_info.beacon_ies) |
1414 |
wpa_hexdump(MSG_DEBUG, "beacon_ies", |
1415 |
data->assoc_info.beacon_ies, |
1416 |
data->assoc_info.beacon_ies_len); |
1417 |
if (data->assoc_info.freq) |
1418 |
wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz", |
1419 |
data->assoc_info.freq); |
1420 |
|
1421 |
p = data->assoc_info.req_ies; |
1422 |
l = data->assoc_info.req_ies_len; |
1423 |
|
1424 |
/* Go through the IEs and make a copy of the WPA/RSN IE, if present. */ |
1425 |
while (p && l >= 2) { |
1426 |
len = p[1] + 2; |
1427 |
if (len > l) { |
1428 |
wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", |
1429 |
p, l); |
1430 |
break; |
1431 |
} |
1432 |
if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 && |
1433 |
(os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) || |
1434 |
(p[0] == WLAN_EID_RSN && p[1] >= 2)) { |
1435 |
if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len)) |
1436 |
break; |
1437 |
found = 1; |
1438 |
wpa_find_assoc_pmkid(wpa_s); |
1439 |
break; |
1440 |
} |
1441 |
l -= len; |
1442 |
p += len; |
1443 |
} |
1444 |
if (!found && data->assoc_info.req_ies) |
1445 |
wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); |
1446 |
|
1447 |
#ifdef CONFIG_IEEE80211R |
1448 |
#ifdef CONFIG_SME |
1449 |
if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) { |
1450 |
u8 bssid[ETH_ALEN]; |
1451 |
if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || |
1452 |
wpa_ft_validate_reassoc_resp(wpa_s->wpa, |
1453 |
data->assoc_info.resp_ies, |
1454 |
data->assoc_info.resp_ies_len, |
1455 |
bssid) < 0) { |
1456 |
wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of " |
1457 |
"Reassociation Response failed"); |
1458 |
wpa_supplicant_deauthenticate( |
1459 |
wpa_s, WLAN_REASON_INVALID_IE); |
1460 |
return -1; |
1461 |
} |
1462 |
} |
1463 |
|
1464 |
p = data->assoc_info.resp_ies; |
1465 |
l = data->assoc_info.resp_ies_len; |
1466 |
|
1467 |
#ifdef CONFIG_WPS_STRICT |
1468 |
if (p && wpa_s->current_ssid && |
1469 |
wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_WPS) { |
1470 |
struct wpabuf *wps; |
1471 |
wps = ieee802_11_vendor_ie_concat(p, l, WPS_IE_VENDOR_TYPE); |
1472 |
if (wps == NULL) { |
1473 |
wpa_msg(wpa_s, MSG_INFO, "WPS-STRICT: AP did not " |
1474 |
"include WPS IE in (Re)Association Response"); |
1475 |
return -1; |
1476 |
} |
1477 |
|
1478 |
if (wps_validate_assoc_resp(wps) < 0) { |
1479 |
wpabuf_free(wps); |
1480 |
wpa_supplicant_deauthenticate( |
1481 |
wpa_s, WLAN_REASON_INVALID_IE); |
1482 |
return -1; |
1483 |
} |
1484 |
wpabuf_free(wps); |
1485 |
} |
1486 |
#endif /* CONFIG_WPS_STRICT */ |
1487 |
|
1488 |
/* Go through the IEs and make a copy of the MDIE, if present. */ |
1489 |
while (p && l >= 2) { |
1490 |
len = p[1] + 2; |
1491 |
if (len > l) { |
1492 |
wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", |
1493 |
p, l); |
1494 |
break; |
1495 |
} |
1496 |
if (p[0] == WLAN_EID_MOBILITY_DOMAIN && |
1497 |
p[1] >= MOBILITY_DOMAIN_ID_LEN) { |
1498 |
wpa_s->sme.ft_used = 1; |
1499 |
os_memcpy(wpa_s->sme.mobility_domain, p + 2, |
1500 |
MOBILITY_DOMAIN_ID_LEN); |
1501 |
break; |
1502 |
} |
1503 |
l -= len; |
1504 |
p += len; |
1505 |
} |
1506 |
#endif /* CONFIG_SME */ |
1507 |
|
1508 |
wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies, |
1509 |
data->assoc_info.resp_ies_len); |
1510 |
#endif /* CONFIG_IEEE80211R */ |
1511 |
|
1512 |
/* WPA/RSN IE from Beacon/ProbeResp */ |
1513 |
p = data->assoc_info.beacon_ies; |
1514 |
l = data->assoc_info.beacon_ies_len; |
1515 |
|
1516 |
/* Go through the IEs and make a copy of the WPA/RSN IEs, if present. |
1517 |
*/ |
1518 |
wpa_found = rsn_found = 0; |
1519 |
while (p && l >= 2) { |
1520 |
len = p[1] + 2; |
1521 |
if (len > l) { |
1522 |
wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies", |
1523 |
p, l); |
1524 |
break; |
1525 |
} |
1526 |
if (!wpa_found && |
1527 |
p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 && |
1528 |
os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) { |
1529 |
wpa_found = 1; |
1530 |
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len); |
1531 |
} |
1532 |
|
1533 |
if (!rsn_found && |
1534 |
p[0] == WLAN_EID_RSN && p[1] >= 2) { |
1535 |
rsn_found = 1; |
1536 |
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len); |
1537 |
} |
1538 |
|
1539 |
l -= len; |
1540 |
p += len; |
1541 |
} |
1542 |
|
1543 |
if (!wpa_found && data->assoc_info.beacon_ies) |
1544 |
wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); |
1545 |
if (!rsn_found && data->assoc_info.beacon_ies) |
1546 |
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); |
1547 |
if (wpa_found || rsn_found) |
1548 |
wpa_s->ap_ies_from_associnfo = 1; |
1549 |
|
1550 |
if (wpa_s->assoc_freq && data->assoc_info.freq && |
1551 |
wpa_s->assoc_freq != data->assoc_info.freq) { |
1552 |
wpa_printf(MSG_DEBUG, "Operating frequency changed from " |
1553 |
"%u to %u MHz", |
1554 |
wpa_s->assoc_freq, data->assoc_info.freq); |
1555 |
wpa_supplicant_update_scan_results(wpa_s); |
1556 |
} |
1557 |
|
1558 |
wpa_s->assoc_freq = data->assoc_info.freq; |
1559 |
|
1560 |
return 0; |
1561 |
} |
1562 |
|
1563 |
|
1564 |
static struct wpa_bss * wpa_supplicant_get_new_bss( |
1565 |
struct wpa_supplicant *wpa_s, const u8 *bssid) |
1566 |
{ |
1567 |
struct wpa_bss *bss = NULL; |
1568 |
struct wpa_ssid *ssid = wpa_s->current_ssid; |
1569 |
|
1570 |
if (ssid->ssid_len > 0) |
1571 |
bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); |
1572 |
if (!bss) |
1573 |
bss = wpa_bss_get_bssid(wpa_s, bssid); |
1574 |
|
1575 |
return bss; |
1576 |
} |
1577 |
|
1578 |
|
1579 |
static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s) |
1580 |
{ |
1581 |
const u8 *bss_wpa = NULL, *bss_rsn = NULL; |
1582 |
|
1583 |
if (!wpa_s->current_bss || !wpa_s->current_ssid) |
1584 |
return -1; |
1585 |
|
1586 |
if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt)) |
1587 |
return 0; |
1588 |
|
1589 |
bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss, |
1590 |
WPA_IE_VENDOR_TYPE); |
1591 |
bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN); |
1592 |
|
1593 |
if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa, |
1594 |
bss_wpa ? 2 + bss_wpa[1] : 0) || |
1595 |
wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn, |
1596 |
bss_rsn ? 2 + bss_rsn[1] : 0)) |
1597 |
return -1; |
1598 |
|
1599 |
return 0; |
1600 |
} |
1601 |
|
1602 |
|
1603 |
static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, |
1604 |
union wpa_event_data *data) |
1605 |
{ |
1606 |
u8 bssid[ETH_ALEN]; |
1607 |
int ft_completed; |
1608 |
struct wpa_driver_capa capa; |
1609 |
|
1610 |
#ifdef CONFIG_AP |
1611 |
if (wpa_s->ap_iface) { |
1612 |
hostapd_notif_assoc(wpa_s->ap_iface->bss[0], |
1613 |
data->assoc_info.addr, |
1614 |
data->assoc_info.req_ies, |
1615 |
data->assoc_info.req_ies_len, |
1616 |
data->assoc_info.reassoc); |
1617 |
return; |
1618 |
} |
1619 |
#endif /* CONFIG_AP */ |
1620 |
|
1621 |
ft_completed = wpa_ft_is_completed(wpa_s->wpa); |
1622 |
if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) |
1623 |
return; |
1624 |
|
1625 |
if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { |
1626 |
wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID"); |
1627 |
wpa_supplicant_deauthenticate( |
1628 |
wpa_s, WLAN_REASON_DEAUTH_LEAVING); |
1629 |
return; |
1630 |
} |
1631 |
|
1632 |
wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); |
1633 |
if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { |
1634 |
wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" |
1635 |
MACSTR, MAC2STR(bssid)); |
1636 |
random_add_randomness(bssid, ETH_ALEN); |
1637 |
os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); |
1638 |
os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); |
1639 |
wpas_notify_bssid_changed(wpa_s); |
1640 |
|
1641 |
if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) { |
1642 |
wpa_clear_keys(wpa_s, bssid); |
1643 |
} |
1644 |
if (wpa_supplicant_select_config(wpa_s) < 0) { |
1645 |
wpa_supplicant_deauthenticate( |
1646 |
wpa_s, WLAN_REASON_DEAUTH_LEAVING); |
1647 |
return; |
1648 |
} |
1649 |
if (wpa_s->current_ssid) { |
1650 |
struct wpa_bss *bss = NULL; |
1651 |
|
1652 |
bss = wpa_supplicant_get_new_bss(wpa_s, bssid); |
1653 |
if (!bss) { |
1654 |
wpa_supplicant_update_scan_results(wpa_s); |
1655 |
|
1656 |
/* Get the BSS from the new scan results */ |
1657 |
bss = wpa_supplicant_get_new_bss(wpa_s, bssid); |
1658 |
} |
1659 |
|
1660 |
if (bss) |
1661 |
wpa_s->current_bss = bss; |
1662 |
} |
1663 |
|
1664 |
if (wpa_s->conf->ap_scan == 1 && |
1665 |
wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) { |
1666 |
if (wpa_supplicant_assoc_update_ie(wpa_s) < 0) |
1667 |
wpa_msg(wpa_s, MSG_WARNING, |
1668 |
"WPA/RSN IEs not updated"); |
1669 |
} |
1670 |
} |
1671 |
|
1672 |
#ifdef CONFIG_SME |
1673 |
os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN); |
1674 |
wpa_s->sme.prev_bssid_set = 1; |
1675 |
#endif /* CONFIG_SME */ |
1676 |
|
1677 |
wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); |
1678 |
if (wpa_s->current_ssid) { |
1679 |
/* When using scanning (ap_scan=1), SIM PC/SC interface can be |
1680 |
* initialized before association, but for other modes, |
1681 |
* initialize PC/SC here, if the current configuration needs |
1682 |
* smartcard or SIM/USIM. */ |
1683 |
wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); |
1684 |
} |
1685 |
wpa_sm_notify_assoc(wpa_s->wpa, bssid); |
1686 |
if (wpa_s->l2) |
1687 |
l2_packet_notify_auth_start(wpa_s->l2); |
1688 |
|
1689 |
/* |
1690 |
* Set portEnabled first to FALSE in order to get EAP state machine out |
1691 |
* of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE |
1692 |
* state machine may transit to AUTHENTICATING state based on obsolete |
1693 |
* eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to |
1694 |
* AUTHENTICATED without ever giving chance to EAP state machine to |
1695 |
* reset the state. |
1696 |
*/ |
1697 |
if (!ft_completed) { |
1698 |
eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); |
1699 |
eapol_sm_notify_portValid(wpa_s->eapol, FALSE); |
1700 |
} |
1701 |
if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) |
1702 |
eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); |
1703 |
/* 802.1X::portControl = Auto */ |
1704 |
eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); |
1705 |
wpa_s->eapol_received = 0; |
1706 |
if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || |
1707 |
wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE || |
1708 |
(wpa_s->current_ssid && |
1709 |
wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) { |
1710 |
wpa_supplicant_cancel_auth_timeout(wpa_s); |
1711 |
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); |
1712 |
} else if (!ft_completed) { |
1713 |
/* Timeout for receiving the first EAPOL packet */ |
1714 |
wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); |
1715 |
} |
1716 |
wpa_supplicant_cancel_scan(wpa_s); |
1717 |
|
1718 |
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && |
1719 |
wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { |
1720 |
/* |
1721 |
* We are done; the driver will take care of RSN 4-way |
1722 |
* handshake. |
1723 |
*/ |
1724 |
wpa_supplicant_cancel_auth_timeout(wpa_s); |
1725 |
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); |
1726 |
eapol_sm_notify_portValid(wpa_s->eapol, TRUE); |
1727 |
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); |
1728 |
} else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && |
1729 |
wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { |
1730 |
/* |
1731 |
* The driver will take care of RSN 4-way handshake, so we need |
1732 |
* to allow EAPOL supplicant to complete its work without |
1733 |
* waiting for WPA supplicant. |
1734 |
*/ |
1735 |
eapol_sm_notify_portValid(wpa_s->eapol, TRUE); |
1736 |
} else if (ft_completed) { |
1737 |
/* |
1738 |
* FT protocol completed - make sure EAPOL state machine ends |
1739 |
* up in authenticated. |
1740 |
*/ |
1741 |
wpa_supplicant_cancel_auth_timeout(wpa_s); |
1742 |
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); |
1743 |
eapol_sm_notify_portValid(wpa_s->eapol, TRUE); |
1744 |
eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); |
1745 |
} |
1746 |
|
1747 |
wpa_s->last_eapol_matches_bssid = 0; |
1748 |
|
1749 |
if (wpa_s->pending_eapol_rx) { |
1750 |
struct os_time now, age; |
1751 |
os_get_time(&now); |
1752 |
os_time_sub(&now, &wpa_s->pending_eapol_rx_time, &age); |
1753 |
if (age.sec == 0 && age.usec < 100000 && |
1754 |
os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == |
1755 |
0) { |
1756 |
wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL " |
1757 |
"frame that was received just before " |
1758 |
"association notification"); |
1759 |
wpa_supplicant_rx_eapol( |
1760 |
wpa_s, wpa_s->pending_eapol_rx_src, |
1761 |
wpabuf_head(wpa_s->pending_eapol_rx), |
1762 |
wpabuf_len(wpa_s->pending_eapol_rx)); |
1763 |
} |
1764 |
wpabuf_free(wpa_s->pending_eapol_rx); |
1765 |
wpa_s->pending_eapol_rx = NULL; |
1766 |
} |
1767 |
|
1768 |
if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || |
1769 |
wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) && |
1770 |
wpa_s->current_ssid && wpa_drv_get_capa(wpa_s, &capa) == 0 && |
1771 |
capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE) { |
1772 |
/* Set static WEP keys again */ |
1773 |
wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); |
1774 |
} |
1775 |
|
1776 |
#ifdef CONFIG_IBSS_RSN |
1777 |
if (wpa_s->current_ssid && |
1778 |
wpa_s->current_ssid->mode == WPAS_MODE_IBSS && |
1779 |
wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && |
1780 |
wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE && |
1781 |
wpa_s->ibss_rsn == NULL) { |
1782 |
wpa_s->ibss_rsn = ibss_rsn_init(wpa_s); |
1783 |
if (!wpa_s->ibss_rsn) { |
1784 |
wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN"); |
1785 |
wpa_supplicant_deauthenticate( |
1786 |
wpa_s, WLAN_REASON_DEAUTH_LEAVING); |
1787 |
return; |
1788 |
} |
1789 |
|
1790 |
ibss_rsn_set_psk(wpa_s->ibss_rsn, wpa_s->current_ssid->psk); |
1791 |
} |
1792 |
#endif /* CONFIG_IBSS_RSN */ |
1793 |
|
1794 |
wpas_wps_notify_assoc(wpa_s, bssid); |
1795 |
} |
1796 |
|
1797 |
|
1798 |
static int disconnect_reason_recoverable(u16 reason_code) |
1799 |
{ |
1800 |
return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY || |
1801 |
reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || |
1802 |
reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; |
1803 |
} |
1804 |
|
1805 |
|
1806 |
static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, |
1807 |
u16 reason_code, |
1808 |
int locally_generated) |
1809 |
{ |
1810 |
const u8 *bssid; |
1811 |
|
1812 |
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { |
1813 |
/* |
1814 |
* At least Host AP driver and a Prism3 card seemed to be |
1815 |
* generating streams of disconnected events when configuring |
1816 |
* IBSS for WPA-None. Ignore them for now. |
1817 |
*/ |
1818 |
return; |
1819 |
} |
1820 |
|
1821 |
bssid = wpa_s->bssid; |
1822 |
if (is_zero_ether_addr(bssid)) |
1823 |
bssid = wpa_s->pending_bssid; |
1824 |
|
1825 |
if (!is_zero_ether_addr(bssid) || |
1826 |
wpa_s->wpa_state >= WPA_AUTHENTICATING) { |
1827 |
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR |
1828 |
" reason=%d%s", |
1829 |
MAC2STR(bssid), reason_code, |
1830 |
locally_generated ? " locally_generated=1" : ""); |
1831 |
} |
1832 |
} |
1833 |
|
1834 |
|
1835 |
static int could_be_psk_mismatch(struct wpa_supplicant *wpa_s, u16 reason_code, |
1836 |
int locally_generated) |
1837 |
{ |
1838 |
if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE || |
1839 |
!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) |
1840 |
return 0; /* Not in 4-way handshake with PSK */ |
1841 |
|
1842 |
/* |
1843 |
* It looks like connection was lost while trying to go through PSK |
1844 |
* 4-way handshake. Filter out known disconnection cases that are caused |
1845 |
* by something else than PSK mismatch to avoid confusing reports. |
1846 |
*/ |
1847 |
|
1848 |
if (locally_generated) { |
1849 |
if (reason_code == WLAN_REASON_IE_IN_4WAY_DIFFERS) |
1850 |
return 0; |
1851 |
} |
1852 |
|
1853 |
return 1; |
1854 |
} |
1855 |
|
1856 |
|
1857 |
static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, |
1858 |
u16 reason_code, |
1859 |
int locally_generated) |
1860 |
{ |
1861 |
const u8 *bssid; |
1862 |
int authenticating; |
1863 |
u8 prev_pending_bssid[ETH_ALEN]; |
1864 |
struct wpa_bss *fast_reconnect = NULL; |
1865 |
struct wpa_ssid *fast_reconnect_ssid = NULL; |
1866 |
struct wpa_ssid *last_ssid; |
1867 |
|
1868 |
authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING; |
1869 |
os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN); |
1870 |
|
1871 |
if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { |
1872 |
/* |
1873 |
* At least Host AP driver and a Prism3 card seemed to be |
1874 |
* generating streams of disconnected events when configuring |
1875 |
* IBSS for WPA-None. Ignore them for now. |
1876 |
*/ |
1877 |
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - ignore in " |
1878 |
"IBSS/WPA-None mode"); |
1879 |
return; |
1880 |
} |
1881 |
|
1882 |
if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) { |
1883 |
wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " |
1884 |
"pre-shared key may be incorrect"); |
1885 |
wpas_auth_failed(wpa_s); |
1886 |
} |
1887 |
if (!wpa_s->auto_reconnect_disabled || |
1888 |
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) { |
1889 |
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to " |
1890 |
"reconnect (wps=%d wpa_state=%d)", |
1891 |
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS, |
1892 |
wpa_s->wpa_state); |
1893 |
if (wpa_s->wpa_state == WPA_COMPLETED && |
1894 |
wpa_s->current_ssid && |
1895 |
wpa_s->current_ssid->mode == WPAS_MODE_INFRA && |
1896 |
!locally_generated && |
1897 |
disconnect_reason_recoverable(reason_code)) { |
1898 |
/* |
1899 |
* It looks like the AP has dropped association with |
1900 |
* us, but could allow us to get back in. Try to |
1901 |
* reconnect to the same BSS without full scan to save |
1902 |
* time for some common cases. |
1903 |
*/ |
1904 |
fast_reconnect = wpa_s->current_bss; |
1905 |
fast_reconnect_ssid = wpa_s->current_ssid; |
1906 |
} else if (wpa_s->wpa_state >= WPA_ASSOCIATING) |
1907 |
wpa_supplicant_req_scan(wpa_s, 0, 100000); |
1908 |
else |
1909 |
wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new " |
1910 |
"immediate scan"); |
1911 |
} else { |
1912 |
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not " |
1913 |
"try to re-connect"); |
1914 |
wpa_s->reassociate = 0; |
1915 |
wpa_s->disconnected = 1; |
1916 |
wpa_supplicant_cancel_sched_scan(wpa_s); |
1917 |
} |
1918 |
bssid = wpa_s->bssid; |
1919 |
if (is_zero_ether_addr(bssid)) |
1920 |
bssid = wpa_s->pending_bssid; |
1921 |
if (wpa_s->wpa_state >= WPA_AUTHENTICATING) |
1922 |
wpas_connection_failed(wpa_s, bssid); |
1923 |
wpa_sm_notify_disassoc(wpa_s->wpa); |
1924 |
if (locally_generated) |
1925 |
wpa_s->disconnect_reason = -reason_code; |
1926 |
else |
1927 |
wpa_s->disconnect_reason = reason_code; |
1928 |
wpas_notify_disconnect_reason(wpa_s); |
1929 |
if (wpa_supplicant_dynamic_keys(wpa_s)) { |
1930 |
wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys"); |
1931 |
wpa_s->keys_cleared = 0; |
1932 |
wpa_clear_keys(wpa_s, wpa_s->bssid); |
1933 |
} |
1934 |
last_ssid = wpa_s->current_ssid; |
1935 |
wpa_supplicant_mark_disassoc(wpa_s); |
1936 |
|
1937 |
if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) { |
1938 |
sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid); |
1939 |
wpa_s->current_ssid = last_ssid; |
1940 |
} |
1941 |
|
1942 |
if (fast_reconnect) { |
1943 |
#ifndef CONFIG_NO_SCAN_PROCESSING |
1944 |
wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS"); |
1945 |
if (wpa_supplicant_connect(wpa_s, fast_reconnect, |
1946 |
fast_reconnect_ssid) < 0) { |
1947 |
/* Recover through full scan */ |
1948 |
wpa_supplicant_req_scan(wpa_s, 0, 100000); |
1949 |
} |
1950 |
#endif /* CONFIG_NO_SCAN_PROCESSING */ |
1951 |
} |
1952 |
} |
1953 |
|
1954 |
|
1955 |
#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT |
1956 |
void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx) |
1957 |
{ |
1958 |
struct wpa_supplicant *wpa_s = eloop_ctx; |
1959 |
|
1960 |
if (!wpa_s->pending_mic_error_report) |
1961 |
return; |
1962 |
|
1963 |
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Sending pending MIC error report"); |
1964 |
wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise); |
1965 |
wpa_s->pending_mic_error_report = 0; |
1966 |
} |
1967 |
#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ |
1968 |
|
1969 |
|
1970 |
static void |
1971 |
wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s, |
1972 |
union wpa_event_data *data) |
1973 |
{ |
1974 |
int pairwise; |
1975 |
struct os_time t; |
1976 |
|
1977 |
wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); |
1978 |
pairwise = (data && data->michael_mic_failure.unicast); |
1979 |
os_get_time(&t); |
1980 |
if ((wpa_s->last_michael_mic_error && |
1981 |
t.sec - wpa_s->last_michael_mic_error <= 60) || |
1982 |
wpa_s->pending_mic_error_report) { |
1983 |
if (wpa_s->pending_mic_error_report) { |
1984 |
/* |
1985 |
* Send the pending MIC error report immediately since |
1986 |
* we are going to start countermeasures and AP better |
1987 |
* do the same. |
1988 |
*/ |
1989 |
wpa_sm_key_request(wpa_s->wpa, 1, |
1990 |
wpa_s->pending_mic_error_pairwise); |
1991 |
} |
1992 |
|
1993 |
/* Send the new MIC error report immediately since we are going |
1994 |
* to start countermeasures and AP better do the same. |
1995 |
*/ |
1996 |
wpa_sm_key_request(wpa_s->wpa, 1, pairwise); |
1997 |
|
1998 |
/* initialize countermeasures */ |
1999 |
wpa_s->countermeasures = 1; |
2000 |
|
2001 |
wpa_blacklist_add(wpa_s, wpa_s->bssid); |
2002 |
|
2003 |
wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started"); |
2004 |
|
2005 |
/* |
2006 |
* Need to wait for completion of request frame. We do not get |
2007 |
* any callback for the message completion, so just wait a |
2008 |
* short while and hope for the best. */ |
2009 |
os_sleep(0, 10000); |
2010 |
|
2011 |
wpa_drv_set_countermeasures(wpa_s, 1); |
2012 |
wpa_supplicant_deauthenticate(wpa_s, |
2013 |
WLAN_REASON_MICHAEL_MIC_FAILURE); |
2014 |
eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, |
2015 |
wpa_s, NULL); |
2016 |
eloop_register_timeout(60, 0, |
2017 |
wpa_supplicant_stop_countermeasures, |
2018 |
wpa_s, NULL); |
2019 |
/* TODO: mark the AP rejected for 60 second. STA is |
2020 |
* allowed to associate with another AP.. */ |
2021 |
} else { |
2022 |
#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT |
2023 |
if (wpa_s->mic_errors_seen) { |
2024 |
/* |
2025 |
* Reduce the effectiveness of Michael MIC error |
2026 |
* reports as a means for attacking against TKIP if |
2027 |
* more than one MIC failure is noticed with the same |
2028 |
* PTK. We delay the transmission of the reports by a |
2029 |
* random time between 0 and 60 seconds in order to |
2030 |
* force the attacker wait 60 seconds before getting |
2031 |
* the information on whether a frame resulted in a MIC |
2032 |
* failure. |
2033 |
*/ |
2034 |
u8 rval[4]; |
2035 |
int sec; |
2036 |
|
2037 |
if (os_get_random(rval, sizeof(rval)) < 0) |
2038 |
sec = os_random() % 60; |
2039 |
else |
2040 |
sec = WPA_GET_BE32(rval) % 60; |
2041 |
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Delay MIC error " |
2042 |
"report %d seconds", sec); |
2043 |
wpa_s->pending_mic_error_report = 1; |
2044 |
wpa_s->pending_mic_error_pairwise = pairwise; |
2045 |
eloop_cancel_timeout( |
2046 |
wpa_supplicant_delayed_mic_error_report, |
2047 |
wpa_s, NULL); |
2048 |
eloop_register_timeout( |
2049 |
sec, os_random() % 1000000, |
2050 |
wpa_supplicant_delayed_mic_error_report, |
2051 |
wpa_s, NULL); |
2052 |
} else { |
2053 |
wpa_sm_key_request(wpa_s->wpa, 1, pairwise); |
2054 |
} |
2055 |
#else /* CONFIG_DELAYED_MIC_ERROR_REPORT */ |
2056 |
wpa_sm_key_request(wpa_s->wpa, 1, pairwise); |
2057 |
#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ |
2058 |
} |
2059 |
wpa_s->last_michael_mic_error = t.sec; |
2060 |
wpa_s->mic_errors_seen++; |
2061 |
} |
2062 |
|
2063 |
|
2064 |
#ifdef CONFIG_TERMINATE_ONLASTIF |
2065 |
static int any_interfaces(struct wpa_supplicant *head) |
2066 |
{ |
2067 |
struct wpa_supplicant *wpa_s; |
2068 |
|
2069 |
for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next) |
2070 |
if (!wpa_s->interface_removed) |
2071 |
return 1; |
2072 |
return 0; |
2073 |
} |
2074 |
#endif /* CONFIG_TERMINATE_ONLASTIF */ |
2075 |
|
2076 |
|
2077 |
static void |
2078 |
wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s, |
2079 |
union wpa_event_data *data) |
2080 |
{ |
2081 |
if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0) |
2082 |
return; |
2083 |
|
2084 |
switch (data->interface_status.ievent) { |
2085 |
case EVENT_INTERFACE_ADDED: |
2086 |
if (!wpa_s->interface_removed) |
2087 |
break; |
2088 |
wpa_s->interface_removed = 0; |
2089 |
wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was added"); |
2090 |
if (wpa_supplicant_driver_init(wpa_s) < 0) { |
2091 |
wpa_msg(wpa_s, MSG_INFO, "Failed to initialize the " |
2092 |
"driver after interface was added"); |
2093 |
} |
2094 |
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); |
2095 |
break; |
2096 |
case EVENT_INTERFACE_REMOVED: |
2097 |
wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed"); |
2098 |
wpa_s->interface_removed = 1; |
2099 |
wpa_supplicant_mark_disassoc(wpa_s); |
2100 |
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); |
2101 |
l2_packet_deinit(wpa_s->l2); |
2102 |
wpa_s->l2 = NULL; |
2103 |
#ifdef CONFIG_IBSS_RSN |
2104 |
ibss_rsn_deinit(wpa_s->ibss_rsn); |
2105 |
wpa_s->ibss_rsn = NULL; |
2106 |
#endif /* CONFIG_IBSS_RSN */ |
2107 |
#ifdef CONFIG_TERMINATE_ONLASTIF |
2108 |
/* check if last interface */ |
2109 |
if (!any_interfaces(wpa_s->global->ifaces)) |
2110 |
eloop_terminate(); |
2111 |
#endif /* CONFIG_TERMINATE_ONLASTIF */ |
2112 |
break; |
2113 |
} |
2114 |
} |
2115 |
|
2116 |
|
2117 |
#ifdef CONFIG_PEERKEY |
2118 |
static void |
2119 |
wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s, |
2120 |
union wpa_event_data *data) |
2121 |
{ |
2122 |
if (data == NULL) |
2123 |
return; |
2124 |
wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer); |
2125 |
} |
2126 |
#endif /* CONFIG_PEERKEY */ |
2127 |
|
2128 |
|
2129 |
#ifdef CONFIG_TDLS |
2130 |
static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s, |
2131 |
union wpa_event_data *data) |
2132 |
{ |
2133 |
if (data == NULL) |
2134 |
return; |
2135 |
switch (data->tdls.oper) { |
2136 |
case TDLS_REQUEST_SETUP: |
2137 |
wpa_tdls_start(wpa_s->wpa, data->tdls.peer); |
2138 |
break; |
2139 |
case TDLS_REQUEST_TEARDOWN: |
2140 |
wpa_tdls_send_teardown(wpa_s->wpa, data->tdls.peer, |
2141 |
data->tdls.reason_code); |
2142 |
break; |
2143 |
} |
2144 |
} |
2145 |
#endif /* CONFIG_TDLS */ |
2146 |
|
2147 |
|
2148 |
#ifdef CONFIG_WNM |
2149 |
static void wpa_supplicant_event_wnm(struct wpa_supplicant *wpa_s, |
2150 |
union wpa_event_data *data) |
2151 |
{ |
2152 |
if (data == NULL) |
2153 |
return; |
2154 |
switch (data->wnm.oper) { |
2155 |
case WNM_OPER_SLEEP: |
2156 |
wpa_printf(MSG_DEBUG, "Start sending WNM-Sleep Request " |
2157 |
"(action=%d, intval=%d)", |
2158 |
data->wnm.sleep_action, data->wnm.sleep_intval); |
2159 |
ieee802_11_send_wnmsleep_req(wpa_s, data->wnm.sleep_action, |
2160 |
data->wnm.sleep_intval, NULL); |
2161 |
break; |
2162 |
} |
2163 |
} |
2164 |
#endif /* CONFIG_WNM */ |
2165 |
|
2166 |
|
2167 |
#ifdef CONFIG_IEEE80211R |
2168 |
static void |
2169 |
wpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s, |
2170 |
union wpa_event_data *data) |
2171 |
{ |
2172 |
if (data == NULL) |
2173 |
return; |
2174 |
|
2175 |
if (wpa_ft_process_response(wpa_s->wpa, data->ft_ies.ies, |
2176 |
data->ft_ies.ies_len, |
2177 |
data->ft_ies.ft_action, |
2178 |
data->ft_ies.target_ap, |
2179 |
data->ft_ies.ric_ies, |
2180 |
data->ft_ies.ric_ies_len) < 0) { |
2181 |
/* TODO: prevent MLME/driver from trying to associate? */ |
2182 |
} |
2183 |
} |
2184 |
#endif /* CONFIG_IEEE80211R */ |
2185 |
|
2186 |
|
2187 |
#ifdef CONFIG_IBSS_RSN |
2188 |
static void wpa_supplicant_event_ibss_rsn_start(struct wpa_supplicant *wpa_s, |
2189 |
union wpa_event_data *data) |
2190 |
{ |
2191 |
struct wpa_ssid *ssid; |
2192 |
if (wpa_s->wpa_state < WPA_ASSOCIATED) |
2193 |
return; |
2194 |
if (data == NULL) |
2195 |
return; |
2196 |
ssid = wpa_s->current_ssid; |
2197 |
if (ssid == NULL) |
2198 |
return; |
2199 |
if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt)) |
2200 |
return; |
2201 |
|
2202 |
ibss_rsn_start(wpa_s->ibss_rsn, data->ibss_rsn_start.peer); |
2203 |
} |
2204 |
#endif /* CONFIG_IBSS_RSN */ |
2205 |
|
2206 |
|
2207 |
#ifdef CONFIG_IEEE80211R |
2208 |
static void ft_rx_action(struct wpa_supplicant *wpa_s, const u8 *data, |
2209 |
size_t len) |
2210 |
{ |
2211 |
const u8 *sta_addr, *target_ap_addr; |
2212 |
u16 status; |
2213 |
|
2214 |
wpa_hexdump(MSG_MSGDUMP, "FT: RX Action", data, len); |
2215 |
if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) |
2216 |
return; /* only SME case supported for now */ |
2217 |
if (len < 1 + 2 * ETH_ALEN + 2) |
2218 |
return; |
2219 |
if (data[0] != 2) |
2220 |
return; /* Only FT Action Response is supported for now */ |
2221 |
sta_addr = data + 1; |
2222 |
target_ap_addr = data + 1 + ETH_ALEN; |
2223 |
status = WPA_GET_LE16(data + 1 + 2 * ETH_ALEN); |
2224 |
wpa_dbg(wpa_s, MSG_DEBUG, "FT: Received FT Action Response: STA " |
2225 |
MACSTR " TargetAP " MACSTR " status %u", |
2226 |
MAC2STR(sta_addr), MAC2STR(target_ap_addr), status); |
2227 |
|
2228 |
if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) { |
2229 |
wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR |
2230 |
" in FT Action Response", MAC2STR(sta_addr)); |
2231 |
return; |
2232 |
} |
2233 |
|
2234 |
if (status) { |
2235 |
wpa_dbg(wpa_s, MSG_DEBUG, "FT: FT Action Response indicates " |
2236 |
"failure (status code %d)", status); |
2237 |
/* TODO: report error to FT code(?) */ |
2238 |
return; |
2239 |
} |
2240 |
|
2241 |
if (wpa_ft_process_response(wpa_s->wpa, data + 1 + 2 * ETH_ALEN + 2, |
2242 |
len - (1 + 2 * ETH_ALEN + 2), 1, |
2243 |
target_ap_addr, NULL, 0) < 0) |
2244 |
return; |
2245 |
|
2246 |
#ifdef CONFIG_SME |
2247 |
{ |
2248 |
struct wpa_bss *bss; |
2249 |
bss = wpa_bss_get_bssid(wpa_s, target_ap_addr); |
2250 |
if (bss) |
2251 |
wpa_s->sme.freq = bss->freq; |
2252 |
wpa_s->sme.auth_alg = WPA_AUTH_ALG_FT; |
2253 |
sme_associate(wpa_s, WPAS_MODE_INFRA, target_ap_addr, |
2254 |
WLAN_AUTH_FT); |
2255 |
} |
2256 |
#endif /* CONFIG_SME */ |
2257 |
} |
2258 |
#endif /* CONFIG_IEEE80211R */ |
2259 |
|
2260 |
|
2261 |
static void wpa_supplicant_event_unprot_deauth(struct wpa_supplicant *wpa_s, |
2262 |
struct unprot_deauth *e) |
2263 |
{ |
2264 |
#ifdef CONFIG_IEEE80211W |
2265 |
wpa_printf(MSG_DEBUG, "Unprotected Deauthentication frame " |
2266 |
"dropped: " MACSTR " -> " MACSTR |
2267 |
" (reason code %u)", |
2268 |
MAC2STR(e->sa), MAC2STR(e->da), e->reason_code); |
2269 |
sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code); |
2270 |
#endif /* CONFIG_IEEE80211W */ |
2271 |
} |
2272 |
|
2273 |
|
2274 |
static void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s, |
2275 |
struct unprot_disassoc *e) |
2276 |
{ |
2277 |
#ifdef CONFIG_IEEE80211W |
2278 |
wpa_printf(MSG_DEBUG, "Unprotected Disassociation frame " |
2279 |
"dropped: " MACSTR " -> " MACSTR |
2280 |
" (reason code %u)", |
2281 |
MAC2STR(e->sa), MAC2STR(e->da), e->reason_code); |
2282 |
sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code); |
2283 |
#endif /* CONFIG_IEEE80211W */ |
2284 |
} |
2285 |
|
2286 |
|
2287 |
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, |
2288 |
union wpa_event_data *data) |
2289 |
{ |
2290 |
struct wpa_supplicant *wpa_s = ctx; |
2291 |
u16 reason_code = 0; |
2292 |
int locally_generated = 0; |
2293 |
|
2294 |
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED && |
2295 |
event != EVENT_INTERFACE_ENABLED && |
2296 |
event != EVENT_INTERFACE_STATUS && |
2297 |
event != EVENT_SCHED_SCAN_STOPPED) { |
2298 |
wpa_dbg(wpa_s, MSG_DEBUG, |
2299 |
"Ignore event %s (%d) while interface is disabled", |
2300 |
event_to_string(event), event); |
2301 |
return; |
2302 |
} |
2303 |
|
2304 |
#ifndef CONFIG_NO_STDOUT_DEBUG |
2305 |
{ |
2306 |
int level = MSG_DEBUG; |
2307 |
|
2308 |
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) { |
2309 |
const struct ieee80211_hdr *hdr; |
2310 |
u16 fc; |
2311 |
hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; |
2312 |
fc = le_to_host16(hdr->frame_control); |
2313 |
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && |
2314 |
WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) |
2315 |
level = MSG_EXCESSIVE; |
2316 |
} |
2317 |
|
2318 |
wpa_dbg(wpa_s, level, "Event %s (%d) received", |
2319 |
event_to_string(event), event); |
2320 |
} |
2321 |
#endif /* CONFIG_NO_STDOUT_DEBUG */ |
2322 |
|
2323 |
switch (event) { |
2324 |
case EVENT_AUTH: |
2325 |
sme_event_auth(wpa_s, data); |
2326 |
break; |
2327 |
case EVENT_ASSOC: |
2328 |
wpa_supplicant_event_assoc(wpa_s, data); |
2329 |
break; |
2330 |
case EVENT_DISASSOC: |
2331 |
wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification"); |
2332 |
if (data) { |
2333 |
wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", |
2334 |
data->disassoc_info.reason_code, |
2335 |
data->disassoc_info.locally_generated ? |
2336 |
" (locally generated)" : ""); |
2337 |
if (data->disassoc_info.addr) |
2338 |
wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR, |
2339 |
MAC2STR(data->disassoc_info.addr)); |
2340 |
} |
2341 |
#ifdef CONFIG_AP |
2342 |
if (wpa_s->ap_iface && data && data->disassoc_info.addr) { |
2343 |
hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], |
2344 |
data->disassoc_info.addr); |
2345 |
break; |
2346 |
} |
2347 |
if (wpa_s->ap_iface) { |
2348 |
wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in " |
2349 |
"AP mode"); |
2350 |
break; |
2351 |
} |
2352 |
#endif /* CONFIG_AP */ |
2353 |
if (data) { |
2354 |
reason_code = data->disassoc_info.reason_code; |
2355 |
locally_generated = |
2356 |
data->disassoc_info.locally_generated; |
2357 |
wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)", |
2358 |
data->disassoc_info.ie, |
2359 |
data->disassoc_info.ie_len); |
2360 |
#ifdef CONFIG_P2P |
2361 |
wpas_p2p_disassoc_notif( |
2362 |
wpa_s, data->disassoc_info.addr, reason_code, |
2363 |
data->disassoc_info.ie, |
2364 |
data->disassoc_info.ie_len, |
2365 |
locally_generated); |
2366 |
#endif /* CONFIG_P2P */ |
2367 |
} |
2368 |
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) |
2369 |
sme_event_disassoc(wpa_s, data); |
2370 |
/* fall through */ |
2371 |
case EVENT_DEAUTH: |
2372 |
if (event == EVENT_DEAUTH) { |
2373 |
wpa_dbg(wpa_s, MSG_DEBUG, |
2374 |
"Deauthentication notification"); |
2375 |
if (data) { |
2376 |
reason_code = data->deauth_info.reason_code; |
2377 |
locally_generated = |
2378 |
data->deauth_info.locally_generated; |
2379 |
wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", |
2380 |
data->deauth_info.reason_code, |
2381 |
data->deauth_info.locally_generated ? |
2382 |
" (locally generated)" : ""); |
2383 |
if (data->deauth_info.addr) { |
2384 |
wpa_dbg(wpa_s, MSG_DEBUG, " * address " |
2385 |
MACSTR, |
2386 |
MAC2STR(data->deauth_info. |
2387 |
addr)); |
2388 |
} |
2389 |
wpa_hexdump(MSG_DEBUG, |
2390 |
"Deauthentication frame IE(s)", |
2391 |
data->deauth_info.ie, |
2392 |
data->deauth_info.ie_len); |
2393 |
} |
2394 |
} |
2395 |
#ifdef CONFIG_AP |
2396 |
if (wpa_s->ap_iface && data && data->deauth_info.addr) { |
2397 |
hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], |
2398 |
data->deauth_info.addr); |
2399 |
break; |
2400 |
} |
2401 |
if (wpa_s->ap_iface) { |
2402 |
wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in " |
2403 |
"AP mode"); |
2404 |
break; |
2405 |
} |
2406 |
#endif /* CONFIG_AP */ |
2407 |
wpa_supplicant_event_disassoc(wpa_s, reason_code, |
2408 |
locally_generated); |
2409 |
if (reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED || |
2410 |
((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || |
2411 |
(wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) && |
2412 |
eapol_sm_failed(wpa_s->eapol))) |
2413 |
wpas_auth_failed(wpa_s); |
2414 |
#ifdef CONFIG_P2P |
2415 |
if (event == EVENT_DEAUTH && data) { |
2416 |
if (wpas_p2p_deauth_notif(wpa_s, |
2417 |
data->deauth_info.addr, |
2418 |
reason_code, |
2419 |
data->deauth_info.ie, |
2420 |
data->deauth_info.ie_len, |
2421 |
locally_generated) > 0) { |
2422 |
/* |
2423 |
* The interface was removed, so cannot |
2424 |
* continue processing any additional |
2425 |
* operations after this. |
2426 |
*/ |
2427 |
break; |
2428 |
} |
2429 |
} |
2430 |
#endif /* CONFIG_P2P */ |
2431 |
wpa_supplicant_event_disassoc_finish(wpa_s, reason_code, |
2432 |
locally_generated); |
2433 |
break; |
2434 |
case EVENT_MICHAEL_MIC_FAILURE: |
2435 |
wpa_supplicant_event_michael_mic_failure(wpa_s, data); |
2436 |
break; |
2437 |
#ifndef CONFIG_NO_SCAN_PROCESSING |
2438 |
case EVENT_SCAN_RESULTS: |
2439 |
wpa_supplicant_event_scan_results(wpa_s, data); |
2440 |
#ifdef CONFIG_P2P |
2441 |
if (wpa_s->global->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled && |
2442 |
wpa_s->global->p2p != NULL && |
2443 |
wpa_s->wpa_state != WPA_AUTHENTICATING && |
2444 |
wpa_s->wpa_state != WPA_ASSOCIATING) { |
2445 |
wpa_s->global->p2p_cb_on_scan_complete = 0; |
2446 |
if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { |
2447 |
wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " |
2448 |
"continued after scan result processing"); |
2449 |
} |
2450 |
} |
2451 |
#endif /* CONFIG_P2P */ |
2452 |
break; |
2453 |
#endif /* CONFIG_NO_SCAN_PROCESSING */ |
2454 |
case EVENT_ASSOCINFO: |
2455 |
wpa_supplicant_event_associnfo(wpa_s, data); |
2456 |
break; |
2457 |
case EVENT_INTERFACE_STATUS: |
2458 |
wpa_supplicant_event_interface_status(wpa_s, data); |
2459 |
break; |
2460 |
case EVENT_PMKID_CANDIDATE: |
2461 |
wpa_supplicant_event_pmkid_candidate(wpa_s, data); |
2462 |
break; |
2463 |
#ifdef CONFIG_PEERKEY |
2464 |
case EVENT_STKSTART: |
2465 |
wpa_supplicant_event_stkstart(wpa_s, data); |
2466 |
break; |
2467 |
#endif /* CONFIG_PEERKEY */ |
2468 |
#ifdef CONFIG_TDLS |
2469 |
case EVENT_TDLS: |
2470 |
wpa_supplicant_event_tdls(wpa_s, data); |
2471 |
break; |
2472 |
#endif /* CONFIG_TDLS */ |
2473 |
#ifdef CONFIG_WNM |
2474 |
case EVENT_WNM: |
2475 |
wpa_supplicant_event_wnm(wpa_s, data); |
2476 |
break; |
2477 |
#endif /* CONFIG_WNM */ |
2478 |
#ifdef CONFIG_IEEE80211R |
2479 |
case EVENT_FT_RESPONSE: |
2480 |
wpa_supplicant_event_ft_response(wpa_s, data); |
2481 |
break; |
2482 |
#endif /* CONFIG_IEEE80211R */ |
2483 |
#ifdef CONFIG_IBSS_RSN |
2484 |
case EVENT_IBSS_RSN_START: |
2485 |
wpa_supplicant_event_ibss_rsn_start(wpa_s, data); |
2486 |
break; |
2487 |
#endif /* CONFIG_IBSS_RSN */ |
2488 |
case EVENT_ASSOC_REJECT: |
2489 |
if (data->assoc_reject.bssid) |
2490 |
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT |
2491 |
"bssid=" MACSTR " status_code=%u", |
2492 |
MAC2STR(data->assoc_reject.bssid), |
2493 |
data->assoc_reject.status_code); |
2494 |
else |
2495 |
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT |
2496 |
"status_code=%u", |
2497 |
data->assoc_reject.status_code); |
2498 |
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) |
2499 |
sme_event_assoc_reject(wpa_s, data); |
2500 |
else { |
2501 |
const u8 *bssid = data->assoc_reject.bssid; |
2502 |
if (bssid == NULL || is_zero_ether_addr(bssid)) |
2503 |
bssid = wpa_s->pending_bssid; |
2504 |
wpas_connection_failed(wpa_s, bssid); |
2505 |
wpa_supplicant_mark_disassoc(wpa_s); |
2506 |
} |
2507 |
break; |
2508 |
case EVENT_AUTH_TIMED_OUT: |
2509 |
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) |
2510 |
sme_event_auth_timed_out(wpa_s, data); |
2511 |
break; |
2512 |
case EVENT_ASSOC_TIMED_OUT: |
2513 |
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) |
2514 |
sme_event_assoc_timed_out(wpa_s, data); |
2515 |
break; |
2516 |
case EVENT_TX_STATUS: |
2517 |
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS dst=" MACSTR |
2518 |
" type=%d stype=%d", |
2519 |
MAC2STR(data->tx_status.dst), |
2520 |
data->tx_status.type, data->tx_status.stype); |
2521 |
#ifdef CONFIG_AP |
2522 |
if (wpa_s->ap_iface == NULL) { |
2523 |
#ifdef CONFIG_OFFCHANNEL |
2524 |
if (data->tx_status.type == WLAN_FC_TYPE_MGMT && |
2525 |
data->tx_status.stype == WLAN_FC_STYPE_ACTION) |
2526 |
offchannel_send_action_tx_status( |
2527 |
wpa_s, data->tx_status.dst, |
2528 |
data->tx_status.data, |
2529 |
data->tx_status.data_len, |
2530 |
data->tx_status.ack ? |
2531 |
OFFCHANNEL_SEND_ACTION_SUCCESS : |
2532 |
OFFCHANNEL_SEND_ACTION_NO_ACK); |
2533 |
#endif /* CONFIG_OFFCHANNEL */ |
2534 |
break; |
2535 |
} |
2536 |
#endif /* CONFIG_AP */ |
2537 |
#ifdef CONFIG_OFFCHANNEL |
2538 |
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst=" |
2539 |
MACSTR, MAC2STR(wpa_s->parent->pending_action_dst)); |
2540 |
/* |
2541 |
* Catch TX status events for Action frames we sent via group |
2542 |
* interface in GO mode. |
2543 |
*/ |
2544 |
if (data->tx_status.type == WLAN_FC_TYPE_MGMT && |
2545 |
data->tx_status.stype == WLAN_FC_STYPE_ACTION && |
2546 |
os_memcmp(wpa_s->parent->pending_action_dst, |
2547 |
data->tx_status.dst, ETH_ALEN) == 0) { |
2548 |
offchannel_send_action_tx_status( |
2549 |
wpa_s->parent, data->tx_status.dst, |
2550 |
data->tx_status.data, |
2551 |
data->tx_status.data_len, |
2552 |
data->tx_status.ack ? |
2553 |
OFFCHANNEL_SEND_ACTION_SUCCESS : |
2554 |
OFFCHANNEL_SEND_ACTION_NO_ACK); |
2555 |
break; |
2556 |
} |
2557 |
#endif /* CONFIG_OFFCHANNEL */ |
2558 |
#ifdef CONFIG_AP |
2559 |
switch (data->tx_status.type) { |
2560 |
case WLAN_FC_TYPE_MGMT: |
2561 |
ap_mgmt_tx_cb(wpa_s, data->tx_status.data, |
2562 |
data->tx_status.data_len, |
2563 |
data->tx_status.stype, |
2564 |
data->tx_status.ack); |
2565 |
break; |
2566 |
case WLAN_FC_TYPE_DATA: |
2567 |
ap_tx_status(wpa_s, data->tx_status.dst, |
2568 |
data->tx_status.data, |
2569 |
data->tx_status.data_len, |
2570 |
data->tx_status.ack); |
2571 |
break; |
2572 |
} |
2573 |
#endif /* CONFIG_AP */ |
2574 |
break; |
2575 |
#ifdef CONFIG_AP |
2576 |
case EVENT_EAPOL_TX_STATUS: |
2577 |
ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst, |
2578 |
data->eapol_tx_status.data, |
2579 |
data->eapol_tx_status.data_len, |
2580 |
data->eapol_tx_status.ack); |
2581 |
break; |
2582 |
case EVENT_DRIVER_CLIENT_POLL_OK: |
2583 |
ap_client_poll_ok(wpa_s, data->client_poll.addr); |
2584 |
break; |
2585 |
case EVENT_RX_FROM_UNKNOWN: |
2586 |
if (wpa_s->ap_iface == NULL) |
2587 |
break; |
2588 |
ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr, |
2589 |
data->rx_from_unknown.wds); |
2590 |
break; |
2591 |
case EVENT_CH_SWITCH: |
2592 |
if (!data) |
2593 |
break; |
2594 |
if (!wpa_s->ap_iface) { |
2595 |
wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch " |
2596 |
"event in non-AP mode"); |
2597 |
break; |
2598 |
} |
2599 |
|
2600 |
#ifdef CONFIG_AP |
2601 |
wpas_ap_ch_switch(wpa_s, data->ch_switch.freq, |
2602 |
data->ch_switch.ht_enabled, |
2603 |
data->ch_switch.ch_offset); |
2604 |
#endif /* CONFIG_AP */ |
2605 |
break; |
2606 |
case EVENT_RX_MGMT: { |
2607 |
u16 fc, stype; |
2608 |
const struct ieee80211_mgmt *mgmt; |
2609 |
|
2610 |
mgmt = (const struct ieee80211_mgmt *) |
2611 |
data->rx_mgmt.frame; |
2612 |
fc = le_to_host16(mgmt->frame_control); |
2613 |
stype = WLAN_FC_GET_STYPE(fc); |
2614 |
|
2615 |
if (wpa_s->ap_iface == NULL) { |
2616 |
#ifdef CONFIG_P2P |
2617 |
if (stype == WLAN_FC_STYPE_PROBE_REQ && |
2618 |
data->rx_mgmt.frame_len > 24) { |
2619 |
const u8 *src = mgmt->sa; |
2620 |
const u8 *ie = mgmt->u.probe_req.variable; |
2621 |
size_t ie_len = data->rx_mgmt.frame_len - |
2622 |
(mgmt->u.probe_req.variable - |
2623 |
data->rx_mgmt.frame); |
2624 |
wpas_p2p_probe_req_rx( |
2625 |
wpa_s, src, mgmt->da, |
2626 |
mgmt->bssid, ie, ie_len, |
2627 |
data->rx_mgmt.ssi_signal); |
2628 |
break; |
2629 |
} |
2630 |
#endif /* CONFIG_P2P */ |
2631 |
wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received " |
2632 |
"management frame in non-AP mode"); |
2633 |
break; |
2634 |
} |
2635 |
|
2636 |
if (stype == WLAN_FC_STYPE_PROBE_REQ && |
2637 |
data->rx_mgmt.frame_len > 24) { |
2638 |
const u8 *ie = mgmt->u.probe_req.variable; |
2639 |
size_t ie_len = data->rx_mgmt.frame_len - |
2640 |
(mgmt->u.probe_req.variable - |
2641 |
data->rx_mgmt.frame); |
2642 |
|
2643 |
wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da, |
2644 |
mgmt->bssid, ie, ie_len, |
2645 |
data->rx_mgmt.ssi_signal); |
2646 |
} |
2647 |
|
2648 |
ap_mgmt_rx(wpa_s, &data->rx_mgmt); |
2649 |
break; |
2650 |
} |
2651 |
#endif /* CONFIG_AP */ |
2652 |
case EVENT_RX_ACTION: |
2653 |
wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR |
2654 |
" Category=%u DataLen=%d freq=%d MHz", |
2655 |
MAC2STR(data->rx_action.sa), |
2656 |
data->rx_action.category, (int) data->rx_action.len, |
2657 |
data->rx_action.freq); |
2658 |
#ifdef CONFIG_IEEE80211R |
2659 |
if (data->rx_action.category == WLAN_ACTION_FT) { |
2660 |
ft_rx_action(wpa_s, data->rx_action.data, |
2661 |
data->rx_action.len); |
2662 |
break; |
2663 |
} |
2664 |
#endif /* CONFIG_IEEE80211R */ |
2665 |
#ifdef CONFIG_IEEE80211W |
2666 |
#ifdef CONFIG_SME |
2667 |
if (data->rx_action.category == WLAN_ACTION_SA_QUERY) { |
2668 |
sme_sa_query_rx(wpa_s, data->rx_action.sa, |
2669 |
data->rx_action.data, |
2670 |
data->rx_action.len); |
2671 |
break; |
2672 |
} |
2673 |
#endif /* CONFIG_SME */ |
2674 |
#endif /* CONFIG_IEEE80211W */ |
2675 |
#ifdef CONFIG_WNM |
2676 |
if (data->rx_action.category == WLAN_ACTION_WNM) { |
2677 |
ieee802_11_rx_wnm_action(wpa_s, &data->rx_action); |
2678 |
break; |
2679 |
} |
2680 |
#endif /* CONFIG_WNM */ |
2681 |
#ifdef CONFIG_GAS |
2682 |
if (data->rx_action.category == WLAN_ACTION_PUBLIC && |
2683 |
gas_query_rx(wpa_s->gas, data->rx_action.da, |
2684 |
data->rx_action.sa, data->rx_action.bssid, |
2685 |
data->rx_action.data, data->rx_action.len, |
2686 |
data->rx_action.freq) == 0) |
2687 |
break; |
2688 |
#endif /* CONFIG_GAS */ |
2689 |
#ifdef CONFIG_TDLS |
2690 |
if (data->rx_action.category == WLAN_ACTION_PUBLIC && |
2691 |
data->rx_action.len >= 4 && |
2692 |
data->rx_action.data[0] == WLAN_TDLS_DISCOVERY_RESPONSE) { |
2693 |
wpa_dbg(wpa_s, MSG_DEBUG, "TDLS: Received Discovery " |
2694 |
"Response from " MACSTR, |
2695 |
MAC2STR(data->rx_action.sa)); |
2696 |
break; |
2697 |
} |
2698 |
#endif /* CONFIG_TDLS */ |
2699 |
#ifdef CONFIG_P2P |
2700 |
wpas_p2p_rx_action(wpa_s, data->rx_action.da, |
2701 |
data->rx_action.sa, |
2702 |
data->rx_action.bssid, |
2703 |
data->rx_action.category, |
2704 |
data->rx_action.data, |
2705 |
data->rx_action.len, data->rx_action.freq); |
2706 |
#endif /* CONFIG_P2P */ |
2707 |
break; |
2708 |
case EVENT_RX_PROBE_REQ: |
2709 |
if (data->rx_probe_req.sa == NULL || |
2710 |
data->rx_probe_req.ie == NULL) |
2711 |
break; |
2712 |
#ifdef CONFIG_AP |
2713 |
if (wpa_s->ap_iface) { |
2714 |
hostapd_probe_req_rx(wpa_s->ap_iface->bss[0], |
2715 |
data->rx_probe_req.sa, |
2716 |
data->rx_probe_req.da, |
2717 |
data->rx_probe_req.bssid, |
2718 |
data->rx_probe_req.ie, |
2719 |
data->rx_probe_req.ie_len, |
2720 |
data->rx_probe_req.ssi_signal); |
2721 |
break; |
2722 |
} |
2723 |
#endif /* CONFIG_AP */ |
2724 |
#ifdef CONFIG_P2P |
2725 |
wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa, |
2726 |
data->rx_probe_req.da, |
2727 |
data->rx_probe_req.bssid, |
2728 |
data->rx_probe_req.ie, |
2729 |
data->rx_probe_req.ie_len, |
2730 |
data->rx_probe_req.ssi_signal); |
2731 |
#endif /* CONFIG_P2P */ |
2732 |
break; |
2733 |
case EVENT_REMAIN_ON_CHANNEL: |
2734 |
#ifdef CONFIG_OFFCHANNEL |
2735 |
offchannel_remain_on_channel_cb( |
2736 |
wpa_s, data->remain_on_channel.freq, |
2737 |
data->remain_on_channel.duration); |
2738 |
#endif /* CONFIG_OFFCHANNEL */ |
2739 |
#ifdef CONFIG_P2P |
2740 |
wpas_p2p_remain_on_channel_cb( |
2741 |
wpa_s, data->remain_on_channel.freq, |
2742 |
data->remain_on_channel.duration); |
2743 |
#endif /* CONFIG_P2P */ |
2744 |
break; |
2745 |
case EVENT_CANCEL_REMAIN_ON_CHANNEL: |
2746 |
#ifdef CONFIG_OFFCHANNEL |
2747 |
offchannel_cancel_remain_on_channel_cb( |
2748 |
wpa_s, data->remain_on_channel.freq); |
2749 |
#endif /* CONFIG_OFFCHANNEL */ |
2750 |
#ifdef CONFIG_P2P |
2751 |
wpas_p2p_cancel_remain_on_channel_cb( |
2752 |
wpa_s, data->remain_on_channel.freq); |
2753 |
#endif /* CONFIG_P2P */ |
2754 |
break; |
2755 |
#ifdef CONFIG_P2P |
2756 |
case EVENT_P2P_DEV_FOUND: { |
2757 |
struct p2p_peer_info peer_info; |
2758 |
|
2759 |
os_memset(&peer_info, 0, sizeof(peer_info)); |
2760 |
if (data->p2p_dev_found.dev_addr) |
2761 |
os_memcpy(peer_info.p2p_device_addr, |
2762 |
data->p2p_dev_found.dev_addr, ETH_ALEN); |
2763 |
if (data->p2p_dev_found.pri_dev_type) |
2764 |
os_memcpy(peer_info.pri_dev_type, |
2765 |
data->p2p_dev_found.pri_dev_type, |
2766 |
sizeof(peer_info.pri_dev_type)); |
2767 |
if (data->p2p_dev_found.dev_name) |
2768 |
os_strlcpy(peer_info.device_name, |
2769 |
data->p2p_dev_found.dev_name, |
2770 |
sizeof(peer_info.device_name)); |
2771 |
peer_info.config_methods = data->p2p_dev_found.config_methods; |
2772 |
peer_info.dev_capab = data->p2p_dev_found.dev_capab; |
2773 |
peer_info.group_capab = data->p2p_dev_found.group_capab; |
2774 |
|
2775 |
/* |
2776 |
* FIX: new_device=1 is not necessarily correct. We should |
2777 |
* maintain a P2P peer database in wpa_supplicant and update |
2778 |
* this information based on whether the peer is truly new. |
2779 |
*/ |
2780 |
wpas_dev_found(wpa_s, data->p2p_dev_found.addr, &peer_info, 1); |
2781 |
break; |
2782 |
} |
2783 |
case EVENT_P2P_GO_NEG_REQ_RX: |
2784 |
wpas_go_neg_req_rx(wpa_s, data->p2p_go_neg_req_rx.src, |
2785 |
data->p2p_go_neg_req_rx.dev_passwd_id); |
2786 |
break; |
2787 |
case EVENT_P2P_GO_NEG_COMPLETED: |
2788 |
wpas_go_neg_completed(wpa_s, data->p2p_go_neg_completed.res); |
2789 |
break; |
2790 |
case EVENT_P2P_PROV_DISC_REQUEST: |
2791 |
wpas_prov_disc_req(wpa_s, data->p2p_prov_disc_req.peer, |
2792 |
data->p2p_prov_disc_req.config_methods, |
2793 |
data->p2p_prov_disc_req.dev_addr, |
2794 |
data->p2p_prov_disc_req.pri_dev_type, |
2795 |
data->p2p_prov_disc_req.dev_name, |
2796 |
data->p2p_prov_disc_req.supp_config_methods, |
2797 |
data->p2p_prov_disc_req.dev_capab, |
2798 |
data->p2p_prov_disc_req.group_capab, |
2799 |
NULL, 0); |
2800 |
break; |
2801 |
case EVENT_P2P_PROV_DISC_RESPONSE: |
2802 |
wpas_prov_disc_resp(wpa_s, data->p2p_prov_disc_resp.peer, |
2803 |
data->p2p_prov_disc_resp.config_methods); |
2804 |
break; |
2805 |
case EVENT_P2P_SD_REQUEST: |
2806 |
wpas_sd_request(wpa_s, data->p2p_sd_req.freq, |
2807 |
data->p2p_sd_req.sa, |
2808 |
data->p2p_sd_req.dialog_token, |
2809 |
data->p2p_sd_req.update_indic, |
2810 |
data->p2p_sd_req.tlvs, |
2811 |
data->p2p_sd_req.tlvs_len); |
2812 |
break; |
2813 |
case EVENT_P2P_SD_RESPONSE: |
2814 |
wpas_sd_response(wpa_s, data->p2p_sd_resp.sa, |
2815 |
data->p2p_sd_resp.update_indic, |
2816 |
data->p2p_sd_resp.tlvs, |
2817 |
data->p2p_sd_resp.tlvs_len); |
2818 |
break; |
2819 |
#endif /* CONFIG_P2P */ |
2820 |
case EVENT_EAPOL_RX: |
2821 |
wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src, |
2822 |
data->eapol_rx.data, |
2823 |
data->eapol_rx.data_len); |
2824 |
break; |
2825 |
case EVENT_SIGNAL_CHANGE: |
2826 |
bgscan_notify_signal_change( |
2827 |
wpa_s, data->signal_change.above_threshold, |
2828 |
data->signal_change.current_signal, |
2829 |
data->signal_change.current_noise, |
2830 |
data->signal_change.current_txrate); |
2831 |
break; |
2832 |
case EVENT_INTERFACE_ENABLED: |
2833 |
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled"); |
2834 |
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { |
2835 |
wpa_supplicant_update_mac_addr(wpa_s); |
2836 |
#ifdef CONFIG_AP |
2837 |
if (!wpa_s->ap_iface) { |
2838 |
wpa_supplicant_set_state(wpa_s, |
2839 |
WPA_DISCONNECTED); |
2840 |
wpa_supplicant_req_scan(wpa_s, 0, 0); |
2841 |
} else |
2842 |
wpa_supplicant_set_state(wpa_s, |
2843 |
WPA_COMPLETED); |
2844 |
#else /* CONFIG_AP */ |
2845 |
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); |
2846 |
wpa_supplicant_req_scan(wpa_s, 0, 0); |
2847 |
#endif /* CONFIG_AP */ |
2848 |
} |
2849 |
break; |
2850 |
case EVENT_INTERFACE_DISABLED: |
2851 |
wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled"); |
2852 |
wpa_supplicant_mark_disassoc(wpa_s); |
2853 |
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); |
2854 |
break; |
2855 |
case EVENT_CHANNEL_LIST_CHANGED: |
2856 |
if (wpa_s->drv_priv == NULL) |
2857 |
break; /* Ignore event during drv initialization */ |
2858 |
|
2859 |
free_hw_features(wpa_s); |
2860 |
wpa_s->hw.modes = wpa_drv_get_hw_feature_data( |
2861 |
wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags); |
2862 |
|
2863 |
#ifdef CONFIG_P2P |
2864 |
wpas_p2p_update_channel_list(wpa_s); |
2865 |
#endif /* CONFIG_P2P */ |
2866 |
break; |
2867 |
case EVENT_INTERFACE_UNAVAILABLE: |
2868 |
#ifdef CONFIG_P2P |
2869 |
wpas_p2p_interface_unavailable(wpa_s); |
2870 |
#endif /* CONFIG_P2P */ |
2871 |
break; |
2872 |
case EVENT_BEST_CHANNEL: |
2873 |
wpa_dbg(wpa_s, MSG_DEBUG, "Best channel event received " |
2874 |
"(%d %d %d)", |
2875 |
data->best_chan.freq_24, data->best_chan.freq_5, |
2876 |
data->best_chan.freq_overall); |
2877 |
wpa_s->best_24_freq = data->best_chan.freq_24; |
2878 |
wpa_s->best_5_freq = data->best_chan.freq_5; |
2879 |
wpa_s->best_overall_freq = data->best_chan.freq_overall; |
2880 |
#ifdef CONFIG_P2P |
2881 |
wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24, |
2882 |
data->best_chan.freq_5, |
2883 |
data->best_chan.freq_overall); |
2884 |
#endif /* CONFIG_P2P */ |
2885 |
break; |
2886 |
case EVENT_UNPROT_DEAUTH: |
2887 |
wpa_supplicant_event_unprot_deauth(wpa_s, |
2888 |
&data->unprot_deauth); |
2889 |
break; |
2890 |
case EVENT_UNPROT_DISASSOC: |
2891 |
wpa_supplicant_event_unprot_disassoc(wpa_s, |
2892 |
&data->unprot_disassoc); |
2893 |
break; |
2894 |
case EVENT_STATION_LOW_ACK: |
2895 |
#ifdef CONFIG_AP |
2896 |
if (wpa_s->ap_iface && data) |
2897 |
hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0], |
2898 |
data->low_ack.addr); |
2899 |
#endif /* CONFIG_AP */ |
2900 |
#ifdef CONFIG_TDLS |
2901 |
if (data) |
2902 |
wpa_tdls_disable_link(wpa_s->wpa, data->low_ack.addr); |
2903 |
#endif /* CONFIG_TDLS */ |
2904 |
break; |
2905 |
case EVENT_IBSS_PEER_LOST: |
2906 |
#ifdef CONFIG_IBSS_RSN |
2907 |
ibss_rsn_stop(wpa_s->ibss_rsn, data->ibss_peer_lost.peer); |
2908 |
#endif /* CONFIG_IBSS_RSN */ |
2909 |
break; |
2910 |
case EVENT_DRIVER_GTK_REKEY: |
2911 |
if (os_memcmp(data->driver_gtk_rekey.bssid, |
2912 |
wpa_s->bssid, ETH_ALEN)) |
2913 |
break; |
2914 |
if (!wpa_s->wpa) |
2915 |
break; |
2916 |
wpa_sm_update_replay_ctr(wpa_s->wpa, |
2917 |
data->driver_gtk_rekey.replay_ctr); |
2918 |
break; |
2919 |
case EVENT_SCHED_SCAN_STOPPED: |
2920 |
wpa_s->sched_scanning = 0; |
2921 |
wpa_supplicant_notify_scanning(wpa_s, 0); |
2922 |
|
2923 |
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) |
2924 |
break; |
2925 |
|
2926 |
/* |
2927 |
* If we timed out, start a new sched scan to continue |
2928 |
* searching for more SSIDs. |
2929 |
*/ |
2930 |
if (wpa_s->sched_scan_timed_out) |
2931 |
wpa_supplicant_req_sched_scan(wpa_s); |
2932 |
break; |
2933 |
case EVENT_WPS_BUTTON_PUSHED: |
2934 |
#ifdef CONFIG_WPS |
2935 |
wpas_wps_start_pbc(wpa_s, NULL, 0); |
2936 |
#endif /* CONFIG_WPS */ |
2937 |
break; |
2938 |
default: |
2939 |
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); |
2940 |
break; |
2941 |
} |
2942 |
} |