blob: 1a7c0ff32fb9c7f40f9ba13e8ab2b8a6e1402657 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003 * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
14
15#include "common.h"
16#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080017#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "eapol_supp/eapol_supp_sm.h"
19#include "eap_peer/eap.h"
20#include "eap_server/eap_methods.h"
21#include "rsn_supp/wpa.h"
22#include "eloop.h"
23#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070024#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "l2_packet/l2_packet.h"
26#include "wpa_supplicant_i.h"
27#include "driver_i.h"
28#include "ctrl_iface.h"
29#include "pcsc_funcs.h"
30#include "common/version.h"
31#include "rsn_supp/preauth.h"
32#include "rsn_supp/pmksa_cache.h"
33#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "common/ieee802_11_defs.h"
35#include "p2p/p2p.h"
36#include "blacklist.h"
37#include "wpas_glue.h"
38#include "wps_supplicant.h"
39#include "ibss_rsn.h"
40#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080041#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042#include "ap.h"
43#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070044#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "notify.h"
46#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070047#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "bss.h"
49#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080050#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070051#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070052#include "wnm_sta.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053
54const char *wpa_supplicant_version =
55"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080056"Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057
58const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080059"This software may be distributed under the terms of the BSD license.\n"
60"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070061#ifdef EAP_TLS_OPENSSL
62"\nThis product includes software developed by the OpenSSL Project\n"
63"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
64#endif /* EAP_TLS_OPENSSL */
65;
66
67#ifndef CONFIG_NO_STDOUT_DEBUG
68/* Long text divided into parts in order to fit in C89 strings size limits. */
69const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080070"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080072"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073"\n"
74"Redistribution and use in source and binary forms, with or without\n"
75"modification, are permitted provided that the following conditions are\n"
76"met:\n"
77"\n";
78const char *wpa_supplicant_full_license3 =
79"1. Redistributions of source code must retain the above copyright\n"
80" notice, this list of conditions and the following disclaimer.\n"
81"\n"
82"2. Redistributions in binary form must reproduce the above copyright\n"
83" notice, this list of conditions and the following disclaimer in the\n"
84" documentation and/or other materials provided with the distribution.\n"
85"\n";
86const char *wpa_supplicant_full_license4 =
87"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
88" names of its contributors may be used to endorse or promote products\n"
89" derived from this software without specific prior written permission.\n"
90"\n"
91"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
92"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
93"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
94"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
95const char *wpa_supplicant_full_license5 =
96"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
97"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
98"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
99"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
100"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
101"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
102"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
103"\n";
104#endif /* CONFIG_NO_STDOUT_DEBUG */
105
106extern int wpa_debug_level;
107extern int wpa_debug_show_keys;
108extern int wpa_debug_timestamp;
109extern struct wpa_driver_ops *wpa_drivers[];
110
111/* Configure default/group WEP keys for static WEP */
112int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
113{
114 int i, set = 0;
115
116 for (i = 0; i < NUM_WEP_KEYS; i++) {
117 if (ssid->wep_key_len[i] == 0)
118 continue;
119
120 set = 1;
121 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
122 i, i == ssid->wep_tx_keyidx, NULL, 0,
123 ssid->wep_key[i], ssid->wep_key_len[i]);
124 }
125
126 return set;
127}
128
129
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700130int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
131 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700132{
133 u8 key[32];
134 size_t keylen;
135 enum wpa_alg alg;
136 u8 seq[6] = { 0 };
137
138 /* IBSS/WPA-None uses only one key (Group) for both receiving and
139 * sending unicast and multicast packets. */
140
141 if (ssid->mode != WPAS_MODE_IBSS) {
142 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
143 "IBSS/ad-hoc) for WPA-None", ssid->mode);
144 return -1;
145 }
146
147 if (!ssid->psk_set) {
148 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
149 "WPA-None");
150 return -1;
151 }
152
153 switch (wpa_s->group_cipher) {
154 case WPA_CIPHER_CCMP:
155 os_memcpy(key, ssid->psk, 16);
156 keylen = 16;
157 alg = WPA_ALG_CCMP;
158 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700159 case WPA_CIPHER_GCMP:
160 os_memcpy(key, ssid->psk, 16);
161 keylen = 16;
162 alg = WPA_ALG_GCMP;
163 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700164 case WPA_CIPHER_TKIP:
165 /* WPA-None uses the same Michael MIC key for both TX and RX */
166 os_memcpy(key, ssid->psk, 16 + 8);
167 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
168 keylen = 32;
169 alg = WPA_ALG_TKIP;
170 break;
171 default:
172 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
173 "WPA-None", wpa_s->group_cipher);
174 return -1;
175 }
176
177 /* TODO: should actually remember the previously used seq#, both for TX
178 * and RX from each STA.. */
179
180 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
181}
182
183
184static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
185{
186 struct wpa_supplicant *wpa_s = eloop_ctx;
187 const u8 *bssid = wpa_s->bssid;
188 if (is_zero_ether_addr(bssid))
189 bssid = wpa_s->pending_bssid;
190 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
191 MAC2STR(bssid));
192 wpa_blacklist_add(wpa_s, bssid);
193 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800194 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700195 wpa_s->reassociate = 1;
196
197 /*
198 * If we timed out, the AP or the local radio may be busy.
199 * So, wait a second until scanning again.
200 */
201 wpa_supplicant_req_scan(wpa_s, 1, 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700202
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -0700203 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204}
205
206
207/**
208 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
209 * @wpa_s: Pointer to wpa_supplicant data
210 * @sec: Number of seconds after which to time out authentication
211 * @usec: Number of microseconds after which to time out authentication
212 *
213 * This function is used to schedule a timeout for the current authentication
214 * attempt.
215 */
216void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
217 int sec, int usec)
218{
219 if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
220 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
221 return;
222
223 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
224 "%d usec", sec, usec);
225 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
226 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
227}
228
229
230/**
231 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
232 * @wpa_s: Pointer to wpa_supplicant data
233 *
234 * This function is used to cancel authentication timeout scheduled with
235 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
236 * been completed.
237 */
238void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
239{
240 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
241 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
242 wpa_blacklist_del(wpa_s, wpa_s->bssid);
243}
244
245
246/**
247 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
248 * @wpa_s: Pointer to wpa_supplicant data
249 *
250 * This function is used to configure EAPOL state machine based on the selected
251 * authentication mode.
252 */
253void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
254{
255#ifdef IEEE8021X_EAPOL
256 struct eapol_config eapol_conf;
257 struct wpa_ssid *ssid = wpa_s->current_ssid;
258
259#ifdef CONFIG_IBSS_RSN
260 if (ssid->mode == WPAS_MODE_IBSS &&
261 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
262 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
263 /*
264 * RSN IBSS authentication is per-STA and we can disable the
265 * per-BSSID EAPOL authentication.
266 */
267 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
268 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
269 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
270 return;
271 }
272#endif /* CONFIG_IBSS_RSN */
273
274 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
275 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
276
277 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
278 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
279 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
280 else
281 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
282
283 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
285 eapol_conf.accept_802_1x_keys = 1;
286 eapol_conf.required_keys = 0;
287 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
288 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
289 }
290 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
291 eapol_conf.required_keys |=
292 EAPOL_REQUIRE_KEY_BROADCAST;
293 }
294
295 if (wpa_s->conf && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
296 eapol_conf.required_keys = 0;
297 }
298 if (wpa_s->conf)
299 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
300 eapol_conf.workaround = ssid->eap_workaround;
301 eapol_conf.eap_disabled =
302 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
303 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
304 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
305 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
306#endif /* IEEE8021X_EAPOL */
307}
308
309
310/**
311 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
312 * @wpa_s: Pointer to wpa_supplicant data
313 * @ssid: Configuration data for the network
314 *
315 * This function is used to configure WPA state machine and related parameters
316 * to a mode where WPA is not enabled. This is called as part of the
317 * authentication configuration when the selected network does not use WPA.
318 */
319void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
320 struct wpa_ssid *ssid)
321{
322 int i;
323
324 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
325 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
326 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
327 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
328 else
329 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
330 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
331 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
332 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
333 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
334 wpa_s->group_cipher = WPA_CIPHER_NONE;
335 wpa_s->mgmt_group_cipher = 0;
336
337 for (i = 0; i < NUM_WEP_KEYS; i++) {
338 if (ssid->wep_key_len[i] > 5) {
339 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
340 wpa_s->group_cipher = WPA_CIPHER_WEP104;
341 break;
342 } else if (ssid->wep_key_len[i] > 0) {
343 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
344 wpa_s->group_cipher = WPA_CIPHER_WEP40;
345 break;
346 }
347 }
348
349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
351 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
352 wpa_s->pairwise_cipher);
353 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
354#ifdef CONFIG_IEEE80211W
355 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
356 wpa_s->mgmt_group_cipher);
357#endif /* CONFIG_IEEE80211W */
358
359 pmksa_cache_clear_current(wpa_s->wpa);
360}
361
362
Dmitry Shmidt04949592012-07-19 12:16:46 -0700363void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800364{
365 int i;
366 if (wpa_s->hw.modes == NULL)
367 return;
368
369 for (i = 0; i < wpa_s->hw.num_modes; i++) {
370 os_free(wpa_s->hw.modes[i].channels);
371 os_free(wpa_s->hw.modes[i].rates);
372 }
373
374 os_free(wpa_s->hw.modes);
375 wpa_s->hw.modes = NULL;
376}
377
378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700379static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
380{
381 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700382 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 scard_deinit(wpa_s->scard);
384 wpa_s->scard = NULL;
385 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
386 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
387 l2_packet_deinit(wpa_s->l2);
388 wpa_s->l2 = NULL;
389 if (wpa_s->l2_br) {
390 l2_packet_deinit(wpa_s->l2_br);
391 wpa_s->l2_br = NULL;
392 }
393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394 if (wpa_s->conf != NULL) {
395 struct wpa_ssid *ssid;
396 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
397 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700398 }
399
400 os_free(wpa_s->confname);
401 wpa_s->confname = NULL;
402
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700403 os_free(wpa_s->confanother);
404 wpa_s->confanother = NULL;
405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 wpa_sm_set_eapol(wpa_s->wpa, NULL);
407 eapol_sm_deinit(wpa_s->eapol);
408 wpa_s->eapol = NULL;
409
410 rsn_preauth_deinit(wpa_s->wpa);
411
412#ifdef CONFIG_TDLS
413 wpa_tdls_deinit(wpa_s->wpa);
414#endif /* CONFIG_TDLS */
415
416 pmksa_candidate_free(wpa_s->wpa);
417 wpa_sm_deinit(wpa_s->wpa);
418 wpa_s->wpa = NULL;
419 wpa_blacklist_clear(wpa_s);
420
421 wpa_bss_deinit(wpa_s);
422
423 wpa_supplicant_cancel_scan(wpa_s);
424 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800425 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
426#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
427 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
428 wpa_s, NULL);
429#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700430
431 wpas_wps_deinit(wpa_s);
432
433 wpabuf_free(wpa_s->pending_eapol_rx);
434 wpa_s->pending_eapol_rx = NULL;
435
436#ifdef CONFIG_IBSS_RSN
437 ibss_rsn_deinit(wpa_s->ibss_rsn);
438 wpa_s->ibss_rsn = NULL;
439#endif /* CONFIG_IBSS_RSN */
440
441 sme_deinit(wpa_s);
442
443#ifdef CONFIG_AP
444 wpa_supplicant_ap_deinit(wpa_s);
445#endif /* CONFIG_AP */
446
447#ifdef CONFIG_P2P
448 wpas_p2p_deinit(wpa_s);
449#endif /* CONFIG_P2P */
450
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800451#ifdef CONFIG_OFFCHANNEL
452 offchannel_deinit(wpa_s);
453#endif /* CONFIG_OFFCHANNEL */
454
455 wpa_supplicant_cancel_sched_scan(wpa_s);
456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 os_free(wpa_s->next_scan_freqs);
458 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800459
460 gas_query_deinit(wpa_s->gas);
461 wpa_s->gas = NULL;
462
463 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700464
465 os_free(wpa_s->bssid_filter);
466 wpa_s->bssid_filter = NULL;
467
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800468 os_free(wpa_s->disallow_aps_bssid);
469 wpa_s->disallow_aps_bssid = NULL;
470 os_free(wpa_s->disallow_aps_ssid);
471 wpa_s->disallow_aps_ssid = NULL;
472
Dmitry Shmidt04949592012-07-19 12:16:46 -0700473 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700474#ifdef CONFIG_WNM
475 wnm_deallocate_memory(wpa_s);
476#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700477
478 ext_password_deinit(wpa_s->ext_pw);
479 wpa_s->ext_pw = NULL;
480
481 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700482
483 os_free(wpa_s->last_scan_res);
484 wpa_s->last_scan_res = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700485}
486
487
488/**
489 * wpa_clear_keys - Clear keys configured for the driver
490 * @wpa_s: Pointer to wpa_supplicant data
491 * @addr: Previously used BSSID or %NULL if not available
492 *
493 * This function clears the encryption keys that has been previously configured
494 * for the driver.
495 */
496void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
497{
498 if (wpa_s->keys_cleared) {
499 /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
500 * timing issues with keys being cleared just before new keys
501 * are set or just after association or something similar. This
502 * shows up in group key handshake failing often because of the
503 * client not receiving the first encrypted packets correctly.
504 * Skipping some of the extra key clearing steps seems to help
505 * in completing group key handshake more reliably. */
506 wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
507 "skip key clearing");
508 return;
509 }
510
511 /* MLME-DELETEKEYS.request */
512 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
513 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
514 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
515 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
516#ifdef CONFIG_IEEE80211W
517 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
518 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
519#endif /* CONFIG_IEEE80211W */
520 if (addr) {
521 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
522 0);
523 /* MLME-SETPROTECTION.request(None) */
524 wpa_drv_mlme_setprotection(
525 wpa_s, addr,
526 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
527 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
528 }
529 wpa_s->keys_cleared = 1;
530}
531
532
533/**
534 * wpa_supplicant_state_txt - Get the connection state name as a text string
535 * @state: State (wpa_state; WPA_*)
536 * Returns: The state name as a printable text string
537 */
538const char * wpa_supplicant_state_txt(enum wpa_states state)
539{
540 switch (state) {
541 case WPA_DISCONNECTED:
542 return "DISCONNECTED";
543 case WPA_INACTIVE:
544 return "INACTIVE";
545 case WPA_INTERFACE_DISABLED:
546 return "INTERFACE_DISABLED";
547 case WPA_SCANNING:
548 return "SCANNING";
549 case WPA_AUTHENTICATING:
550 return "AUTHENTICATING";
551 case WPA_ASSOCIATING:
552 return "ASSOCIATING";
553 case WPA_ASSOCIATED:
554 return "ASSOCIATED";
555 case WPA_4WAY_HANDSHAKE:
556 return "4WAY_HANDSHAKE";
557 case WPA_GROUP_HANDSHAKE:
558 return "GROUP_HANDSHAKE";
559 case WPA_COMPLETED:
560 return "COMPLETED";
561 default:
562 return "UNKNOWN";
563 }
564}
565
566
567#ifdef CONFIG_BGSCAN
568
569static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
570{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800571 if (wpas_driver_bss_selection(wpa_s))
572 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
574 return;
575
576 bgscan_deinit(wpa_s);
577 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
578 if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
579 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
580 "bgscan");
581 /*
582 * Live without bgscan; it is only used as a roaming
583 * optimization, so the initial connection is not
584 * affected.
585 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700586 } else {
587 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700589 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
590 0);
591 if (scan_res) {
592 bgscan_notify_scan(wpa_s, scan_res);
593 wpa_scan_results_free(scan_res);
594 }
595 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 } else
597 wpa_s->bgscan_ssid = NULL;
598}
599
600
601static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
602{
603 if (wpa_s->bgscan_ssid != NULL) {
604 bgscan_deinit(wpa_s);
605 wpa_s->bgscan_ssid = NULL;
606 }
607}
608
609#endif /* CONFIG_BGSCAN */
610
611
Dmitry Shmidt04949592012-07-19 12:16:46 -0700612static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
613{
614 if (autoscan_init(wpa_s, 0))
615 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
616}
617
618
619static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
620{
621 autoscan_deinit(wpa_s);
622}
623
624
625void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
626{
627 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
628 wpa_s->wpa_state == WPA_SCANNING) {
629 autoscan_deinit(wpa_s);
630 wpa_supplicant_start_autoscan(wpa_s);
631 }
632}
633
634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700635/**
636 * wpa_supplicant_set_state - Set current connection state
637 * @wpa_s: Pointer to wpa_supplicant data
638 * @state: The new connection state
639 *
640 * This function is called whenever the connection state changes, e.g.,
641 * association is completed for WPA/WPA2 4-Way Handshake is started.
642 */
643void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
644 enum wpa_states state)
645{
646 enum wpa_states old_state = wpa_s->wpa_state;
647
648 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
649 wpa_supplicant_state_txt(wpa_s->wpa_state),
650 wpa_supplicant_state_txt(state));
651
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700652#ifdef ANDROID_P2P
Irfan Sheriff7db4ef72012-06-18 09:39:07 -0700653 if(state == WPA_ASSOCIATED && wpa_s->current_ssid) {
654 wpa_s->current_ssid->assoc_retry = 0;
655 }
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700656#endif /* ANDROID_P2P */
657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 if (state != WPA_SCANNING)
659 wpa_supplicant_notify_scanning(wpa_s, 0);
660
661 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700663#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800665 MACSTR " completed (auth) [id=%d id_str=%s]",
666 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667 ssid ? ssid->id : -1,
668 ssid && ssid->id_str ? ssid->id_str : "");
669#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800671 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673 wpa_drv_set_operstate(wpa_s, 1);
674#ifndef IEEE8021X_EAPOL
675 wpa_drv_set_supp_port(wpa_s, 1);
676#endif /* IEEE8021X_EAPOL */
677 wpa_s->after_wps = 0;
678#ifdef CONFIG_P2P
679 wpas_p2p_completed(wpa_s);
680#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700681
682 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
684 state == WPA_ASSOCIATED) {
685 wpa_s->new_connection = 1;
686 wpa_drv_set_operstate(wpa_s, 0);
687#ifndef IEEE8021X_EAPOL
688 wpa_drv_set_supp_port(wpa_s, 0);
689#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700690 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 }
692 wpa_s->wpa_state = state;
693
694#ifdef CONFIG_BGSCAN
695 if (state == WPA_COMPLETED)
696 wpa_supplicant_start_bgscan(wpa_s);
697 else
698 wpa_supplicant_stop_bgscan(wpa_s);
699#endif /* CONFIG_BGSCAN */
700
Dmitry Shmidt04949592012-07-19 12:16:46 -0700701 if (state == WPA_AUTHENTICATING)
702 wpa_supplicant_stop_autoscan(wpa_s);
703
704 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
705 wpa_supplicant_start_autoscan(wpa_s);
706
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 if (wpa_s->wpa_state != old_state) {
708 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
709
710 if (wpa_s->wpa_state == WPA_COMPLETED ||
711 old_state == WPA_COMPLETED)
712 wpas_notify_auth_changed(wpa_s);
713 }
714}
715
716
717void wpa_supplicant_terminate_proc(struct wpa_global *global)
718{
719 int pending = 0;
720#ifdef CONFIG_WPS
721 struct wpa_supplicant *wpa_s = global->ifaces;
722 while (wpa_s) {
723 if (wpas_wps_terminate_pending(wpa_s) == 1)
724 pending = 1;
725 wpa_s = wpa_s->next;
726 }
727#endif /* CONFIG_WPS */
728 if (pending)
729 return;
730 eloop_terminate();
731}
732
733
734static void wpa_supplicant_terminate(int sig, void *signal_ctx)
735{
736 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737 wpa_supplicant_terminate_proc(global);
738}
739
740
741void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
742{
743 enum wpa_states old_state = wpa_s->wpa_state;
744
745 wpa_s->pairwise_cipher = 0;
746 wpa_s->group_cipher = 0;
747 wpa_s->mgmt_group_cipher = 0;
748 wpa_s->key_mgmt = 0;
749 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700750 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751
752 if (wpa_s->wpa_state != old_state)
753 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
754}
755
756
757/**
758 * wpa_supplicant_reload_configuration - Reload configuration data
759 * @wpa_s: Pointer to wpa_supplicant data
760 * Returns: 0 on success or -1 if configuration parsing failed
761 *
762 * This function can be used to request that the configuration data is reloaded
763 * (e.g., after configuration file change). This function is reloading
764 * configuration only for one interface, so this may need to be called multiple
765 * times if %wpa_supplicant is controlling multiple interfaces and all
766 * interfaces need reconfiguration.
767 */
768int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
769{
770 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 int reconf_ctrl;
772 int old_ap_scan;
773
774 if (wpa_s->confname == NULL)
775 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700776 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 if (conf == NULL) {
778 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
779 "file '%s' - exiting", wpa_s->confname);
780 return -1;
781 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700782 wpa_config_read(wpa_s->confanother, conf);
783
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 conf->changed_parameters = (unsigned int) -1;
785
786 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
787 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
788 os_strcmp(conf->ctrl_interface,
789 wpa_s->conf->ctrl_interface) != 0);
790
791 if (reconf_ctrl && wpa_s->ctrl_iface) {
792 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
793 wpa_s->ctrl_iface = NULL;
794 }
795
796 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800797 if (wpa_s->current_ssid) {
798 wpa_supplicant_deauthenticate(wpa_s,
799 WLAN_REASON_DEAUTH_LEAVING);
800 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801
802 /*
803 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
804 * pkcs11_engine_path, pkcs11_module_path.
805 */
806 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
807 /*
808 * Clear forced success to clear EAP state for next
809 * authentication.
810 */
811 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
812 }
813 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
814 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800815 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700816 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
817 rsn_preauth_deinit(wpa_s->wpa);
818
819 old_ap_scan = wpa_s->conf->ap_scan;
820 wpa_config_free(wpa_s->conf);
821 wpa_s->conf = conf;
822 if (old_ap_scan != wpa_s->conf->ap_scan)
823 wpas_notify_ap_scan_changed(wpa_s);
824
825 if (reconf_ctrl)
826 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
827
828 wpa_supplicant_update_config(wpa_s);
829
830 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700831 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 wpa_s->reassociate = 1;
833 wpa_supplicant_req_scan(wpa_s, 0, 0);
834 }
835 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
836 return 0;
837}
838
839
840static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
841{
842 struct wpa_global *global = signal_ctx;
843 struct wpa_supplicant *wpa_s;
844 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
845 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
846 sig);
847 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
848 wpa_supplicant_terminate_proc(global);
849 }
850 }
851}
852
853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
855{
856 switch (key_mgmt) {
857 case WPA_KEY_MGMT_NONE:
858 return KEY_MGMT_NONE;
859 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
860 return KEY_MGMT_802_1X_NO_WPA;
861 case WPA_KEY_MGMT_IEEE8021X:
862 return KEY_MGMT_802_1X;
863 case WPA_KEY_MGMT_WPA_NONE:
864 return KEY_MGMT_WPA_NONE;
865 case WPA_KEY_MGMT_FT_IEEE8021X:
866 return KEY_MGMT_FT_802_1X;
867 case WPA_KEY_MGMT_FT_PSK:
868 return KEY_MGMT_FT_PSK;
869 case WPA_KEY_MGMT_IEEE8021X_SHA256:
870 return KEY_MGMT_802_1X_SHA256;
871 case WPA_KEY_MGMT_PSK_SHA256:
872 return KEY_MGMT_PSK_SHA256;
873 case WPA_KEY_MGMT_WPS:
874 return KEY_MGMT_WPS;
875 case WPA_KEY_MGMT_PSK:
876 default:
877 return KEY_MGMT_PSK;
878 }
879}
880
881
882static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
883 struct wpa_ssid *ssid,
884 struct wpa_ie_data *ie)
885{
886 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
887 if (ret) {
888 if (ret == -2) {
889 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
890 "from association info");
891 }
892 return -1;
893 }
894
895 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
896 "cipher suites");
897 if (!(ie->group_cipher & ssid->group_cipher)) {
898 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
899 "cipher 0x%x (mask 0x%x) - reject",
900 ie->group_cipher, ssid->group_cipher);
901 return -1;
902 }
903 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
904 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
905 "cipher 0x%x (mask 0x%x) - reject",
906 ie->pairwise_cipher, ssid->pairwise_cipher);
907 return -1;
908 }
909 if (!(ie->key_mgmt & ssid->key_mgmt)) {
910 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
911 "management 0x%x (mask 0x%x) - reject",
912 ie->key_mgmt, ssid->key_mgmt);
913 return -1;
914 }
915
916#ifdef CONFIG_IEEE80211W
917 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800918 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
919 wpa_s->conf->pmf : ssid->ieee80211w) ==
920 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700921 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
922 "that does not support management frame protection - "
923 "reject");
924 return -1;
925 }
926#endif /* CONFIG_IEEE80211W */
927
928 return 0;
929}
930
931
932/**
933 * wpa_supplicant_set_suites - Set authentication and encryption parameters
934 * @wpa_s: Pointer to wpa_supplicant data
935 * @bss: Scan results for the selected BSS, or %NULL if not available
936 * @ssid: Configuration data for the selected network
937 * @wpa_ie: Buffer for the WPA/RSN IE
938 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
939 * used buffer length in case the functions returns success.
940 * Returns: 0 on success or -1 on failure
941 *
942 * This function is used to configure authentication and encryption parameters
943 * based on the network configuration and scan result for the selected BSS (if
944 * available).
945 */
946int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
947 struct wpa_bss *bss, struct wpa_ssid *ssid,
948 u8 *wpa_ie, size_t *wpa_ie_len)
949{
950 struct wpa_ie_data ie;
951 int sel, proto;
952 const u8 *bss_wpa, *bss_rsn;
953
954 if (bss) {
955 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
956 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
957 } else
958 bss_wpa = bss_rsn = NULL;
959
960 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
961 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
962 (ie.group_cipher & ssid->group_cipher) &&
963 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
964 (ie.key_mgmt & ssid->key_mgmt)) {
965 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
966 proto = WPA_PROTO_RSN;
967 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
968 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
969 (ie.group_cipher & ssid->group_cipher) &&
970 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
971 (ie.key_mgmt & ssid->key_mgmt)) {
972 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
973 proto = WPA_PROTO_WPA;
974 } else if (bss) {
975 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
976 return -1;
977 } else {
978 if (ssid->proto & WPA_PROTO_RSN)
979 proto = WPA_PROTO_RSN;
980 else
981 proto = WPA_PROTO_WPA;
982 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
983 os_memset(&ie, 0, sizeof(ie));
984 ie.group_cipher = ssid->group_cipher;
985 ie.pairwise_cipher = ssid->pairwise_cipher;
986 ie.key_mgmt = ssid->key_mgmt;
987#ifdef CONFIG_IEEE80211W
988 ie.mgmt_group_cipher =
989 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
990 WPA_CIPHER_AES_128_CMAC : 0;
991#endif /* CONFIG_IEEE80211W */
992 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
993 "based on configuration");
994 } else
995 proto = ie.proto;
996 }
997
998 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
999 "pairwise %d key_mgmt %d proto %d",
1000 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1001#ifdef CONFIG_IEEE80211W
1002 if (ssid->ieee80211w) {
1003 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1004 ie.mgmt_group_cipher);
1005 }
1006#endif /* CONFIG_IEEE80211W */
1007
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001008 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1010 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
1011 !!(ssid->proto & WPA_PROTO_RSN));
1012
1013 if (bss || !wpa_s->ap_ies_from_associnfo) {
1014 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1015 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1016 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1017 bss_rsn ? 2 + bss_rsn[1] : 0))
1018 return -1;
1019 }
1020
1021 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001022 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1023 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001024 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1025 "cipher");
1026 return -1;
1027 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001028 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1029 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030
1031 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001032 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1033 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1035 "cipher");
1036 return -1;
1037 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001038 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1039 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001040
1041 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001042#ifdef CONFIG_SAE
1043 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1044 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1045#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001046 if (0) {
1047#ifdef CONFIG_IEEE80211R
1048 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1049 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1050 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1051 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1052 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1053 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1054#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001055#ifdef CONFIG_SAE
1056 } else if (sel & WPA_KEY_MGMT_SAE) {
1057 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1058 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1059 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1060 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1061 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1062#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063#ifdef CONFIG_IEEE80211W
1064 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1065 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1066 wpa_dbg(wpa_s, MSG_DEBUG,
1067 "WPA: using KEY_MGMT 802.1X with SHA256");
1068 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1069 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1070 wpa_dbg(wpa_s, MSG_DEBUG,
1071 "WPA: using KEY_MGMT PSK with SHA256");
1072#endif /* CONFIG_IEEE80211W */
1073 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1074 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1075 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1076 } else if (sel & WPA_KEY_MGMT_PSK) {
1077 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1078 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1079 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1080 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1081 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1082 } else {
1083 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1084 "authenticated key management type");
1085 return -1;
1086 }
1087
1088 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1089 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1090 wpa_s->pairwise_cipher);
1091 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1092
1093#ifdef CONFIG_IEEE80211W
1094 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001095 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1096 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1098 sel = 0;
1099 if (sel & WPA_CIPHER_AES_128_CMAC) {
1100 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1101 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1102 "AES-128-CMAC");
1103 } else {
1104 wpa_s->mgmt_group_cipher = 0;
1105 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1106 }
1107 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1108 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001109 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1110 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1111 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001112#endif /* CONFIG_IEEE80211W */
1113
1114 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1115 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1116 return -1;
1117 }
1118
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001119 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001121#ifndef CONFIG_NO_PBKDF2
1122 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1123 ssid->passphrase) {
1124 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001125 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1126 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001127 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1128 psk, PMK_LEN);
1129 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1130 }
1131#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001132#ifdef CONFIG_EXT_PASSWORD
1133 if (ssid->ext_psk) {
1134 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1135 ssid->ext_psk);
1136 char pw_str[64 + 1];
1137 u8 psk[PMK_LEN];
1138
1139 if (pw == NULL) {
1140 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1141 "found from external storage");
1142 return -1;
1143 }
1144
1145 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1146 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1147 "PSK length %d in external storage",
1148 (int) wpabuf_len(pw));
1149 ext_password_free(pw);
1150 return -1;
1151 }
1152
1153 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1154 pw_str[wpabuf_len(pw)] = '\0';
1155
1156#ifndef CONFIG_NO_PBKDF2
1157 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1158 {
1159 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1160 4096, psk, PMK_LEN);
1161 os_memset(pw_str, 0, sizeof(pw_str));
1162 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1163 "external passphrase)",
1164 psk, PMK_LEN);
1165 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1166 } else
1167#endif /* CONFIG_NO_PBKDF2 */
1168 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1169 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1170 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1171 "Invalid PSK hex string");
1172 os_memset(pw_str, 0, sizeof(pw_str));
1173 ext_password_free(pw);
1174 return -1;
1175 }
1176 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1177 } else {
1178 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1179 "PSK available");
1180 os_memset(pw_str, 0, sizeof(pw_str));
1181 ext_password_free(pw);
1182 return -1;
1183 }
1184
1185 os_memset(pw_str, 0, sizeof(pw_str));
1186 ext_password_free(pw);
1187 }
1188#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001189 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001190 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1191
1192 return 0;
1193}
1194
1195
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001196static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1197{
1198 *pos = 0x00;
1199
1200 switch (idx) {
1201 case 0: /* Bits 0-7 */
1202 break;
1203 case 1: /* Bits 8-15 */
1204 break;
1205 case 2: /* Bits 16-23 */
1206#ifdef CONFIG_WNM
1207 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1208 *pos |= 0x08; /* Bit 19 - BSS Transition */
1209#endif /* CONFIG_WNM */
1210 break;
1211 case 3: /* Bits 24-31 */
1212#ifdef CONFIG_WNM
1213 *pos |= 0x02; /* Bit 25 - SSID List */
1214#endif /* CONFIG_WNM */
1215#ifdef CONFIG_INTERWORKING
1216 if (wpa_s->conf->interworking)
1217 *pos |= 0x80; /* Bit 31 - Interworking */
1218#endif /* CONFIG_INTERWORKING */
1219 break;
1220 case 4: /* Bits 32-39 */
1221 break;
1222 case 5: /* Bits 40-47 */
1223 break;
1224 case 6: /* Bits 48-55 */
1225 break;
1226 }
1227}
1228
1229
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001230int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1231{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001232 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001233 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001234
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001235 if (len < wpa_s->extended_capa_len)
1236 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001237
1238 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001239 *pos++ = len;
1240 for (i = 0; i < len; i++, pos++) {
1241 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001242
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001243 if (i < wpa_s->extended_capa_len) {
1244 *pos &= ~wpa_s->extended_capa_mask[i];
1245 *pos |= wpa_s->extended_capa[i];
1246 }
1247 }
1248
1249 while (len > 0 && buf[1 + len] == 0) {
1250 len--;
1251 buf[1] = len;
1252 }
1253 if (len == 0)
1254 return 0;
1255
1256 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001257}
1258
1259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001260/**
1261 * wpa_supplicant_associate - Request association
1262 * @wpa_s: Pointer to wpa_supplicant data
1263 * @bss: Scan results for the selected BSS, or %NULL if not available
1264 * @ssid: Configuration data for the selected network
1265 *
1266 * This function is used to request %wpa_supplicant to associate with a BSS.
1267 */
1268void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1269 struct wpa_bss *bss, struct wpa_ssid *ssid)
1270{
1271 u8 wpa_ie[200];
1272 size_t wpa_ie_len;
1273 int use_crypt, ret, i, bssid_changed;
1274 int algs = WPA_AUTH_ALG_OPEN;
1275 enum wpa_cipher cipher_pairwise, cipher_group;
1276 struct wpa_driver_associate_params params;
1277 int wep_keys_set = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001278 int assoc_failed = 0;
1279 struct wpa_ssid *old_ssid;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001280 u8 ext_capab[10];
1281 int ext_capab_len;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001282#ifdef CONFIG_HT_OVERRIDES
1283 struct ieee80211_ht_capabilities htcaps;
1284 struct ieee80211_ht_capabilities htcaps_mask;
1285#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001286
1287#ifdef CONFIG_IBSS_RSN
1288 ibss_rsn_deinit(wpa_s->ibss_rsn);
1289 wpa_s->ibss_rsn = NULL;
1290#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001291#ifdef ANDROID_P2P
1292 int freq = 0;
1293#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001294
1295 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1296 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1297#ifdef CONFIG_AP
1298 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1299 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1300 "mode");
1301 return;
1302 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001303 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1304 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1305 return;
1306 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 wpa_s->current_bss = bss;
1308#else /* CONFIG_AP */
1309 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1310 "the build");
1311#endif /* CONFIG_AP */
1312 return;
1313 }
1314
1315#ifdef CONFIG_TDLS
1316 if (bss)
1317 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1318 bss->ie_len);
1319#endif /* CONFIG_TDLS */
1320
1321 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1322 ssid->mode == IEEE80211_MODE_INFRA) {
1323 sme_authenticate(wpa_s, bss, ssid);
1324 return;
1325 }
1326
1327 os_memset(&params, 0, sizeof(params));
1328 wpa_s->reassociate = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001329 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330#ifdef CONFIG_IEEE80211R
1331 const u8 *ie, *md = NULL;
1332#endif /* CONFIG_IEEE80211R */
1333 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1334 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1335 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1336 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1337 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1338 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1339 if (bssid_changed)
1340 wpas_notify_bssid_changed(wpa_s);
1341#ifdef CONFIG_IEEE80211R
1342 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1343 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1344 md = ie + 2;
1345 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1346 if (md) {
1347 /* Prepare for the next transition */
1348 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1349 }
1350#endif /* CONFIG_IEEE80211R */
1351#ifdef CONFIG_WPS
1352 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1353 wpa_s->conf->ap_scan == 2 &&
1354 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1355 /* Use ap_scan==1 style network selection to find the network
1356 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001357 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001358 wpa_s->reassociate = 1;
1359 wpa_supplicant_req_scan(wpa_s, 0, 0);
1360 return;
1361#endif /* CONFIG_WPS */
1362 } else {
1363 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1364 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1365 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1366 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001367 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368 wpa_supplicant_cancel_scan(wpa_s);
1369
1370 /* Starting new association, so clear the possibly used WPA IE from the
1371 * previous association. */
1372 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1373
1374#ifdef IEEE8021X_EAPOL
1375 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1376 if (ssid->leap) {
1377 if (ssid->non_leap == 0)
1378 algs = WPA_AUTH_ALG_LEAP;
1379 else
1380 algs |= WPA_AUTH_ALG_LEAP;
1381 }
1382 }
1383#endif /* IEEE8021X_EAPOL */
1384 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1385 if (ssid->auth_alg) {
1386 algs = ssid->auth_alg;
1387 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1388 "0x%x", algs);
1389 }
1390
1391 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1392 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001393 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001394 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001395 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1396 wpa_s->conf->okc :
1397 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398 (ssid->proto & WPA_PROTO_RSN);
1399 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001400 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1402 wpa_ie_len = sizeof(wpa_ie);
1403 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1404 wpa_ie, &wpa_ie_len)) {
1405 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1406 "key management and encryption suites");
1407 return;
1408 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001409 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1410 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1411 /*
1412 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1413 * use non-WPA since the scan results did not indicate that the
1414 * AP is using WPA or WPA2.
1415 */
1416 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1417 wpa_ie_len = 0;
1418 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001419 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420 wpa_ie_len = sizeof(wpa_ie);
1421 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1422 wpa_ie, &wpa_ie_len)) {
1423 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1424 "key management and encryption suites (no "
1425 "scan results)");
1426 return;
1427 }
1428#ifdef CONFIG_WPS
1429 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1430 struct wpabuf *wps_ie;
1431 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1432 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1433 wpa_ie_len = wpabuf_len(wps_ie);
1434 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1435 } else
1436 wpa_ie_len = 0;
1437 wpabuf_free(wps_ie);
1438 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1439 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1440 params.wps = WPS_MODE_PRIVACY;
1441 else
1442 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001443 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001444#endif /* CONFIG_WPS */
1445 } else {
1446 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1447 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001448 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001449 }
1450
1451#ifdef CONFIG_P2P
1452 if (wpa_s->global->p2p) {
1453 u8 *pos;
1454 size_t len;
1455 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001456 pos = wpa_ie + wpa_ie_len;
1457 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001458 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1459 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001460 if (res >= 0)
1461 wpa_ie_len += res;
1462 }
1463
1464 wpa_s->cross_connect_disallowed = 0;
1465 if (bss) {
1466 struct wpabuf *p2p;
1467 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1468 if (p2p) {
1469 wpa_s->cross_connect_disallowed =
1470 p2p_get_cross_connect_disallowed(p2p);
1471 wpabuf_free(p2p);
1472 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1473 "connection",
1474 wpa_s->cross_connect_disallowed ?
1475 "disallows" : "allows");
1476 }
1477 }
1478#endif /* CONFIG_P2P */
1479
Dmitry Shmidt04949592012-07-19 12:16:46 -07001480#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001481 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001482 struct wpabuf *hs20;
1483 hs20 = wpabuf_alloc(20);
1484 if (hs20) {
1485 wpas_hs20_add_indication(hs20);
1486 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1487 wpabuf_len(hs20));
1488 wpa_ie_len += wpabuf_len(hs20);
1489 wpabuf_free(hs20);
1490 }
1491 }
1492#endif /* CONFIG_HS20 */
1493
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001494 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1495 if (ext_capab_len > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001496 u8 *pos = wpa_ie;
1497 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1498 pos += 2 + pos[1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001499 os_memmove(pos + ext_capab_len, pos,
1500 wpa_ie_len - (pos - wpa_ie));
1501 wpa_ie_len += ext_capab_len;
1502 os_memcpy(pos, ext_capab, ext_capab_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001503 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001504
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1506 use_crypt = 1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001507 cipher_pairwise = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
1508 cipher_group = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1510 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1511 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1512 use_crypt = 0;
1513 if (wpa_set_wep_keys(wpa_s, ssid)) {
1514 use_crypt = 1;
1515 wep_keys_set = 1;
1516 }
1517 }
1518 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1519 use_crypt = 0;
1520
1521#ifdef IEEE8021X_EAPOL
1522 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1523 if ((ssid->eapol_flags &
1524 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1525 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1526 !wep_keys_set) {
1527 use_crypt = 0;
1528 } else {
1529 /* Assume that dynamic WEP-104 keys will be used and
1530 * set cipher suites in order for drivers to expect
1531 * encryption. */
1532 cipher_pairwise = cipher_group = CIPHER_WEP104;
1533 }
1534 }
1535#endif /* IEEE8021X_EAPOL */
1536
1537 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1538 /* Set the key before (and later after) association */
1539 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1540 }
1541
1542 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1543 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001544 params.ssid = bss->ssid;
1545 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001546 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1547 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1548 MACSTR " freq=%u MHz based on scan results "
1549 "(bssid_set=%d)",
1550 MAC2STR(bss->bssid), bss->freq,
1551 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001552 params.bssid = bss->bssid;
1553 params.freq = bss->freq;
1554 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001555 } else {
1556 params.ssid = ssid->ssid;
1557 params.ssid_len = ssid->ssid_len;
1558 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001559
1560 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1561 wpa_s->conf->ap_scan == 2) {
1562 params.bssid = ssid->bssid;
1563 params.fixed_bssid = 1;
1564 }
1565
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001566 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1567 params.freq == 0)
1568 params.freq = ssid->frequency; /* Initial channel for IBSS */
1569 params.wpa_ie = wpa_ie;
1570 params.wpa_ie_len = wpa_ie_len;
1571 params.pairwise_suite = cipher_pairwise;
1572 params.group_suite = cipher_group;
1573 params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001574 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 params.auth_alg = algs;
1576 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001577 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001578 for (i = 0; i < NUM_WEP_KEYS; i++) {
1579 if (ssid->wep_key_len[i])
1580 params.wep_key[i] = ssid->wep_key[i];
1581 params.wep_key_len[i] = ssid->wep_key_len[i];
1582 }
1583 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1584
1585 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1586 (params.key_mgmt_suite == KEY_MGMT_PSK ||
1587 params.key_mgmt_suite == KEY_MGMT_FT_PSK)) {
1588 params.passphrase = ssid->passphrase;
1589 if (ssid->psk_set)
1590 params.psk = ssid->psk;
1591 }
1592
1593 params.drop_unencrypted = use_crypt;
1594
1595#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001596 params.mgmt_frame_protection =
1597 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1598 wpa_s->conf->pmf : ssid->ieee80211w;
1599 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1601 struct wpa_ie_data ie;
1602 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1603 ie.capabilities &
1604 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1605 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1606 "MFP: require MFP");
1607 params.mgmt_frame_protection =
1608 MGMT_FRAME_PROTECTION_REQUIRED;
1609 }
1610 }
1611#endif /* CONFIG_IEEE80211W */
1612
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001613 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614
1615 if (wpa_s->parent->set_sta_uapsd)
1616 params.uapsd = wpa_s->parent->sta_uapsd;
1617 else
1618 params.uapsd = -1;
1619
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001620#ifdef CONFIG_HT_OVERRIDES
1621 os_memset(&htcaps, 0, sizeof(htcaps));
1622 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1623 params.htcaps = (u8 *) &htcaps;
1624 params.htcaps_mask = (u8 *) &htcaps_mask;
1625 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1626#endif /* CONFIG_HT_OVERRIDES */
1627
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001628#ifdef ANDROID_P2P
1629 /* If multichannel concurrency is not supported, check for any frequency
1630 * conflict and take appropriate action.
1631 */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001632 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
1633 ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
1634 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001635 , freq, params.freq);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001636 if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07001637 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001638 }
1639#endif
1640 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 if (ret < 0) {
1642 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1643 "failed");
1644 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1645 /*
1646 * The driver is known to mean what is saying, so we
1647 * can stop right here; the association will not
1648 * succeed.
1649 */
1650 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001651 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1653 return;
1654 }
1655 /* try to continue anyway; new association will be tried again
1656 * after timeout */
1657 assoc_failed = 1;
1658 }
1659
1660 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1661 /* Set the key after the association just in case association
1662 * cleared the previously configured key. */
1663 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1664 /* No need to timeout authentication since there is no key
1665 * management. */
1666 wpa_supplicant_cancel_auth_timeout(wpa_s);
1667 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1668#ifdef CONFIG_IBSS_RSN
1669 } else if (ssid->mode == WPAS_MODE_IBSS &&
1670 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1671 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1672 /*
1673 * RSN IBSS authentication is per-STA and we can disable the
1674 * per-BSSID authentication.
1675 */
1676 wpa_supplicant_cancel_auth_timeout(wpa_s);
1677#endif /* CONFIG_IBSS_RSN */
1678 } else {
1679 /* Timeout for IEEE 802.11 authentication and association */
1680 int timeout = 60;
1681
1682 if (assoc_failed) {
1683 /* give IBSS a bit more time */
1684 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1685 } else if (wpa_s->conf->ap_scan == 1) {
1686 /* give IBSS a bit more time */
1687 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1688 }
1689 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1690 }
1691
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001692 if (wep_keys_set &&
1693 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001694 /* Set static WEP keys again */
1695 wpa_set_wep_keys(wpa_s, ssid);
1696 }
1697
1698 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1699 /*
1700 * Do not allow EAP session resumption between different
1701 * network configurations.
1702 */
1703 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1704 }
1705 old_ssid = wpa_s->current_ssid;
1706 wpa_s->current_ssid = ssid;
1707 wpa_s->current_bss = bss;
1708 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1709 wpa_supplicant_initiate_eapol(wpa_s);
1710 if (old_ssid != wpa_s->current_ssid)
1711 wpas_notify_network_changed(wpa_s);
1712}
1713
1714
1715static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1716 const u8 *addr)
1717{
1718 struct wpa_ssid *old_ssid;
1719
1720 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001721 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001722 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 wpa_sm_set_config(wpa_s->wpa, NULL);
1724 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1725 if (old_ssid != wpa_s->current_ssid)
1726 wpas_notify_network_changed(wpa_s);
1727 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1728}
1729
1730
1731/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1733 * @wpa_s: Pointer to wpa_supplicant data
1734 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1735 *
1736 * This function is used to request %wpa_supplicant to deauthenticate from the
1737 * current AP.
1738 */
1739void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1740 int reason_code)
1741{
1742 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001743 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001744 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001746 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1747 " pending_bssid=" MACSTR " reason=%d state=%s",
1748 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1749 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1750
1751 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001753 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1754 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1755 wpa_s->wpa_state == WPA_ASSOCIATING))
1756 addr = wpa_s->pending_bssid;
1757 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1758 /*
1759 * When using driver-based BSS selection, we may not know the
1760 * BSSID with which we are currently trying to associate. We
1761 * need to notify the driver of this disconnection even in such
1762 * a case, so use the all zeros address here.
1763 */
1764 addr = wpa_s->bssid;
1765 zero_addr = 1;
1766 }
1767
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001768#ifdef CONFIG_TDLS
1769 wpa_tdls_teardown_peers(wpa_s->wpa);
1770#endif /* CONFIG_TDLS */
1771
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001772 if (addr) {
1773 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001774 os_memset(&event, 0, sizeof(event));
1775 event.deauth_info.reason_code = (u16) reason_code;
1776 event.deauth_info.locally_generated = 1;
1777 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001778 if (zero_addr)
1779 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780 }
1781
1782 wpa_supplicant_clear_connection(wpa_s, addr);
1783}
1784
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001785static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1786 struct wpa_ssid *ssid)
1787{
1788 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1789 return;
1790
1791 ssid->disabled = 0;
1792 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1793 wpas_notify_network_enabled_changed(wpa_s, ssid);
1794
1795 /*
1796 * Try to reassociate since there is no current configuration and a new
1797 * network was made available.
1798 */
1799 if (!wpa_s->current_ssid)
1800 wpa_s->reassociate = 1;
1801}
1802
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001803
1804/**
1805 * wpa_supplicant_enable_network - Mark a configured network as enabled
1806 * @wpa_s: wpa_supplicant structure for a network interface
1807 * @ssid: wpa_ssid structure for a configured network or %NULL
1808 *
1809 * Enables the specified network or all networks if no network specified.
1810 */
1811void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1812 struct wpa_ssid *ssid)
1813{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001814 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001815 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1816 wpa_supplicant_enable_one_network(wpa_s, ssid);
1817 } else
1818 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001820 if (wpa_s->reassociate) {
1821 if (wpa_s->sched_scanning) {
1822 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1823 "new network to scan filters");
1824 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001825 }
1826
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001827 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828 }
1829}
1830
1831
1832/**
1833 * wpa_supplicant_disable_network - Mark a configured network as disabled
1834 * @wpa_s: wpa_supplicant structure for a network interface
1835 * @ssid: wpa_ssid structure for a configured network or %NULL
1836 *
1837 * Disables the specified network or all networks if no network specified.
1838 */
1839void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1840 struct wpa_ssid *ssid)
1841{
1842 struct wpa_ssid *other_ssid;
1843 int was_disabled;
1844
1845 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001846 if (wpa_s->sched_scanning)
1847 wpa_supplicant_cancel_sched_scan(wpa_s);
1848
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1850 other_ssid = other_ssid->next) {
1851 was_disabled = other_ssid->disabled;
1852 if (was_disabled == 2)
1853 continue; /* do not change persistent P2P group
1854 * data */
1855
1856 other_ssid->disabled = 1;
1857
1858 if (was_disabled != other_ssid->disabled)
1859 wpas_notify_network_enabled_changed(
1860 wpa_s, other_ssid);
1861 }
1862 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001863 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1865 } else if (ssid->disabled != 2) {
1866 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001867 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1869
1870 was_disabled = ssid->disabled;
1871
1872 ssid->disabled = 1;
1873
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001874 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001875 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001876 if (wpa_s->sched_scanning) {
1877 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1878 "to remove network from filters");
1879 wpa_supplicant_cancel_sched_scan(wpa_s);
1880 wpa_supplicant_req_scan(wpa_s, 0, 0);
1881 }
1882 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001883 }
1884}
1885
1886
1887/**
1888 * wpa_supplicant_select_network - Attempt association with a network
1889 * @wpa_s: wpa_supplicant structure for a network interface
1890 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1891 */
1892void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1893 struct wpa_ssid *ssid)
1894{
1895
1896 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001897 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001899 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001900 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001902 disconnected = 1;
1903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001905 if (ssid)
1906 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1907
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001908 /*
1909 * Mark all other networks disabled or mark all networks enabled if no
1910 * network specified.
1911 */
1912 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1913 other_ssid = other_ssid->next) {
1914 int was_disabled = other_ssid->disabled;
1915 if (was_disabled == 2)
1916 continue; /* do not change persistent P2P group data */
1917
1918 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001919 if (was_disabled && !other_ssid->disabled)
1920 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921
1922 if (was_disabled != other_ssid->disabled)
1923 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1924 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001925
1926 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
1927 /* We are already associated with the selected network */
1928 wpa_printf(MSG_DEBUG, "Already associated with the "
1929 "selected network - do nothing");
1930 return;
1931 }
1932
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001933 if (ssid)
1934 wpa_s->current_ssid = ssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001935 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 wpa_s->disconnected = 0;
1937 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001938
1939 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1940 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941
1942 if (ssid)
1943 wpas_notify_network_selected(wpa_s, ssid);
1944}
1945
1946
1947/**
1948 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
1949 * @wpa_s: wpa_supplicant structure for a network interface
1950 * @ap_scan: AP scan mode
1951 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
1952 *
1953 */
1954int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
1955{
1956
1957 int old_ap_scan;
1958
1959 if (ap_scan < 0 || ap_scan > 2)
1960 return -1;
1961
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001962#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001963 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
1964 wpa_s->wpa_state >= WPA_ASSOCIATING &&
1965 wpa_s->wpa_state < WPA_COMPLETED) {
1966 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
1967 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001968 return 0;
1969 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001970#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001971
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001972 old_ap_scan = wpa_s->conf->ap_scan;
1973 wpa_s->conf->ap_scan = ap_scan;
1974
1975 if (old_ap_scan != wpa_s->conf->ap_scan)
1976 wpas_notify_ap_scan_changed(wpa_s);
1977
1978 return 0;
1979}
1980
1981
1982/**
1983 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
1984 * @wpa_s: wpa_supplicant structure for a network interface
1985 * @expire_age: Expiration age in seconds
1986 * Returns: 0 if succeed or -1 if expire_age has an invalid value
1987 *
1988 */
1989int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
1990 unsigned int bss_expire_age)
1991{
1992 if (bss_expire_age < 10) {
1993 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
1994 bss_expire_age);
1995 return -1;
1996 }
1997 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
1998 bss_expire_age);
1999 wpa_s->conf->bss_expiration_age = bss_expire_age;
2000
2001 return 0;
2002}
2003
2004
2005/**
2006 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2007 * @wpa_s: wpa_supplicant structure for a network interface
2008 * @expire_count: number of scans after which an unseen BSS is reclaimed
2009 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2010 *
2011 */
2012int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2013 unsigned int bss_expire_count)
2014{
2015 if (bss_expire_count < 1) {
2016 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2017 bss_expire_count);
2018 return -1;
2019 }
2020 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2021 bss_expire_count);
2022 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2023
2024 return 0;
2025}
2026
2027
2028/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002029 * wpa_supplicant_set_scan_interval - Set scan interval
2030 * @wpa_s: wpa_supplicant structure for a network interface
2031 * @scan_interval: scan interval in seconds
2032 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2033 *
2034 */
2035int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2036 int scan_interval)
2037{
2038 if (scan_interval < 0) {
2039 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2040 scan_interval);
2041 return -1;
2042 }
2043 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2044 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002045 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002046
2047 return 0;
2048}
2049
2050
2051/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052 * wpa_supplicant_set_debug_params - Set global debug params
2053 * @global: wpa_global structure
2054 * @debug_level: debug level
2055 * @debug_timestamp: determines if show timestamp in debug data
2056 * @debug_show_keys: determines if show keys in debug data
2057 * Returns: 0 if succeed or -1 if debug_level has wrong value
2058 */
2059int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2060 int debug_timestamp, int debug_show_keys)
2061{
2062
2063 int old_level, old_timestamp, old_show_keys;
2064
2065 /* check for allowed debuglevels */
2066 if (debug_level != MSG_EXCESSIVE &&
2067 debug_level != MSG_MSGDUMP &&
2068 debug_level != MSG_DEBUG &&
2069 debug_level != MSG_INFO &&
2070 debug_level != MSG_WARNING &&
2071 debug_level != MSG_ERROR)
2072 return -1;
2073
2074 old_level = wpa_debug_level;
2075 old_timestamp = wpa_debug_timestamp;
2076 old_show_keys = wpa_debug_show_keys;
2077
2078 wpa_debug_level = debug_level;
2079 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2080 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2081
2082 if (wpa_debug_level != old_level)
2083 wpas_notify_debug_level_changed(global);
2084 if (wpa_debug_timestamp != old_timestamp)
2085 wpas_notify_debug_timestamp_changed(global);
2086 if (wpa_debug_show_keys != old_show_keys)
2087 wpas_notify_debug_show_keys_changed(global);
2088
2089 return 0;
2090}
2091
2092
2093/**
2094 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2095 * @wpa_s: Pointer to wpa_supplicant data
2096 * Returns: A pointer to the current network structure or %NULL on failure
2097 */
2098struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2099{
2100 struct wpa_ssid *entry;
2101 u8 ssid[MAX_SSID_LEN];
2102 int res;
2103 size_t ssid_len;
2104 u8 bssid[ETH_ALEN];
2105 int wired;
2106
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002107 res = wpa_drv_get_ssid(wpa_s, ssid);
2108 if (res < 0) {
2109 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2110 "driver");
2111 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002112 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002113 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002114
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002115 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002116 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2117 "driver");
2118 return NULL;
2119 }
2120
2121 wired = wpa_s->conf->ap_scan == 0 &&
2122 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2123
2124 entry = wpa_s->conf->ssid;
2125 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002126 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 ((ssid_len == entry->ssid_len &&
2128 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2129 (!entry->bssid_set ||
2130 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2131 return entry;
2132#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002133 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2135 (entry->ssid == NULL || entry->ssid_len == 0) &&
2136 (!entry->bssid_set ||
2137 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2138 return entry;
2139#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002140
Dmitry Shmidt04949592012-07-19 12:16:46 -07002141 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002142 entry->ssid_len == 0 &&
2143 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2144 return entry;
2145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146 entry = entry->next;
2147 }
2148
2149 return NULL;
2150}
2151
2152
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002153static int select_driver(struct wpa_supplicant *wpa_s, int i)
2154{
2155 struct wpa_global *global = wpa_s->global;
2156
2157 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2158 global->drv_priv[i] = wpa_drivers[i]->global_init();
2159 if (global->drv_priv[i] == NULL) {
2160 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2161 "'%s'", wpa_drivers[i]->name);
2162 return -1;
2163 }
2164 }
2165
2166 wpa_s->driver = wpa_drivers[i];
2167 wpa_s->global_drv_priv = global->drv_priv[i];
2168
2169 return 0;
2170}
2171
2172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002173static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2174 const char *name)
2175{
2176 int i;
2177 size_t len;
2178 const char *pos, *driver = name;
2179
2180 if (wpa_s == NULL)
2181 return -1;
2182
2183 if (wpa_drivers[0] == NULL) {
2184 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2185 "wpa_supplicant");
2186 return -1;
2187 }
2188
2189 if (name == NULL) {
2190 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002191 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192 }
2193
2194 do {
2195 pos = os_strchr(driver, ',');
2196 if (pos)
2197 len = pos - driver;
2198 else
2199 len = os_strlen(driver);
2200
2201 for (i = 0; wpa_drivers[i]; i++) {
2202 if (os_strlen(wpa_drivers[i]->name) == len &&
2203 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002204 0) {
2205 /* First driver that succeeds wins */
2206 if (select_driver(wpa_s, i) == 0)
2207 return 0;
2208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209 }
2210
2211 driver = pos + 1;
2212 } while (pos);
2213
2214 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2215 return -1;
2216}
2217
2218
2219/**
2220 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2221 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2222 * with struct wpa_driver_ops::init()
2223 * @src_addr: Source address of the EAPOL frame
2224 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2225 * @len: Length of the EAPOL data
2226 *
2227 * This function is called for each received EAPOL frame. Most driver
2228 * interfaces rely on more generic OS mechanism for receiving frames through
2229 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2230 * take care of received EAPOL frames and deliver them to the core supplicant
2231 * code by calling this function.
2232 */
2233void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2234 const u8 *buf, size_t len)
2235{
2236 struct wpa_supplicant *wpa_s = ctx;
2237
2238 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2239 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2240
Jouni Malinena05074c2012-12-21 21:35:35 +02002241 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2242 (wpa_s->last_eapol_matches_bssid &&
2243#ifdef CONFIG_AP
2244 !wpa_s->ap_iface &&
2245#endif /* CONFIG_AP */
2246 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002247 /*
2248 * There is possible race condition between receiving the
2249 * association event and the EAPOL frame since they are coming
2250 * through different paths from the driver. In order to avoid
2251 * issues in trying to process the EAPOL frame before receiving
2252 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002253 * the association event is received. This may also be needed in
2254 * driver-based roaming case, so also use src_addr != BSSID as a
2255 * trigger if we have previously confirmed that the
2256 * Authenticator uses BSSID as the src_addr (which is not the
2257 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 */
2259 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002260 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2261 wpa_supplicant_state_txt(wpa_s->wpa_state),
2262 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263 wpabuf_free(wpa_s->pending_eapol_rx);
2264 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2265 if (wpa_s->pending_eapol_rx) {
2266 os_get_time(&wpa_s->pending_eapol_rx_time);
2267 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2268 ETH_ALEN);
2269 }
2270 return;
2271 }
2272
Jouni Malinena05074c2012-12-21 21:35:35 +02002273 wpa_s->last_eapol_matches_bssid =
2274 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276#ifdef CONFIG_AP
2277 if (wpa_s->ap_iface) {
2278 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2279 return;
2280 }
2281#endif /* CONFIG_AP */
2282
2283 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2284 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2285 "no key management is configured");
2286 return;
2287 }
2288
2289 if (wpa_s->eapol_received == 0 &&
2290 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2291 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2292 wpa_s->wpa_state != WPA_COMPLETED) &&
2293 (wpa_s->current_ssid == NULL ||
2294 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2295 /* Timeout for completing IEEE 802.1X and WPA authentication */
2296 wpa_supplicant_req_auth_timeout(
2297 wpa_s,
2298 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2299 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2300 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2301 70 : 10, 0);
2302 }
2303 wpa_s->eapol_received++;
2304
2305 if (wpa_s->countermeasures) {
2306 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2307 "EAPOL packet");
2308 return;
2309 }
2310
2311#ifdef CONFIG_IBSS_RSN
2312 if (wpa_s->current_ssid &&
2313 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2314 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2315 return;
2316 }
2317#endif /* CONFIG_IBSS_RSN */
2318
2319 /* Source address of the incoming EAPOL frame could be compared to the
2320 * current BSSID. However, it is possible that a centralized
2321 * Authenticator could be using another MAC address than the BSSID of
2322 * an AP, so just allow any address to be used for now. The replies are
2323 * still sent to the current BSSID (if available), though. */
2324
2325 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2326 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2327 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2328 return;
2329 wpa_drv_poll(wpa_s);
2330 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2331 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2332 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2333 /*
2334 * Set portValid = TRUE here since we are going to skip 4-way
2335 * handshake processing which would normally set portValid. We
2336 * need this to allow the EAPOL state machines to be completed
2337 * without going through EAPOL-Key handshake.
2338 */
2339 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2340 }
2341}
2342
2343
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002344int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346 if (wpa_s->driver->send_eapol) {
2347 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2348 if (addr)
2349 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2350 } else if (!(wpa_s->drv_flags &
2351 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002352 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2354 wpa_drv_get_mac_addr(wpa_s),
2355 ETH_P_EAPOL,
2356 wpa_supplicant_rx_eapol, wpa_s, 0);
2357 if (wpa_s->l2 == NULL)
2358 return -1;
2359 } else {
2360 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2361 if (addr)
2362 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2363 }
2364
2365 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2366 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2367 return -1;
2368 }
2369
2370 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2371 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002372 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2373
2374 return 0;
2375}
2376
2377
Dmitry Shmidt04949592012-07-19 12:16:46 -07002378static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2379 const u8 *buf, size_t len)
2380{
2381 struct wpa_supplicant *wpa_s = ctx;
2382 const struct l2_ethhdr *eth;
2383
2384 if (len < sizeof(*eth))
2385 return;
2386 eth = (const struct l2_ethhdr *) buf;
2387
2388 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2389 !(eth->h_dest[0] & 0x01)) {
2390 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2391 " (bridge - not for this interface - ignore)",
2392 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2393 return;
2394 }
2395
2396 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2397 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2398 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2399 len - sizeof(*eth));
2400}
2401
2402
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002403/**
2404 * wpa_supplicant_driver_init - Initialize driver interface parameters
2405 * @wpa_s: Pointer to wpa_supplicant data
2406 * Returns: 0 on success, -1 on failure
2407 *
2408 * This function is called to initialize driver interface parameters.
2409 * wpa_drv_init() must have been called before this function to initialize the
2410 * driver interface.
2411 */
2412int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2413{
2414 static int interface_count = 0;
2415
2416 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2417 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418
2419 if (wpa_s->bridge_ifname[0]) {
2420 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2421 "interface '%s'", wpa_s->bridge_ifname);
2422 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2423 wpa_s->own_addr,
2424 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002425 wpa_supplicant_rx_eapol_bridge,
2426 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 if (wpa_s->l2_br == NULL) {
2428 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2429 "connection for the bridge interface '%s'",
2430 wpa_s->bridge_ifname);
2431 return -1;
2432 }
2433 }
2434
2435 wpa_clear_keys(wpa_s, NULL);
2436
2437 /* Make sure that TKIP countermeasures are not left enabled (could
2438 * happen if wpa_supplicant is killed during countermeasures. */
2439 wpa_drv_set_countermeasures(wpa_s, 0);
2440
2441 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2442 wpa_drv_flush_pmkid(wpa_s);
2443
2444 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002445 wpa_s->prev_scan_wildcard = 0;
2446
Dmitry Shmidt04949592012-07-19 12:16:46 -07002447 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002448 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2449 100000))
2450 wpa_supplicant_req_scan(wpa_s, interface_count,
2451 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 interface_count++;
2453 } else
2454 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2455
2456 return 0;
2457}
2458
2459
2460static int wpa_supplicant_daemon(const char *pid_file)
2461{
2462 wpa_printf(MSG_DEBUG, "Daemonize..");
2463 return os_daemonize(pid_file);
2464}
2465
2466
2467static struct wpa_supplicant * wpa_supplicant_alloc(void)
2468{
2469 struct wpa_supplicant *wpa_s;
2470
2471 wpa_s = os_zalloc(sizeof(*wpa_s));
2472 if (wpa_s == NULL)
2473 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002474 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 wpa_s->scan_interval = 5;
2476 wpa_s->new_connection = 1;
2477 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002478 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479
2480 return wpa_s;
2481}
2482
2483
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002484#ifdef CONFIG_HT_OVERRIDES
2485
2486static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2487 struct ieee80211_ht_capabilities *htcaps,
2488 struct ieee80211_ht_capabilities *htcaps_mask,
2489 const char *ht_mcs)
2490{
2491 /* parse ht_mcs into hex array */
2492 int i;
2493 const char *tmp = ht_mcs;
2494 char *end = NULL;
2495
2496 /* If ht_mcs is null, do not set anything */
2497 if (!ht_mcs)
2498 return 0;
2499
2500 /* This is what we are setting in the kernel */
2501 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2502
2503 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2504
2505 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2506 errno = 0;
2507 long v = strtol(tmp, &end, 16);
2508 if (errno == 0) {
2509 wpa_msg(wpa_s, MSG_DEBUG,
2510 "htcap value[%i]: %ld end: %p tmp: %p",
2511 i, v, end, tmp);
2512 if (end == tmp)
2513 break;
2514
2515 htcaps->supported_mcs_set[i] = v;
2516 tmp = end;
2517 } else {
2518 wpa_msg(wpa_s, MSG_ERROR,
2519 "Failed to parse ht-mcs: %s, error: %s\n",
2520 ht_mcs, strerror(errno));
2521 return -1;
2522 }
2523 }
2524
2525 /*
2526 * If we were able to parse any values, then set mask for the MCS set.
2527 */
2528 if (i) {
2529 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2530 IEEE80211_HT_MCS_MASK_LEN - 1);
2531 /* skip the 3 reserved bits */
2532 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2533 0x1f;
2534 }
2535
2536 return 0;
2537}
2538
2539
2540static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2541 struct ieee80211_ht_capabilities *htcaps,
2542 struct ieee80211_ht_capabilities *htcaps_mask,
2543 int disabled)
2544{
2545 u16 msk;
2546
2547 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2548
2549 if (disabled == -1)
2550 return 0;
2551
2552 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2553 htcaps_mask->ht_capabilities_info |= msk;
2554 if (disabled)
2555 htcaps->ht_capabilities_info &= msk;
2556 else
2557 htcaps->ht_capabilities_info |= msk;
2558
2559 return 0;
2560}
2561
2562
2563static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2564 struct ieee80211_ht_capabilities *htcaps,
2565 struct ieee80211_ht_capabilities *htcaps_mask,
2566 int factor)
2567{
2568 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2569
2570 if (factor == -1)
2571 return 0;
2572
2573 if (factor < 0 || factor > 3) {
2574 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2575 "Must be 0-3 or -1", factor);
2576 return -EINVAL;
2577 }
2578
2579 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2580 htcaps->a_mpdu_params &= ~0x3;
2581 htcaps->a_mpdu_params |= factor & 0x3;
2582
2583 return 0;
2584}
2585
2586
2587static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2588 struct ieee80211_ht_capabilities *htcaps,
2589 struct ieee80211_ht_capabilities *htcaps_mask,
2590 int density)
2591{
2592 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2593
2594 if (density == -1)
2595 return 0;
2596
2597 if (density < 0 || density > 7) {
2598 wpa_msg(wpa_s, MSG_ERROR,
2599 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2600 density);
2601 return -EINVAL;
2602 }
2603
2604 htcaps_mask->a_mpdu_params |= 0x1C;
2605 htcaps->a_mpdu_params &= ~(0x1C);
2606 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2607
2608 return 0;
2609}
2610
2611
2612static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2613 struct ieee80211_ht_capabilities *htcaps,
2614 struct ieee80211_ht_capabilities *htcaps_mask,
2615 int disabled)
2616{
2617 /* Masking these out disables HT40 */
2618 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2619 HT_CAP_INFO_SHORT_GI40MHZ);
2620
2621 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2622
2623 if (disabled)
2624 htcaps->ht_capabilities_info &= ~msk;
2625 else
2626 htcaps->ht_capabilities_info |= msk;
2627
2628 htcaps_mask->ht_capabilities_info |= msk;
2629
2630 return 0;
2631}
2632
2633
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002634static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2635 struct ieee80211_ht_capabilities *htcaps,
2636 struct ieee80211_ht_capabilities *htcaps_mask,
2637 int disabled)
2638{
2639 /* Masking these out disables SGI */
2640 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2641 HT_CAP_INFO_SHORT_GI40MHZ);
2642
2643 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2644
2645 if (disabled)
2646 htcaps->ht_capabilities_info &= ~msk;
2647 else
2648 htcaps->ht_capabilities_info |= msk;
2649
2650 htcaps_mask->ht_capabilities_info |= msk;
2651
2652 return 0;
2653}
2654
2655
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002656void wpa_supplicant_apply_ht_overrides(
2657 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2658 struct wpa_driver_associate_params *params)
2659{
2660 struct ieee80211_ht_capabilities *htcaps;
2661 struct ieee80211_ht_capabilities *htcaps_mask;
2662
2663 if (!ssid)
2664 return;
2665
2666 params->disable_ht = ssid->disable_ht;
2667 if (!params->htcaps || !params->htcaps_mask)
2668 return;
2669
2670 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2671 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2672 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2673 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2674 ssid->disable_max_amsdu);
2675 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2676 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2677 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002678 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002679}
2680
2681#endif /* CONFIG_HT_OVERRIDES */
2682
2683
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002684#ifdef CONFIG_VHT_OVERRIDES
2685void wpa_supplicant_apply_vht_overrides(
2686 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2687 struct wpa_driver_associate_params *params)
2688{
2689 struct ieee80211_vht_capabilities *vhtcaps;
2690 struct ieee80211_vht_capabilities *vhtcaps_mask;
2691
2692 if (!ssid)
2693 return;
2694
2695 params->disable_vht = ssid->disable_vht;
2696
2697 vhtcaps = (void *) params->vhtcaps;
2698 vhtcaps_mask = (void *) params->vhtcaps_mask;
2699
2700 if (!vhtcaps || !vhtcaps_mask)
2701 return;
2702
2703 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2704 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2705
2706#define OVERRIDE_MCS(i) \
2707 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2708 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2709 3 << 2 * (i - 1); \
2710 vhtcaps->vht_supported_mcs_set.tx_map |= \
2711 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2712 } \
2713 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2714 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2715 3 << 2 * (i - 1); \
2716 vhtcaps->vht_supported_mcs_set.rx_map |= \
2717 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2718 }
2719
2720 OVERRIDE_MCS(1);
2721 OVERRIDE_MCS(2);
2722 OVERRIDE_MCS(3);
2723 OVERRIDE_MCS(4);
2724 OVERRIDE_MCS(5);
2725 OVERRIDE_MCS(6);
2726 OVERRIDE_MCS(7);
2727 OVERRIDE_MCS(8);
2728}
2729#endif /* CONFIG_VHT_OVERRIDES */
2730
2731
Dmitry Shmidt04949592012-07-19 12:16:46 -07002732static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2733{
2734#ifdef PCSC_FUNCS
2735 size_t len;
2736
2737 if (!wpa_s->conf->pcsc_reader)
2738 return 0;
2739
2740 wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
2741 if (!wpa_s->scard)
2742 return 1;
2743
2744 if (wpa_s->conf->pcsc_pin &&
2745 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2746 scard_deinit(wpa_s->scard);
2747 wpa_s->scard = NULL;
2748 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2749 return -1;
2750 }
2751
2752 len = sizeof(wpa_s->imsi) - 1;
2753 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2754 scard_deinit(wpa_s->scard);
2755 wpa_s->scard = NULL;
2756 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2757 return -1;
2758 }
2759 wpa_s->imsi[len] = '\0';
2760
2761 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2762
2763 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2764 wpa_s->imsi, wpa_s->mnc_len);
2765
2766 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2767 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2768#endif /* PCSC_FUNCS */
2769
2770 return 0;
2771}
2772
2773
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2775{
2776 char *val, *pos;
2777
2778 ext_password_deinit(wpa_s->ext_pw);
2779 wpa_s->ext_pw = NULL;
2780 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2781
2782 if (!wpa_s->conf->ext_password_backend)
2783 return 0;
2784
2785 val = os_strdup(wpa_s->conf->ext_password_backend);
2786 if (val == NULL)
2787 return -1;
2788 pos = os_strchr(val, ':');
2789 if (pos)
2790 *pos++ = '\0';
2791
2792 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2793
2794 wpa_s->ext_pw = ext_password_init(val, pos);
2795 os_free(val);
2796 if (wpa_s->ext_pw == NULL) {
2797 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2798 return -1;
2799 }
2800 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2801
2802 return 0;
2803}
2804
2805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2807 struct wpa_interface *iface)
2808{
2809 const char *ifname, *driver;
2810 struct wpa_driver_capa capa;
2811
2812 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
2813 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2814 iface->confname ? iface->confname : "N/A",
2815 iface->driver ? iface->driver : "default",
2816 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2817 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2818
2819 if (iface->confname) {
2820#ifdef CONFIG_BACKEND_FILE
2821 wpa_s->confname = os_rel2abs_path(iface->confname);
2822 if (wpa_s->confname == NULL) {
2823 wpa_printf(MSG_ERROR, "Failed to get absolute path "
2824 "for configuration file '%s'.",
2825 iface->confname);
2826 return -1;
2827 }
2828 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
2829 iface->confname, wpa_s->confname);
2830#else /* CONFIG_BACKEND_FILE */
2831 wpa_s->confname = os_strdup(iface->confname);
2832#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002833 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834 if (wpa_s->conf == NULL) {
2835 wpa_printf(MSG_ERROR, "Failed to read or parse "
2836 "configuration '%s'.", wpa_s->confname);
2837 return -1;
2838 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002839 wpa_s->confanother = os_rel2abs_path(iface->confanother);
2840 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841
2842 /*
2843 * Override ctrl_interface and driver_param if set on command
2844 * line.
2845 */
2846 if (iface->ctrl_interface) {
2847 os_free(wpa_s->conf->ctrl_interface);
2848 wpa_s->conf->ctrl_interface =
2849 os_strdup(iface->ctrl_interface);
2850 }
2851
2852 if (iface->driver_param) {
2853 os_free(wpa_s->conf->driver_param);
2854 wpa_s->conf->driver_param =
2855 os_strdup(iface->driver_param);
2856 }
2857 } else
2858 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
2859 iface->driver_param);
2860
2861 if (wpa_s->conf == NULL) {
2862 wpa_printf(MSG_ERROR, "\nNo configuration found.");
2863 return -1;
2864 }
2865
2866 if (iface->ifname == NULL) {
2867 wpa_printf(MSG_ERROR, "\nInterface name is required.");
2868 return -1;
2869 }
2870 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
2871 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
2872 iface->ifname);
2873 return -1;
2874 }
2875 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
2876
2877 if (iface->bridge_ifname) {
2878 if (os_strlen(iface->bridge_ifname) >=
2879 sizeof(wpa_s->bridge_ifname)) {
2880 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
2881 "name '%s'.", iface->bridge_ifname);
2882 return -1;
2883 }
2884 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
2885 sizeof(wpa_s->bridge_ifname));
2886 }
2887
2888 /* RSNA Supplicant Key Management - INITIALIZE */
2889 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2890 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2891
2892 /* Initialize driver interface and register driver event handler before
2893 * L2 receive handler so that association events are processed before
2894 * EAPOL-Key packets if both become available for the same select()
2895 * call. */
2896 driver = iface->driver;
2897next_driver:
2898 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2899 return -1;
2900
2901 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2902 if (wpa_s->drv_priv == NULL) {
2903 const char *pos;
2904 pos = driver ? os_strchr(driver, ',') : NULL;
2905 if (pos) {
2906 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2907 "driver interface - try next driver wrapper");
2908 driver = pos + 1;
2909 goto next_driver;
2910 }
2911 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2912 "interface");
2913 return -1;
2914 }
2915 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2916 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2917 "driver_param '%s'", wpa_s->conf->driver_param);
2918 return -1;
2919 }
2920
2921 ifname = wpa_drv_get_ifname(wpa_s);
2922 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2923 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2924 "interface name with '%s'", ifname);
2925 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2926 }
2927
2928 if (wpa_supplicant_init_wpa(wpa_s) < 0)
2929 return -1;
2930
2931 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
2932 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
2933 NULL);
2934 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
2935
2936 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
2937 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
2938 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
2939 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2940 "dot11RSNAConfigPMKLifetime");
2941 return -1;
2942 }
2943
2944 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
2945 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
2946 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
2947 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2948 "dot11RSNAConfigPMKReauthThreshold");
2949 return -1;
2950 }
2951
2952 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
2953 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
2954 wpa_s->conf->dot11RSNAConfigSATimeout)) {
2955 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2956 "dot11RSNAConfigSATimeout");
2957 return -1;
2958 }
2959
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002960 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
2961 &wpa_s->hw.num_modes,
2962 &wpa_s->hw.flags);
2963
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002965 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002966 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002967 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002968 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002969 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002970 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
2971 wpa_s->sched_scan_supported = capa.sched_scan_supported;
2972 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
2974 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002975 wpa_s->extended_capa = capa.extended_capa;
2976 wpa_s->extended_capa_mask = capa.extended_capa_mask;
2977 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002978 }
2979 if (wpa_s->max_remain_on_chan == 0)
2980 wpa_s->max_remain_on_chan = 1000;
2981
2982 if (wpa_supplicant_driver_init(wpa_s) < 0)
2983 return -1;
2984
2985#ifdef CONFIG_TDLS
2986 if (wpa_tdls_init(wpa_s->wpa))
2987 return -1;
2988#endif /* CONFIG_TDLS */
2989
2990 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
2991 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
2992 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
2993 return -1;
2994 }
2995
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996 if (wpas_wps_init(wpa_s))
2997 return -1;
2998
2999 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3000 return -1;
3001 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3002
3003 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3004 if (wpa_s->ctrl_iface == NULL) {
3005 wpa_printf(MSG_ERROR,
3006 "Failed to initialize control interface '%s'.\n"
3007 "You may have another wpa_supplicant process "
3008 "already running or the file was\n"
3009 "left by an unclean termination of wpa_supplicant "
3010 "in which case you will need\n"
3011 "to manually remove this file before starting "
3012 "wpa_supplicant again.\n",
3013 wpa_s->conf->ctrl_interface);
3014 return -1;
3015 }
3016
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003017 wpa_s->gas = gas_query_init(wpa_s);
3018 if (wpa_s->gas == NULL) {
3019 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3020 return -1;
3021 }
3022
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003023#ifdef CONFIG_P2P
3024 if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
3025 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3026 return -1;
3027 }
3028#endif /* CONFIG_P2P */
3029
3030 if (wpa_bss_init(wpa_s) < 0)
3031 return -1;
3032
Dmitry Shmidt04949592012-07-19 12:16:46 -07003033 if (pcsc_reader_init(wpa_s) < 0)
3034 return -1;
3035
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003036 if (wpas_init_ext_pw(wpa_s) < 0)
3037 return -1;
3038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003039 return 0;
3040}
3041
3042
3043static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003044 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003046 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003047 if (wpa_s->drv_priv) {
3048 wpa_supplicant_deauthenticate(wpa_s,
3049 WLAN_REASON_DEAUTH_LEAVING);
3050
3051 wpa_drv_set_countermeasures(wpa_s, 0);
3052 wpa_clear_keys(wpa_s, NULL);
3053 }
3054
3055 wpa_supplicant_cleanup(wpa_s);
3056
Dmitry Shmidt04949592012-07-19 12:16:46 -07003057#ifdef CONFIG_P2P
3058 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3059 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3060 "the management interface is being removed");
3061 wpas_p2p_deinit_global(wpa_s->global);
3062 }
3063#endif /* CONFIG_P2P */
3064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065 if (wpa_s->drv_priv)
3066 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003067
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003068 if (notify)
3069 wpas_notify_iface_removed(wpa_s);
3070
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003071 if (terminate)
3072 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003073
3074 if (wpa_s->ctrl_iface) {
3075 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3076 wpa_s->ctrl_iface = NULL;
3077 }
3078
3079 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003080 wpa_config_free(wpa_s->conf);
3081 wpa_s->conf = NULL;
3082 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003083
3084 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003085}
3086
3087
3088/**
3089 * wpa_supplicant_add_iface - Add a new network interface
3090 * @global: Pointer to global data from wpa_supplicant_init()
3091 * @iface: Interface configuration options
3092 * Returns: Pointer to the created interface or %NULL on failure
3093 *
3094 * This function is used to add new network interfaces for %wpa_supplicant.
3095 * This can be called before wpa_supplicant_run() to add interfaces before the
3096 * main event loop has been started. In addition, new interfaces can be added
3097 * dynamically while %wpa_supplicant is already running. This could happen,
3098 * e.g., when a hotplug network adapter is inserted.
3099 */
3100struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3101 struct wpa_interface *iface)
3102{
3103 struct wpa_supplicant *wpa_s;
3104 struct wpa_interface t_iface;
3105 struct wpa_ssid *ssid;
3106
3107 if (global == NULL || iface == NULL)
3108 return NULL;
3109
3110 wpa_s = wpa_supplicant_alloc();
3111 if (wpa_s == NULL)
3112 return NULL;
3113
3114 wpa_s->global = global;
3115
3116 t_iface = *iface;
3117 if (global->params.override_driver) {
3118 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3119 "('%s' -> '%s')",
3120 iface->driver, global->params.override_driver);
3121 t_iface.driver = global->params.override_driver;
3122 }
3123 if (global->params.override_ctrl_interface) {
3124 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3125 "ctrl_interface ('%s' -> '%s')",
3126 iface->ctrl_interface,
3127 global->params.override_ctrl_interface);
3128 t_iface.ctrl_interface =
3129 global->params.override_ctrl_interface;
3130 }
3131 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3132 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3133 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003134 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003135 return NULL;
3136 }
3137
3138 /* Notify the control interfaces about new iface */
3139 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003140 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003141 return NULL;
3142 }
3143
3144 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3145 wpas_notify_network_added(wpa_s, ssid);
3146
3147 wpa_s->next = global->ifaces;
3148 global->ifaces = wpa_s;
3149
3150 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003151 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003152
3153 return wpa_s;
3154}
3155
3156
3157/**
3158 * wpa_supplicant_remove_iface - Remove a network interface
3159 * @global: Pointer to global data from wpa_supplicant_init()
3160 * @wpa_s: Pointer to the network interface to be removed
3161 * Returns: 0 if interface was removed, -1 if interface was not found
3162 *
3163 * This function can be used to dynamically remove network interfaces from
3164 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3165 * addition, this function is used to remove all remaining interfaces when
3166 * %wpa_supplicant is terminated.
3167 */
3168int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003169 struct wpa_supplicant *wpa_s,
3170 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003171{
3172 struct wpa_supplicant *prev;
3173
3174 /* Remove interface from the global list of interfaces */
3175 prev = global->ifaces;
3176 if (prev == wpa_s) {
3177 global->ifaces = wpa_s->next;
3178 } else {
3179 while (prev && prev->next != wpa_s)
3180 prev = prev->next;
3181 if (prev == NULL)
3182 return -1;
3183 prev->next = wpa_s->next;
3184 }
3185
3186 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3187
3188 if (global->p2p_group_formation == wpa_s)
3189 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003190 if (global->p2p_invite_group == wpa_s)
3191 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003192 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003193
3194 return 0;
3195}
3196
3197
3198/**
3199 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3200 * @wpa_s: Pointer to the network interface
3201 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3202 */
3203const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3204{
3205 const char *eapol_method;
3206
3207 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3208 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3209 return "NO-EAP";
3210 }
3211
3212 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3213 if (eapol_method == NULL)
3214 return "UNKNOWN-EAP";
3215
3216 return eapol_method;
3217}
3218
3219
3220/**
3221 * wpa_supplicant_get_iface - Get a new network interface
3222 * @global: Pointer to global data from wpa_supplicant_init()
3223 * @ifname: Interface name
3224 * Returns: Pointer to the interface or %NULL if not found
3225 */
3226struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3227 const char *ifname)
3228{
3229 struct wpa_supplicant *wpa_s;
3230
3231 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3232 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3233 return wpa_s;
3234 }
3235 return NULL;
3236}
3237
3238
3239#ifndef CONFIG_NO_WPA_MSG
3240static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3241{
3242 struct wpa_supplicant *wpa_s = ctx;
3243 if (wpa_s == NULL)
3244 return NULL;
3245 return wpa_s->ifname;
3246}
3247#endif /* CONFIG_NO_WPA_MSG */
3248
3249
3250/**
3251 * wpa_supplicant_init - Initialize %wpa_supplicant
3252 * @params: Parameters for %wpa_supplicant
3253 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3254 *
3255 * This function is used to initialize %wpa_supplicant. After successful
3256 * initialization, the returned data pointer can be used to add and remove
3257 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3258 */
3259struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3260{
3261 struct wpa_global *global;
3262 int ret, i;
3263
3264 if (params == NULL)
3265 return NULL;
3266
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003267#ifdef CONFIG_DRIVER_NDIS
3268 {
3269 void driver_ndis_init_ops(void);
3270 driver_ndis_init_ops();
3271 }
3272#endif /* CONFIG_DRIVER_NDIS */
3273
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003274#ifndef CONFIG_NO_WPA_MSG
3275 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3276#endif /* CONFIG_NO_WPA_MSG */
3277
3278 wpa_debug_open_file(params->wpa_debug_file_path);
3279 if (params->wpa_debug_syslog)
3280 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003281 if (params->wpa_debug_tracing) {
3282 ret = wpa_debug_open_linux_tracing();
3283 if (ret) {
3284 wpa_printf(MSG_ERROR,
3285 "Failed to enable trace logging");
3286 return NULL;
3287 }
3288 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289
3290 ret = eap_register_methods();
3291 if (ret) {
3292 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3293 if (ret == -2)
3294 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3295 "the same EAP type.");
3296 return NULL;
3297 }
3298
3299 global = os_zalloc(sizeof(*global));
3300 if (global == NULL)
3301 return NULL;
3302 dl_list_init(&global->p2p_srv_bonjour);
3303 dl_list_init(&global->p2p_srv_upnp);
3304 global->params.daemonize = params->daemonize;
3305 global->params.wait_for_monitor = params->wait_for_monitor;
3306 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3307 if (params->pid_file)
3308 global->params.pid_file = os_strdup(params->pid_file);
3309 if (params->ctrl_interface)
3310 global->params.ctrl_interface =
3311 os_strdup(params->ctrl_interface);
3312 if (params->override_driver)
3313 global->params.override_driver =
3314 os_strdup(params->override_driver);
3315 if (params->override_ctrl_interface)
3316 global->params.override_ctrl_interface =
3317 os_strdup(params->override_ctrl_interface);
3318 wpa_debug_level = global->params.wpa_debug_level =
3319 params->wpa_debug_level;
3320 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3321 params->wpa_debug_show_keys;
3322 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3323 params->wpa_debug_timestamp;
3324
3325 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3326
3327 if (eloop_init()) {
3328 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3329 wpa_supplicant_deinit(global);
3330 return NULL;
3331 }
3332
Jouni Malinen75ecf522011-06-27 15:19:46 -07003333 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003334
3335 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3336 if (global->ctrl_iface == NULL) {
3337 wpa_supplicant_deinit(global);
3338 return NULL;
3339 }
3340
3341 if (wpas_notify_supplicant_initialized(global)) {
3342 wpa_supplicant_deinit(global);
3343 return NULL;
3344 }
3345
3346 for (i = 0; wpa_drivers[i]; i++)
3347 global->drv_count++;
3348 if (global->drv_count == 0) {
3349 wpa_printf(MSG_ERROR, "No drivers enabled");
3350 wpa_supplicant_deinit(global);
3351 return NULL;
3352 }
3353 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3354 if (global->drv_priv == NULL) {
3355 wpa_supplicant_deinit(global);
3356 return NULL;
3357 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003359#ifdef CONFIG_WIFI_DISPLAY
3360 if (wifi_display_init(global) < 0) {
3361 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3362 wpa_supplicant_deinit(global);
3363 return NULL;
3364 }
3365#endif /* CONFIG_WIFI_DISPLAY */
3366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 return global;
3368}
3369
3370
3371/**
3372 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3373 * @global: Pointer to global data from wpa_supplicant_init()
3374 * Returns: 0 after successful event loop run, -1 on failure
3375 *
3376 * This function starts the main event loop and continues running as long as
3377 * there are any remaining events. In most cases, this function is running as
3378 * long as the %wpa_supplicant process in still in use.
3379 */
3380int wpa_supplicant_run(struct wpa_global *global)
3381{
3382 struct wpa_supplicant *wpa_s;
3383
3384 if (global->params.daemonize &&
3385 wpa_supplicant_daemon(global->params.pid_file))
3386 return -1;
3387
3388 if (global->params.wait_for_monitor) {
3389 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3390 if (wpa_s->ctrl_iface)
3391 wpa_supplicant_ctrl_iface_wait(
3392 wpa_s->ctrl_iface);
3393 }
3394
3395 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3396 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3397
3398 eloop_run();
3399
3400 return 0;
3401}
3402
3403
3404/**
3405 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3406 * @global: Pointer to global data from wpa_supplicant_init()
3407 *
3408 * This function is called to deinitialize %wpa_supplicant and to free all
3409 * allocated resources. Remaining network interfaces will also be removed.
3410 */
3411void wpa_supplicant_deinit(struct wpa_global *global)
3412{
3413 int i;
3414
3415 if (global == NULL)
3416 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003417
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003418#ifdef CONFIG_WIFI_DISPLAY
3419 wifi_display_deinit(global);
3420#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421#ifdef CONFIG_P2P
3422 wpas_p2p_deinit_global(global);
3423#endif /* CONFIG_P2P */
3424
3425 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003426 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003427
3428 if (global->ctrl_iface)
3429 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3430
3431 wpas_notify_supplicant_deinitialized(global);
3432
3433 eap_peer_unregister_methods();
3434#ifdef CONFIG_AP
3435 eap_server_unregister_methods();
3436#endif /* CONFIG_AP */
3437
3438 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3439 if (!global->drv_priv[i])
3440 continue;
3441 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3442 }
3443 os_free(global->drv_priv);
3444
3445 random_deinit();
3446
3447 eloop_destroy();
3448
3449 if (global->params.pid_file) {
3450 os_daemonize_terminate(global->params.pid_file);
3451 os_free(global->params.pid_file);
3452 }
3453 os_free(global->params.ctrl_interface);
3454 os_free(global->params.override_driver);
3455 os_free(global->params.override_ctrl_interface);
3456
Dmitry Shmidt04949592012-07-19 12:16:46 -07003457 os_free(global->p2p_disallow_freq);
3458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 os_free(global);
3460 wpa_debug_close_syslog();
3461 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003462 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463}
3464
3465
3466void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3467{
3468 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3469 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3470 char country[3];
3471 country[0] = wpa_s->conf->country[0];
3472 country[1] = wpa_s->conf->country[1];
3473 country[2] = '\0';
3474 if (wpa_drv_set_country(wpa_s, country) < 0) {
3475 wpa_printf(MSG_ERROR, "Failed to set country code "
3476 "'%s'", country);
3477 }
3478 }
3479
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003480 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3481 wpas_init_ext_pw(wpa_s);
3482
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483#ifdef CONFIG_WPS
3484 wpas_wps_update_config(wpa_s);
3485#endif /* CONFIG_WPS */
3486
3487#ifdef CONFIG_P2P
3488 wpas_p2p_update_config(wpa_s);
3489#endif /* CONFIG_P2P */
3490
3491 wpa_s->conf->changed_parameters = 0;
3492}
3493
3494
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003495static void add_freq(int *freqs, int *num_freqs, int freq)
3496{
3497 int i;
3498
3499 for (i = 0; i < *num_freqs; i++) {
3500 if (freqs[i] == freq)
3501 return;
3502 }
3503
3504 freqs[*num_freqs] = freq;
3505 (*num_freqs)++;
3506}
3507
3508
3509static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3510{
3511 struct wpa_bss *bss, *cbss;
3512 const int max_freqs = 10;
3513 int *freqs;
3514 int num_freqs = 0;
3515
3516 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3517 if (freqs == NULL)
3518 return NULL;
3519
3520 cbss = wpa_s->current_bss;
3521
3522 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3523 if (bss == cbss)
3524 continue;
3525 if (bss->ssid_len == cbss->ssid_len &&
3526 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3527 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3528 add_freq(freqs, &num_freqs, bss->freq);
3529 if (num_freqs == max_freqs)
3530 break;
3531 }
3532 }
3533
3534 if (num_freqs == 0) {
3535 os_free(freqs);
3536 freqs = NULL;
3537 }
3538
3539 return freqs;
3540}
3541
3542
3543void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3544{
3545 int timeout;
3546 int count;
3547 int *freqs = NULL;
3548
3549 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003550 * Remove possible authentication timeout since the connection failed.
3551 */
3552 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3553
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003554 if (wpa_s->disconnected) {
3555 /*
3556 * There is no point in blacklisting the AP if this event is
3557 * generated based on local request to disconnect.
3558 */
3559 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
3560 "indication since interface has been put into "
3561 "disconnected state");
3562 return;
3563 }
3564
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003565 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003566 * Add the failed BSSID into the blacklist and speed up next scan
3567 * attempt if there could be other APs that could accept association.
3568 * The current blacklist count indicates how many times we have tried
3569 * connecting to this AP and multiple attempts mean that other APs are
3570 * either not available or has already been tried, so that we can start
3571 * increasing the delay here to avoid constant scanning.
3572 */
3573 count = wpa_blacklist_add(wpa_s, bssid);
3574 if (count == 1 && wpa_s->current_bss) {
3575 /*
3576 * This BSS was not in the blacklist before. If there is
3577 * another BSS available for the same ESS, we should try that
3578 * next. Otherwise, we may as well try this one once more
3579 * before allowing other, likely worse, ESSes to be considered.
3580 */
3581 freqs = get_bss_freqs_in_ess(wpa_s);
3582 if (freqs) {
3583 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3584 "has been seen; try it next");
3585 wpa_blacklist_add(wpa_s, bssid);
3586 /*
3587 * On the next scan, go through only the known channels
3588 * used in this ESS based on previous scans to speed up
3589 * common load balancing use case.
3590 */
3591 os_free(wpa_s->next_scan_freqs);
3592 wpa_s->next_scan_freqs = freqs;
3593 }
3594 }
3595
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003596 /*
3597 * Add previous failure count in case the temporary blacklist was
3598 * cleared due to no other BSSes being available.
3599 */
3600 count += wpa_s->extra_blacklist_count;
3601
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003602 if (count > 3 && wpa_s->current_ssid) {
3603 wpa_printf(MSG_DEBUG, "Continuous association failures - "
3604 "consider temporary network disabling");
3605 wpas_auth_failed(wpa_s);
3606 }
3607
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003608 switch (count) {
3609 case 1:
3610 timeout = 100;
3611 break;
3612 case 2:
3613 timeout = 500;
3614 break;
3615 case 3:
3616 timeout = 1000;
3617 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003618 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003620 break;
3621 default:
3622 timeout = 10000;
3623 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624 }
3625
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003626 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3627 "ms", count, timeout);
3628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 /*
3630 * TODO: if more than one possible AP is available in scan results,
3631 * could try the other ones before requesting a new scan.
3632 */
3633 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3634 1000 * (timeout % 1000));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003635
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07003636 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003638
3639
3640int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3641{
3642 return wpa_s->conf->ap_scan == 2 ||
3643 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3644}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003645
Dmitry Shmidt04949592012-07-19 12:16:46 -07003646
3647#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3648int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3649 struct wpa_ssid *ssid,
3650 const char *field,
3651 const char *value)
3652{
3653#ifdef IEEE8021X_EAPOL
3654 struct eap_peer_config *eap = &ssid->eap;
3655
3656 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3657 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3658 (const u8 *) value, os_strlen(value));
3659
3660 switch (wpa_supplicant_ctrl_req_from_string(field)) {
3661 case WPA_CTRL_REQ_EAP_IDENTITY:
3662 os_free(eap->identity);
3663 eap->identity = (u8 *) os_strdup(value);
3664 eap->identity_len = os_strlen(value);
3665 eap->pending_req_identity = 0;
3666 if (ssid == wpa_s->current_ssid)
3667 wpa_s->reassociate = 1;
3668 break;
3669 case WPA_CTRL_REQ_EAP_PASSWORD:
3670 os_free(eap->password);
3671 eap->password = (u8 *) os_strdup(value);
3672 eap->password_len = os_strlen(value);
3673 eap->pending_req_password = 0;
3674 if (ssid == wpa_s->current_ssid)
3675 wpa_s->reassociate = 1;
3676 break;
3677 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3678 os_free(eap->new_password);
3679 eap->new_password = (u8 *) os_strdup(value);
3680 eap->new_password_len = os_strlen(value);
3681 eap->pending_req_new_password = 0;
3682 if (ssid == wpa_s->current_ssid)
3683 wpa_s->reassociate = 1;
3684 break;
3685 case WPA_CTRL_REQ_EAP_PIN:
3686 os_free(eap->pin);
3687 eap->pin = os_strdup(value);
3688 eap->pending_req_pin = 0;
3689 if (ssid == wpa_s->current_ssid)
3690 wpa_s->reassociate = 1;
3691 break;
3692 case WPA_CTRL_REQ_EAP_OTP:
3693 os_free(eap->otp);
3694 eap->otp = (u8 *) os_strdup(value);
3695 eap->otp_len = os_strlen(value);
3696 os_free(eap->pending_req_otp);
3697 eap->pending_req_otp = NULL;
3698 eap->pending_req_otp_len = 0;
3699 break;
3700 case WPA_CTRL_REQ_EAP_PASSPHRASE:
3701 os_free(eap->private_key_passwd);
3702 eap->private_key_passwd = (u8 *) os_strdup(value);
3703 eap->pending_req_passphrase = 0;
3704 if (ssid == wpa_s->current_ssid)
3705 wpa_s->reassociate = 1;
3706 break;
3707 default:
3708 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3709 return -1;
3710 }
3711
3712 return 0;
3713#else /* IEEE8021X_EAPOL */
3714 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3715 return -1;
3716#endif /* IEEE8021X_EAPOL */
3717}
3718#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3719
3720
3721int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3722{
3723 int i;
3724 unsigned int drv_enc;
3725
3726 if (ssid == NULL)
3727 return 1;
3728
3729 if (ssid->disabled)
3730 return 1;
3731
3732 if (wpa_s && wpa_s->drv_capa_known)
3733 drv_enc = wpa_s->drv_enc;
3734 else
3735 drv_enc = (unsigned int) -1;
3736
3737 for (i = 0; i < NUM_WEP_KEYS; i++) {
3738 size_t len = ssid->wep_key_len[i];
3739 if (len == 0)
3740 continue;
3741 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3742 continue;
3743 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3744 continue;
3745 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3746 continue;
3747 return 1; /* invalid WEP key */
3748 }
3749
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003750 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
3751 !ssid->ext_psk)
3752 return 1;
3753
Dmitry Shmidt04949592012-07-19 12:16:46 -07003754 return 0;
3755}
3756
3757
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003758int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003759{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003760 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003761 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003762 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003763 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003764 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003765}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003766
3767
3768void wpas_auth_failed(struct wpa_supplicant *wpa_s)
3769{
3770 struct wpa_ssid *ssid = wpa_s->current_ssid;
3771 int dur;
3772 struct os_time now;
3773
3774 if (ssid == NULL) {
3775 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3776 "SSID block");
3777 return;
3778 }
3779
3780 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3781 return;
3782
3783 ssid->auth_failures++;
3784 if (ssid->auth_failures > 50)
3785 dur = 300;
3786 else if (ssid->auth_failures > 20)
3787 dur = 120;
3788 else if (ssid->auth_failures > 10)
3789 dur = 60;
3790 else if (ssid->auth_failures > 5)
3791 dur = 30;
3792 else if (ssid->auth_failures > 1)
3793 dur = 20;
3794 else
3795 dur = 10;
3796
3797 os_get_time(&now);
3798 if (now.sec + dur <= ssid->disabled_until.sec)
3799 return;
3800
3801 ssid->disabled_until.sec = now.sec + dur;
3802
3803 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
3804 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
3805 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
3806 ssid->auth_failures, dur);
3807}
3808
3809
3810void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
3811 struct wpa_ssid *ssid, int clear_failures)
3812{
3813 if (ssid == NULL)
3814 return;
3815
3816 if (ssid->disabled_until.sec) {
3817 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
3818 "id=%d ssid=\"%s\"",
3819 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3820 }
3821 ssid->disabled_until.sec = 0;
3822 ssid->disabled_until.usec = 0;
3823 if (clear_failures)
3824 ssid->auth_failures = 0;
3825}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003826
3827
3828int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
3829{
3830 size_t i;
3831
3832 if (wpa_s->disallow_aps_bssid == NULL)
3833 return 0;
3834
3835 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
3836 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
3837 bssid, ETH_ALEN) == 0)
3838 return 1;
3839 }
3840
3841 return 0;
3842}
3843
3844
3845int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
3846 size_t ssid_len)
3847{
3848 size_t i;
3849
3850 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
3851 return 0;
3852
3853 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
3854 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
3855 if (ssid_len == s->ssid_len &&
3856 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3857 return 1;
3858 }
3859
3860 return 0;
3861}
3862
3863
3864/**
3865 * wpas_request_connection - Request a new connection
3866 * @wpa_s: Pointer to the network interface
3867 *
3868 * This function is used to request a new connection to be found. It will mark
3869 * the interface to allow reassociation and request a new scan to find a
3870 * suitable network to connect to.
3871 */
3872void wpas_request_connection(struct wpa_supplicant *wpa_s)
3873{
3874 wpa_s->normal_scans = 0;
3875 wpa_supplicant_reinit_autoscan(wpa_s);
3876 wpa_s->extra_blacklist_count = 0;
3877 wpa_s->disconnected = 0;
3878 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08003879
3880 if (wpa_supplicant_fast_associate(wpa_s) != 1)
3881 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003882}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003883
3884
3885/**
3886 * wpas_wpa_is_in_progress - Check whether a connection is in progress
3887 * @wpa_s: Pointer to wpa_supplicant data
3888 *
3889 * This function is to check if the wpa state is in beginning of the connection
3890 * during 4-way handshake or group key handshake with WPA on any shared
3891 * interface.
3892 */
3893int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
3894{
3895 const char *rn, *rn2;
3896 struct wpa_supplicant *ifs;
3897
3898 if (!wpa_s->driver->get_radio_name)
3899 return 0;
3900
3901 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3902 if (rn == NULL || rn[0] == '\0')
3903 return 0;
3904
3905 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3906 if (ifs == wpa_s || !ifs->driver->get_radio_name)
3907 continue;
3908
3909 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
3910 if (!rn2 || os_strcmp(rn, rn2) != 0)
3911 continue;
3912 if (ifs->wpa_state >= WPA_AUTHENTICATING &&
3913 ifs->wpa_state != WPA_COMPLETED) {
3914 wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
3915 "on interface %s - defer scan", ifs->ifname);
3916 return 1;
3917 }
3918 }
3919
3920 return 0;
3921}