blob: 27791b3012d70e597cb15bfe7eb1835769218b16 [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 Shmidtf7e0a992013-05-23 11:03:10 -07001827 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1828 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001829 }
1830}
1831
1832
1833/**
1834 * wpa_supplicant_disable_network - Mark a configured network as disabled
1835 * @wpa_s: wpa_supplicant structure for a network interface
1836 * @ssid: wpa_ssid structure for a configured network or %NULL
1837 *
1838 * Disables the specified network or all networks if no network specified.
1839 */
1840void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1841 struct wpa_ssid *ssid)
1842{
1843 struct wpa_ssid *other_ssid;
1844 int was_disabled;
1845
1846 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001847 if (wpa_s->sched_scanning)
1848 wpa_supplicant_cancel_sched_scan(wpa_s);
1849
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1851 other_ssid = other_ssid->next) {
1852 was_disabled = other_ssid->disabled;
1853 if (was_disabled == 2)
1854 continue; /* do not change persistent P2P group
1855 * data */
1856
1857 other_ssid->disabled = 1;
1858
1859 if (was_disabled != other_ssid->disabled)
1860 wpas_notify_network_enabled_changed(
1861 wpa_s, other_ssid);
1862 }
1863 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001864 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1866 } else if (ssid->disabled != 2) {
1867 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001868 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1870
1871 was_disabled = ssid->disabled;
1872
1873 ssid->disabled = 1;
1874
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001875 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001877 if (wpa_s->sched_scanning) {
1878 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1879 "to remove network from filters");
1880 wpa_supplicant_cancel_sched_scan(wpa_s);
1881 wpa_supplicant_req_scan(wpa_s, 0, 0);
1882 }
1883 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 }
1885}
1886
1887
1888/**
1889 * wpa_supplicant_select_network - Attempt association with a network
1890 * @wpa_s: wpa_supplicant structure for a network interface
1891 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1892 */
1893void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1894 struct wpa_ssid *ssid)
1895{
1896
1897 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001898 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001900 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001901 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001902 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001903 disconnected = 1;
1904 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001905
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001906 if (ssid)
1907 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001909 /*
1910 * Mark all other networks disabled or mark all networks enabled if no
1911 * network specified.
1912 */
1913 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1914 other_ssid = other_ssid->next) {
1915 int was_disabled = other_ssid->disabled;
1916 if (was_disabled == 2)
1917 continue; /* do not change persistent P2P group data */
1918
1919 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001920 if (was_disabled && !other_ssid->disabled)
1921 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922
1923 if (was_disabled != other_ssid->disabled)
1924 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1925 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001926
1927 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
1928 /* We are already associated with the selected network */
1929 wpa_printf(MSG_DEBUG, "Already associated with the "
1930 "selected network - do nothing");
1931 return;
1932 }
1933
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001934 if (ssid)
1935 wpa_s->current_ssid = ssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001936 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001937 wpa_s->disconnected = 0;
1938 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001939
1940 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1941 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942
1943 if (ssid)
1944 wpas_notify_network_selected(wpa_s, ssid);
1945}
1946
1947
1948/**
1949 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
1950 * @wpa_s: wpa_supplicant structure for a network interface
1951 * @ap_scan: AP scan mode
1952 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
1953 *
1954 */
1955int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
1956{
1957
1958 int old_ap_scan;
1959
1960 if (ap_scan < 0 || ap_scan > 2)
1961 return -1;
1962
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001963#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001964 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
1965 wpa_s->wpa_state >= WPA_ASSOCIATING &&
1966 wpa_s->wpa_state < WPA_COMPLETED) {
1967 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
1968 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001969 return 0;
1970 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001971#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973 old_ap_scan = wpa_s->conf->ap_scan;
1974 wpa_s->conf->ap_scan = ap_scan;
1975
1976 if (old_ap_scan != wpa_s->conf->ap_scan)
1977 wpas_notify_ap_scan_changed(wpa_s);
1978
1979 return 0;
1980}
1981
1982
1983/**
1984 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
1985 * @wpa_s: wpa_supplicant structure for a network interface
1986 * @expire_age: Expiration age in seconds
1987 * Returns: 0 if succeed or -1 if expire_age has an invalid value
1988 *
1989 */
1990int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
1991 unsigned int bss_expire_age)
1992{
1993 if (bss_expire_age < 10) {
1994 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
1995 bss_expire_age);
1996 return -1;
1997 }
1998 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
1999 bss_expire_age);
2000 wpa_s->conf->bss_expiration_age = bss_expire_age;
2001
2002 return 0;
2003}
2004
2005
2006/**
2007 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2008 * @wpa_s: wpa_supplicant structure for a network interface
2009 * @expire_count: number of scans after which an unseen BSS is reclaimed
2010 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2011 *
2012 */
2013int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2014 unsigned int bss_expire_count)
2015{
2016 if (bss_expire_count < 1) {
2017 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2018 bss_expire_count);
2019 return -1;
2020 }
2021 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2022 bss_expire_count);
2023 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2024
2025 return 0;
2026}
2027
2028
2029/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002030 * wpa_supplicant_set_scan_interval - Set scan interval
2031 * @wpa_s: wpa_supplicant structure for a network interface
2032 * @scan_interval: scan interval in seconds
2033 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2034 *
2035 */
2036int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2037 int scan_interval)
2038{
2039 if (scan_interval < 0) {
2040 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2041 scan_interval);
2042 return -1;
2043 }
2044 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2045 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002046 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002047
2048 return 0;
2049}
2050
2051
2052/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 * wpa_supplicant_set_debug_params - Set global debug params
2054 * @global: wpa_global structure
2055 * @debug_level: debug level
2056 * @debug_timestamp: determines if show timestamp in debug data
2057 * @debug_show_keys: determines if show keys in debug data
2058 * Returns: 0 if succeed or -1 if debug_level has wrong value
2059 */
2060int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2061 int debug_timestamp, int debug_show_keys)
2062{
2063
2064 int old_level, old_timestamp, old_show_keys;
2065
2066 /* check for allowed debuglevels */
2067 if (debug_level != MSG_EXCESSIVE &&
2068 debug_level != MSG_MSGDUMP &&
2069 debug_level != MSG_DEBUG &&
2070 debug_level != MSG_INFO &&
2071 debug_level != MSG_WARNING &&
2072 debug_level != MSG_ERROR)
2073 return -1;
2074
2075 old_level = wpa_debug_level;
2076 old_timestamp = wpa_debug_timestamp;
2077 old_show_keys = wpa_debug_show_keys;
2078
2079 wpa_debug_level = debug_level;
2080 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2081 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2082
2083 if (wpa_debug_level != old_level)
2084 wpas_notify_debug_level_changed(global);
2085 if (wpa_debug_timestamp != old_timestamp)
2086 wpas_notify_debug_timestamp_changed(global);
2087 if (wpa_debug_show_keys != old_show_keys)
2088 wpas_notify_debug_show_keys_changed(global);
2089
2090 return 0;
2091}
2092
2093
2094/**
2095 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2096 * @wpa_s: Pointer to wpa_supplicant data
2097 * Returns: A pointer to the current network structure or %NULL on failure
2098 */
2099struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2100{
2101 struct wpa_ssid *entry;
2102 u8 ssid[MAX_SSID_LEN];
2103 int res;
2104 size_t ssid_len;
2105 u8 bssid[ETH_ALEN];
2106 int wired;
2107
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002108 res = wpa_drv_get_ssid(wpa_s, ssid);
2109 if (res < 0) {
2110 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2111 "driver");
2112 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002114 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002116 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2118 "driver");
2119 return NULL;
2120 }
2121
2122 wired = wpa_s->conf->ap_scan == 0 &&
2123 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2124
2125 entry = wpa_s->conf->ssid;
2126 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002127 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002128 ((ssid_len == entry->ssid_len &&
2129 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2130 (!entry->bssid_set ||
2131 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2132 return entry;
2133#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002134 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2136 (entry->ssid == NULL || entry->ssid_len == 0) &&
2137 (!entry->bssid_set ||
2138 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2139 return entry;
2140#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002141
Dmitry Shmidt04949592012-07-19 12:16:46 -07002142 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002143 entry->ssid_len == 0 &&
2144 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2145 return entry;
2146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147 entry = entry->next;
2148 }
2149
2150 return NULL;
2151}
2152
2153
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002154static int select_driver(struct wpa_supplicant *wpa_s, int i)
2155{
2156 struct wpa_global *global = wpa_s->global;
2157
2158 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2159 global->drv_priv[i] = wpa_drivers[i]->global_init();
2160 if (global->drv_priv[i] == NULL) {
2161 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2162 "'%s'", wpa_drivers[i]->name);
2163 return -1;
2164 }
2165 }
2166
2167 wpa_s->driver = wpa_drivers[i];
2168 wpa_s->global_drv_priv = global->drv_priv[i];
2169
2170 return 0;
2171}
2172
2173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002174static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2175 const char *name)
2176{
2177 int i;
2178 size_t len;
2179 const char *pos, *driver = name;
2180
2181 if (wpa_s == NULL)
2182 return -1;
2183
2184 if (wpa_drivers[0] == NULL) {
2185 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2186 "wpa_supplicant");
2187 return -1;
2188 }
2189
2190 if (name == NULL) {
2191 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002192 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193 }
2194
2195 do {
2196 pos = os_strchr(driver, ',');
2197 if (pos)
2198 len = pos - driver;
2199 else
2200 len = os_strlen(driver);
2201
2202 for (i = 0; wpa_drivers[i]; i++) {
2203 if (os_strlen(wpa_drivers[i]->name) == len &&
2204 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002205 0) {
2206 /* First driver that succeeds wins */
2207 if (select_driver(wpa_s, i) == 0)
2208 return 0;
2209 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002210 }
2211
2212 driver = pos + 1;
2213 } while (pos);
2214
2215 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2216 return -1;
2217}
2218
2219
2220/**
2221 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2222 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2223 * with struct wpa_driver_ops::init()
2224 * @src_addr: Source address of the EAPOL frame
2225 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2226 * @len: Length of the EAPOL data
2227 *
2228 * This function is called for each received EAPOL frame. Most driver
2229 * interfaces rely on more generic OS mechanism for receiving frames through
2230 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2231 * take care of received EAPOL frames and deliver them to the core supplicant
2232 * code by calling this function.
2233 */
2234void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2235 const u8 *buf, size_t len)
2236{
2237 struct wpa_supplicant *wpa_s = ctx;
2238
2239 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2240 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2241
Jouni Malinena05074c2012-12-21 21:35:35 +02002242 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2243 (wpa_s->last_eapol_matches_bssid &&
2244#ifdef CONFIG_AP
2245 !wpa_s->ap_iface &&
2246#endif /* CONFIG_AP */
2247 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248 /*
2249 * There is possible race condition between receiving the
2250 * association event and the EAPOL frame since they are coming
2251 * through different paths from the driver. In order to avoid
2252 * issues in trying to process the EAPOL frame before receiving
2253 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002254 * the association event is received. This may also be needed in
2255 * driver-based roaming case, so also use src_addr != BSSID as a
2256 * trigger if we have previously confirmed that the
2257 * Authenticator uses BSSID as the src_addr (which is not the
2258 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259 */
2260 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002261 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2262 wpa_supplicant_state_txt(wpa_s->wpa_state),
2263 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 wpabuf_free(wpa_s->pending_eapol_rx);
2265 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2266 if (wpa_s->pending_eapol_rx) {
2267 os_get_time(&wpa_s->pending_eapol_rx_time);
2268 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2269 ETH_ALEN);
2270 }
2271 return;
2272 }
2273
Jouni Malinena05074c2012-12-21 21:35:35 +02002274 wpa_s->last_eapol_matches_bssid =
2275 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2276
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277#ifdef CONFIG_AP
2278 if (wpa_s->ap_iface) {
2279 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2280 return;
2281 }
2282#endif /* CONFIG_AP */
2283
2284 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2285 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2286 "no key management is configured");
2287 return;
2288 }
2289
2290 if (wpa_s->eapol_received == 0 &&
2291 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2292 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2293 wpa_s->wpa_state != WPA_COMPLETED) &&
2294 (wpa_s->current_ssid == NULL ||
2295 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2296 /* Timeout for completing IEEE 802.1X and WPA authentication */
2297 wpa_supplicant_req_auth_timeout(
2298 wpa_s,
2299 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2300 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2301 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2302 70 : 10, 0);
2303 }
2304 wpa_s->eapol_received++;
2305
2306 if (wpa_s->countermeasures) {
2307 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2308 "EAPOL packet");
2309 return;
2310 }
2311
2312#ifdef CONFIG_IBSS_RSN
2313 if (wpa_s->current_ssid &&
2314 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2315 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2316 return;
2317 }
2318#endif /* CONFIG_IBSS_RSN */
2319
2320 /* Source address of the incoming EAPOL frame could be compared to the
2321 * current BSSID. However, it is possible that a centralized
2322 * Authenticator could be using another MAC address than the BSSID of
2323 * an AP, so just allow any address to be used for now. The replies are
2324 * still sent to the current BSSID (if available), though. */
2325
2326 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2327 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2328 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2329 return;
2330 wpa_drv_poll(wpa_s);
2331 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2332 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2333 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2334 /*
2335 * Set portValid = TRUE here since we are going to skip 4-way
2336 * handshake processing which would normally set portValid. We
2337 * need this to allow the EAPOL state machines to be completed
2338 * without going through EAPOL-Key handshake.
2339 */
2340 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2341 }
2342}
2343
2344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002345int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 if (wpa_s->driver->send_eapol) {
2348 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2349 if (addr)
2350 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2351 } else if (!(wpa_s->drv_flags &
2352 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002353 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2355 wpa_drv_get_mac_addr(wpa_s),
2356 ETH_P_EAPOL,
2357 wpa_supplicant_rx_eapol, wpa_s, 0);
2358 if (wpa_s->l2 == NULL)
2359 return -1;
2360 } else {
2361 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2362 if (addr)
2363 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2364 }
2365
2366 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2367 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2368 return -1;
2369 }
2370
2371 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2372 MAC2STR(wpa_s->own_addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002373 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2374
2375 return 0;
2376}
2377
2378
Dmitry Shmidt04949592012-07-19 12:16:46 -07002379static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2380 const u8 *buf, size_t len)
2381{
2382 struct wpa_supplicant *wpa_s = ctx;
2383 const struct l2_ethhdr *eth;
2384
2385 if (len < sizeof(*eth))
2386 return;
2387 eth = (const struct l2_ethhdr *) buf;
2388
2389 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2390 !(eth->h_dest[0] & 0x01)) {
2391 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2392 " (bridge - not for this interface - ignore)",
2393 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2394 return;
2395 }
2396
2397 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2398 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2399 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2400 len - sizeof(*eth));
2401}
2402
2403
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002404/**
2405 * wpa_supplicant_driver_init - Initialize driver interface parameters
2406 * @wpa_s: Pointer to wpa_supplicant data
2407 * Returns: 0 on success, -1 on failure
2408 *
2409 * This function is called to initialize driver interface parameters.
2410 * wpa_drv_init() must have been called before this function to initialize the
2411 * driver interface.
2412 */
2413int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2414{
2415 static int interface_count = 0;
2416
2417 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2418 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419
2420 if (wpa_s->bridge_ifname[0]) {
2421 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2422 "interface '%s'", wpa_s->bridge_ifname);
2423 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2424 wpa_s->own_addr,
2425 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002426 wpa_supplicant_rx_eapol_bridge,
2427 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 if (wpa_s->l2_br == NULL) {
2429 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2430 "connection for the bridge interface '%s'",
2431 wpa_s->bridge_ifname);
2432 return -1;
2433 }
2434 }
2435
2436 wpa_clear_keys(wpa_s, NULL);
2437
2438 /* Make sure that TKIP countermeasures are not left enabled (could
2439 * happen if wpa_supplicant is killed during countermeasures. */
2440 wpa_drv_set_countermeasures(wpa_s, 0);
2441
2442 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2443 wpa_drv_flush_pmkid(wpa_s);
2444
2445 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002446 wpa_s->prev_scan_wildcard = 0;
2447
Dmitry Shmidt04949592012-07-19 12:16:46 -07002448 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002449 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2450 100000))
2451 wpa_supplicant_req_scan(wpa_s, interface_count,
2452 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 interface_count++;
2454 } else
2455 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2456
2457 return 0;
2458}
2459
2460
2461static int wpa_supplicant_daemon(const char *pid_file)
2462{
2463 wpa_printf(MSG_DEBUG, "Daemonize..");
2464 return os_daemonize(pid_file);
2465}
2466
2467
2468static struct wpa_supplicant * wpa_supplicant_alloc(void)
2469{
2470 struct wpa_supplicant *wpa_s;
2471
2472 wpa_s = os_zalloc(sizeof(*wpa_s));
2473 if (wpa_s == NULL)
2474 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002475 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 wpa_s->scan_interval = 5;
2477 wpa_s->new_connection = 1;
2478 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002479 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480
2481 return wpa_s;
2482}
2483
2484
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002485#ifdef CONFIG_HT_OVERRIDES
2486
2487static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2488 struct ieee80211_ht_capabilities *htcaps,
2489 struct ieee80211_ht_capabilities *htcaps_mask,
2490 const char *ht_mcs)
2491{
2492 /* parse ht_mcs into hex array */
2493 int i;
2494 const char *tmp = ht_mcs;
2495 char *end = NULL;
2496
2497 /* If ht_mcs is null, do not set anything */
2498 if (!ht_mcs)
2499 return 0;
2500
2501 /* This is what we are setting in the kernel */
2502 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2503
2504 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2505
2506 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2507 errno = 0;
2508 long v = strtol(tmp, &end, 16);
2509 if (errno == 0) {
2510 wpa_msg(wpa_s, MSG_DEBUG,
2511 "htcap value[%i]: %ld end: %p tmp: %p",
2512 i, v, end, tmp);
2513 if (end == tmp)
2514 break;
2515
2516 htcaps->supported_mcs_set[i] = v;
2517 tmp = end;
2518 } else {
2519 wpa_msg(wpa_s, MSG_ERROR,
2520 "Failed to parse ht-mcs: %s, error: %s\n",
2521 ht_mcs, strerror(errno));
2522 return -1;
2523 }
2524 }
2525
2526 /*
2527 * If we were able to parse any values, then set mask for the MCS set.
2528 */
2529 if (i) {
2530 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2531 IEEE80211_HT_MCS_MASK_LEN - 1);
2532 /* skip the 3 reserved bits */
2533 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2534 0x1f;
2535 }
2536
2537 return 0;
2538}
2539
2540
2541static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2542 struct ieee80211_ht_capabilities *htcaps,
2543 struct ieee80211_ht_capabilities *htcaps_mask,
2544 int disabled)
2545{
2546 u16 msk;
2547
2548 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2549
2550 if (disabled == -1)
2551 return 0;
2552
2553 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2554 htcaps_mask->ht_capabilities_info |= msk;
2555 if (disabled)
2556 htcaps->ht_capabilities_info &= msk;
2557 else
2558 htcaps->ht_capabilities_info |= msk;
2559
2560 return 0;
2561}
2562
2563
2564static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2565 struct ieee80211_ht_capabilities *htcaps,
2566 struct ieee80211_ht_capabilities *htcaps_mask,
2567 int factor)
2568{
2569 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2570
2571 if (factor == -1)
2572 return 0;
2573
2574 if (factor < 0 || factor > 3) {
2575 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2576 "Must be 0-3 or -1", factor);
2577 return -EINVAL;
2578 }
2579
2580 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2581 htcaps->a_mpdu_params &= ~0x3;
2582 htcaps->a_mpdu_params |= factor & 0x3;
2583
2584 return 0;
2585}
2586
2587
2588static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2589 struct ieee80211_ht_capabilities *htcaps,
2590 struct ieee80211_ht_capabilities *htcaps_mask,
2591 int density)
2592{
2593 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2594
2595 if (density == -1)
2596 return 0;
2597
2598 if (density < 0 || density > 7) {
2599 wpa_msg(wpa_s, MSG_ERROR,
2600 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2601 density);
2602 return -EINVAL;
2603 }
2604
2605 htcaps_mask->a_mpdu_params |= 0x1C;
2606 htcaps->a_mpdu_params &= ~(0x1C);
2607 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2608
2609 return 0;
2610}
2611
2612
2613static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2614 struct ieee80211_ht_capabilities *htcaps,
2615 struct ieee80211_ht_capabilities *htcaps_mask,
2616 int disabled)
2617{
2618 /* Masking these out disables HT40 */
2619 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2620 HT_CAP_INFO_SHORT_GI40MHZ);
2621
2622 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2623
2624 if (disabled)
2625 htcaps->ht_capabilities_info &= ~msk;
2626 else
2627 htcaps->ht_capabilities_info |= msk;
2628
2629 htcaps_mask->ht_capabilities_info |= msk;
2630
2631 return 0;
2632}
2633
2634
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002635static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2636 struct ieee80211_ht_capabilities *htcaps,
2637 struct ieee80211_ht_capabilities *htcaps_mask,
2638 int disabled)
2639{
2640 /* Masking these out disables SGI */
2641 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2642 HT_CAP_INFO_SHORT_GI40MHZ);
2643
2644 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2645
2646 if (disabled)
2647 htcaps->ht_capabilities_info &= ~msk;
2648 else
2649 htcaps->ht_capabilities_info |= msk;
2650
2651 htcaps_mask->ht_capabilities_info |= msk;
2652
2653 return 0;
2654}
2655
2656
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002657void wpa_supplicant_apply_ht_overrides(
2658 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2659 struct wpa_driver_associate_params *params)
2660{
2661 struct ieee80211_ht_capabilities *htcaps;
2662 struct ieee80211_ht_capabilities *htcaps_mask;
2663
2664 if (!ssid)
2665 return;
2666
2667 params->disable_ht = ssid->disable_ht;
2668 if (!params->htcaps || !params->htcaps_mask)
2669 return;
2670
2671 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2672 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2673 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2674 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2675 ssid->disable_max_amsdu);
2676 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2677 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2678 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002679 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002680}
2681
2682#endif /* CONFIG_HT_OVERRIDES */
2683
2684
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002685#ifdef CONFIG_VHT_OVERRIDES
2686void wpa_supplicant_apply_vht_overrides(
2687 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2688 struct wpa_driver_associate_params *params)
2689{
2690 struct ieee80211_vht_capabilities *vhtcaps;
2691 struct ieee80211_vht_capabilities *vhtcaps_mask;
2692
2693 if (!ssid)
2694 return;
2695
2696 params->disable_vht = ssid->disable_vht;
2697
2698 vhtcaps = (void *) params->vhtcaps;
2699 vhtcaps_mask = (void *) params->vhtcaps_mask;
2700
2701 if (!vhtcaps || !vhtcaps_mask)
2702 return;
2703
2704 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2705 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2706
2707#define OVERRIDE_MCS(i) \
2708 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2709 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2710 3 << 2 * (i - 1); \
2711 vhtcaps->vht_supported_mcs_set.tx_map |= \
2712 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2713 } \
2714 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2715 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2716 3 << 2 * (i - 1); \
2717 vhtcaps->vht_supported_mcs_set.rx_map |= \
2718 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2719 }
2720
2721 OVERRIDE_MCS(1);
2722 OVERRIDE_MCS(2);
2723 OVERRIDE_MCS(3);
2724 OVERRIDE_MCS(4);
2725 OVERRIDE_MCS(5);
2726 OVERRIDE_MCS(6);
2727 OVERRIDE_MCS(7);
2728 OVERRIDE_MCS(8);
2729}
2730#endif /* CONFIG_VHT_OVERRIDES */
2731
2732
Dmitry Shmidt04949592012-07-19 12:16:46 -07002733static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2734{
2735#ifdef PCSC_FUNCS
2736 size_t len;
2737
2738 if (!wpa_s->conf->pcsc_reader)
2739 return 0;
2740
2741 wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
2742 if (!wpa_s->scard)
2743 return 1;
2744
2745 if (wpa_s->conf->pcsc_pin &&
2746 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2747 scard_deinit(wpa_s->scard);
2748 wpa_s->scard = NULL;
2749 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2750 return -1;
2751 }
2752
2753 len = sizeof(wpa_s->imsi) - 1;
2754 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2755 scard_deinit(wpa_s->scard);
2756 wpa_s->scard = NULL;
2757 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2758 return -1;
2759 }
2760 wpa_s->imsi[len] = '\0';
2761
2762 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2763
2764 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2765 wpa_s->imsi, wpa_s->mnc_len);
2766
2767 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2768 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2769#endif /* PCSC_FUNCS */
2770
2771 return 0;
2772}
2773
2774
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002775int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2776{
2777 char *val, *pos;
2778
2779 ext_password_deinit(wpa_s->ext_pw);
2780 wpa_s->ext_pw = NULL;
2781 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2782
2783 if (!wpa_s->conf->ext_password_backend)
2784 return 0;
2785
2786 val = os_strdup(wpa_s->conf->ext_password_backend);
2787 if (val == NULL)
2788 return -1;
2789 pos = os_strchr(val, ':');
2790 if (pos)
2791 *pos++ = '\0';
2792
2793 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2794
2795 wpa_s->ext_pw = ext_password_init(val, pos);
2796 os_free(val);
2797 if (wpa_s->ext_pw == NULL) {
2798 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2799 return -1;
2800 }
2801 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2802
2803 return 0;
2804}
2805
2806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002807static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2808 struct wpa_interface *iface)
2809{
2810 const char *ifname, *driver;
2811 struct wpa_driver_capa capa;
2812
2813 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
2814 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2815 iface->confname ? iface->confname : "N/A",
2816 iface->driver ? iface->driver : "default",
2817 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2818 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2819
2820 if (iface->confname) {
2821#ifdef CONFIG_BACKEND_FILE
2822 wpa_s->confname = os_rel2abs_path(iface->confname);
2823 if (wpa_s->confname == NULL) {
2824 wpa_printf(MSG_ERROR, "Failed to get absolute path "
2825 "for configuration file '%s'.",
2826 iface->confname);
2827 return -1;
2828 }
2829 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
2830 iface->confname, wpa_s->confname);
2831#else /* CONFIG_BACKEND_FILE */
2832 wpa_s->confname = os_strdup(iface->confname);
2833#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002834 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 if (wpa_s->conf == NULL) {
2836 wpa_printf(MSG_ERROR, "Failed to read or parse "
2837 "configuration '%s'.", wpa_s->confname);
2838 return -1;
2839 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002840 wpa_s->confanother = os_rel2abs_path(iface->confanother);
2841 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842
2843 /*
2844 * Override ctrl_interface and driver_param if set on command
2845 * line.
2846 */
2847 if (iface->ctrl_interface) {
2848 os_free(wpa_s->conf->ctrl_interface);
2849 wpa_s->conf->ctrl_interface =
2850 os_strdup(iface->ctrl_interface);
2851 }
2852
2853 if (iface->driver_param) {
2854 os_free(wpa_s->conf->driver_param);
2855 wpa_s->conf->driver_param =
2856 os_strdup(iface->driver_param);
2857 }
2858 } else
2859 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
2860 iface->driver_param);
2861
2862 if (wpa_s->conf == NULL) {
2863 wpa_printf(MSG_ERROR, "\nNo configuration found.");
2864 return -1;
2865 }
2866
2867 if (iface->ifname == NULL) {
2868 wpa_printf(MSG_ERROR, "\nInterface name is required.");
2869 return -1;
2870 }
2871 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
2872 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
2873 iface->ifname);
2874 return -1;
2875 }
2876 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
2877
2878 if (iface->bridge_ifname) {
2879 if (os_strlen(iface->bridge_ifname) >=
2880 sizeof(wpa_s->bridge_ifname)) {
2881 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
2882 "name '%s'.", iface->bridge_ifname);
2883 return -1;
2884 }
2885 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
2886 sizeof(wpa_s->bridge_ifname));
2887 }
2888
2889 /* RSNA Supplicant Key Management - INITIALIZE */
2890 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2891 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2892
2893 /* Initialize driver interface and register driver event handler before
2894 * L2 receive handler so that association events are processed before
2895 * EAPOL-Key packets if both become available for the same select()
2896 * call. */
2897 driver = iface->driver;
2898next_driver:
2899 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2900 return -1;
2901
2902 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2903 if (wpa_s->drv_priv == NULL) {
2904 const char *pos;
2905 pos = driver ? os_strchr(driver, ',') : NULL;
2906 if (pos) {
2907 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2908 "driver interface - try next driver wrapper");
2909 driver = pos + 1;
2910 goto next_driver;
2911 }
2912 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2913 "interface");
2914 return -1;
2915 }
2916 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2917 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2918 "driver_param '%s'", wpa_s->conf->driver_param);
2919 return -1;
2920 }
2921
2922 ifname = wpa_drv_get_ifname(wpa_s);
2923 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2924 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2925 "interface name with '%s'", ifname);
2926 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2927 }
2928
2929 if (wpa_supplicant_init_wpa(wpa_s) < 0)
2930 return -1;
2931
2932 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
2933 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
2934 NULL);
2935 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
2936
2937 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
2938 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
2939 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
2940 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2941 "dot11RSNAConfigPMKLifetime");
2942 return -1;
2943 }
2944
2945 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
2946 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
2947 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
2948 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2949 "dot11RSNAConfigPMKReauthThreshold");
2950 return -1;
2951 }
2952
2953 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
2954 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
2955 wpa_s->conf->dot11RSNAConfigSATimeout)) {
2956 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2957 "dot11RSNAConfigSATimeout");
2958 return -1;
2959 }
2960
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002961 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
2962 &wpa_s->hw.num_modes,
2963 &wpa_s->hw.flags);
2964
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002965 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002966 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002967 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002968 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002969 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002970 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002971 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
2972 wpa_s->sched_scan_supported = capa.sched_scan_supported;
2973 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
2975 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002976 wpa_s->extended_capa = capa.extended_capa;
2977 wpa_s->extended_capa_mask = capa.extended_capa_mask;
2978 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 }
2980 if (wpa_s->max_remain_on_chan == 0)
2981 wpa_s->max_remain_on_chan = 1000;
2982
2983 if (wpa_supplicant_driver_init(wpa_s) < 0)
2984 return -1;
2985
2986#ifdef CONFIG_TDLS
2987 if (wpa_tdls_init(wpa_s->wpa))
2988 return -1;
2989#endif /* CONFIG_TDLS */
2990
2991 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
2992 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
2993 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
2994 return -1;
2995 }
2996
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002997 if (wpas_wps_init(wpa_s))
2998 return -1;
2999
3000 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3001 return -1;
3002 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3003
3004 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3005 if (wpa_s->ctrl_iface == NULL) {
3006 wpa_printf(MSG_ERROR,
3007 "Failed to initialize control interface '%s'.\n"
3008 "You may have another wpa_supplicant process "
3009 "already running or the file was\n"
3010 "left by an unclean termination of wpa_supplicant "
3011 "in which case you will need\n"
3012 "to manually remove this file before starting "
3013 "wpa_supplicant again.\n",
3014 wpa_s->conf->ctrl_interface);
3015 return -1;
3016 }
3017
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003018 wpa_s->gas = gas_query_init(wpa_s);
3019 if (wpa_s->gas == NULL) {
3020 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3021 return -1;
3022 }
3023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003024#ifdef CONFIG_P2P
3025 if (wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
3026 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3027 return -1;
3028 }
3029#endif /* CONFIG_P2P */
3030
3031 if (wpa_bss_init(wpa_s) < 0)
3032 return -1;
3033
Dmitry Shmidt04949592012-07-19 12:16:46 -07003034 if (pcsc_reader_init(wpa_s) < 0)
3035 return -1;
3036
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003037 if (wpas_init_ext_pw(wpa_s) < 0)
3038 return -1;
3039
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003040 return 0;
3041}
3042
3043
3044static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003045 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003047 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 if (wpa_s->drv_priv) {
3049 wpa_supplicant_deauthenticate(wpa_s,
3050 WLAN_REASON_DEAUTH_LEAVING);
3051
3052 wpa_drv_set_countermeasures(wpa_s, 0);
3053 wpa_clear_keys(wpa_s, NULL);
3054 }
3055
3056 wpa_supplicant_cleanup(wpa_s);
3057
Dmitry Shmidt04949592012-07-19 12:16:46 -07003058#ifdef CONFIG_P2P
3059 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3060 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3061 "the management interface is being removed");
3062 wpas_p2p_deinit_global(wpa_s->global);
3063 }
3064#endif /* CONFIG_P2P */
3065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003066 if (wpa_s->drv_priv)
3067 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003068
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003069 if (notify)
3070 wpas_notify_iface_removed(wpa_s);
3071
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003072 if (terminate)
3073 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003074
3075 if (wpa_s->ctrl_iface) {
3076 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3077 wpa_s->ctrl_iface = NULL;
3078 }
3079
3080 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003081 wpa_config_free(wpa_s->conf);
3082 wpa_s->conf = NULL;
3083 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003084
3085 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003086}
3087
3088
3089/**
3090 * wpa_supplicant_add_iface - Add a new network interface
3091 * @global: Pointer to global data from wpa_supplicant_init()
3092 * @iface: Interface configuration options
3093 * Returns: Pointer to the created interface or %NULL on failure
3094 *
3095 * This function is used to add new network interfaces for %wpa_supplicant.
3096 * This can be called before wpa_supplicant_run() to add interfaces before the
3097 * main event loop has been started. In addition, new interfaces can be added
3098 * dynamically while %wpa_supplicant is already running. This could happen,
3099 * e.g., when a hotplug network adapter is inserted.
3100 */
3101struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3102 struct wpa_interface *iface)
3103{
3104 struct wpa_supplicant *wpa_s;
3105 struct wpa_interface t_iface;
3106 struct wpa_ssid *ssid;
3107
3108 if (global == NULL || iface == NULL)
3109 return NULL;
3110
3111 wpa_s = wpa_supplicant_alloc();
3112 if (wpa_s == NULL)
3113 return NULL;
3114
3115 wpa_s->global = global;
3116
3117 t_iface = *iface;
3118 if (global->params.override_driver) {
3119 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3120 "('%s' -> '%s')",
3121 iface->driver, global->params.override_driver);
3122 t_iface.driver = global->params.override_driver;
3123 }
3124 if (global->params.override_ctrl_interface) {
3125 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3126 "ctrl_interface ('%s' -> '%s')",
3127 iface->ctrl_interface,
3128 global->params.override_ctrl_interface);
3129 t_iface.ctrl_interface =
3130 global->params.override_ctrl_interface;
3131 }
3132 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3133 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3134 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003135 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003136 return NULL;
3137 }
3138
3139 /* Notify the control interfaces about new iface */
3140 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003141 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003142 return NULL;
3143 }
3144
3145 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3146 wpas_notify_network_added(wpa_s, ssid);
3147
3148 wpa_s->next = global->ifaces;
3149 global->ifaces = wpa_s;
3150
3151 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003152 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003153
3154 return wpa_s;
3155}
3156
3157
3158/**
3159 * wpa_supplicant_remove_iface - Remove a network interface
3160 * @global: Pointer to global data from wpa_supplicant_init()
3161 * @wpa_s: Pointer to the network interface to be removed
3162 * Returns: 0 if interface was removed, -1 if interface was not found
3163 *
3164 * This function can be used to dynamically remove network interfaces from
3165 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3166 * addition, this function is used to remove all remaining interfaces when
3167 * %wpa_supplicant is terminated.
3168 */
3169int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003170 struct wpa_supplicant *wpa_s,
3171 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003172{
3173 struct wpa_supplicant *prev;
3174
3175 /* Remove interface from the global list of interfaces */
3176 prev = global->ifaces;
3177 if (prev == wpa_s) {
3178 global->ifaces = wpa_s->next;
3179 } else {
3180 while (prev && prev->next != wpa_s)
3181 prev = prev->next;
3182 if (prev == NULL)
3183 return -1;
3184 prev->next = wpa_s->next;
3185 }
3186
3187 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3188
3189 if (global->p2p_group_formation == wpa_s)
3190 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003191 if (global->p2p_invite_group == wpa_s)
3192 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003193 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003194
3195 return 0;
3196}
3197
3198
3199/**
3200 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3201 * @wpa_s: Pointer to the network interface
3202 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3203 */
3204const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3205{
3206 const char *eapol_method;
3207
3208 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3209 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3210 return "NO-EAP";
3211 }
3212
3213 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3214 if (eapol_method == NULL)
3215 return "UNKNOWN-EAP";
3216
3217 return eapol_method;
3218}
3219
3220
3221/**
3222 * wpa_supplicant_get_iface - Get a new network interface
3223 * @global: Pointer to global data from wpa_supplicant_init()
3224 * @ifname: Interface name
3225 * Returns: Pointer to the interface or %NULL if not found
3226 */
3227struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3228 const char *ifname)
3229{
3230 struct wpa_supplicant *wpa_s;
3231
3232 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3233 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3234 return wpa_s;
3235 }
3236 return NULL;
3237}
3238
3239
3240#ifndef CONFIG_NO_WPA_MSG
3241static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3242{
3243 struct wpa_supplicant *wpa_s = ctx;
3244 if (wpa_s == NULL)
3245 return NULL;
3246 return wpa_s->ifname;
3247}
3248#endif /* CONFIG_NO_WPA_MSG */
3249
3250
3251/**
3252 * wpa_supplicant_init - Initialize %wpa_supplicant
3253 * @params: Parameters for %wpa_supplicant
3254 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3255 *
3256 * This function is used to initialize %wpa_supplicant. After successful
3257 * initialization, the returned data pointer can be used to add and remove
3258 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3259 */
3260struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3261{
3262 struct wpa_global *global;
3263 int ret, i;
3264
3265 if (params == NULL)
3266 return NULL;
3267
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003268#ifdef CONFIG_DRIVER_NDIS
3269 {
3270 void driver_ndis_init_ops(void);
3271 driver_ndis_init_ops();
3272 }
3273#endif /* CONFIG_DRIVER_NDIS */
3274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275#ifndef CONFIG_NO_WPA_MSG
3276 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3277#endif /* CONFIG_NO_WPA_MSG */
3278
3279 wpa_debug_open_file(params->wpa_debug_file_path);
3280 if (params->wpa_debug_syslog)
3281 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003282 if (params->wpa_debug_tracing) {
3283 ret = wpa_debug_open_linux_tracing();
3284 if (ret) {
3285 wpa_printf(MSG_ERROR,
3286 "Failed to enable trace logging");
3287 return NULL;
3288 }
3289 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290
3291 ret = eap_register_methods();
3292 if (ret) {
3293 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3294 if (ret == -2)
3295 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3296 "the same EAP type.");
3297 return NULL;
3298 }
3299
3300 global = os_zalloc(sizeof(*global));
3301 if (global == NULL)
3302 return NULL;
3303 dl_list_init(&global->p2p_srv_bonjour);
3304 dl_list_init(&global->p2p_srv_upnp);
3305 global->params.daemonize = params->daemonize;
3306 global->params.wait_for_monitor = params->wait_for_monitor;
3307 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3308 if (params->pid_file)
3309 global->params.pid_file = os_strdup(params->pid_file);
3310 if (params->ctrl_interface)
3311 global->params.ctrl_interface =
3312 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003313 if (params->ctrl_interface_group)
3314 global->params.ctrl_interface_group =
3315 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003316 if (params->override_driver)
3317 global->params.override_driver =
3318 os_strdup(params->override_driver);
3319 if (params->override_ctrl_interface)
3320 global->params.override_ctrl_interface =
3321 os_strdup(params->override_ctrl_interface);
3322 wpa_debug_level = global->params.wpa_debug_level =
3323 params->wpa_debug_level;
3324 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3325 params->wpa_debug_show_keys;
3326 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3327 params->wpa_debug_timestamp;
3328
3329 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3330
3331 if (eloop_init()) {
3332 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3333 wpa_supplicant_deinit(global);
3334 return NULL;
3335 }
3336
Jouni Malinen75ecf522011-06-27 15:19:46 -07003337 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003338
3339 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3340 if (global->ctrl_iface == NULL) {
3341 wpa_supplicant_deinit(global);
3342 return NULL;
3343 }
3344
3345 if (wpas_notify_supplicant_initialized(global)) {
3346 wpa_supplicant_deinit(global);
3347 return NULL;
3348 }
3349
3350 for (i = 0; wpa_drivers[i]; i++)
3351 global->drv_count++;
3352 if (global->drv_count == 0) {
3353 wpa_printf(MSG_ERROR, "No drivers enabled");
3354 wpa_supplicant_deinit(global);
3355 return NULL;
3356 }
3357 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3358 if (global->drv_priv == NULL) {
3359 wpa_supplicant_deinit(global);
3360 return NULL;
3361 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003363#ifdef CONFIG_WIFI_DISPLAY
3364 if (wifi_display_init(global) < 0) {
3365 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3366 wpa_supplicant_deinit(global);
3367 return NULL;
3368 }
3369#endif /* CONFIG_WIFI_DISPLAY */
3370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003371 return global;
3372}
3373
3374
3375/**
3376 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3377 * @global: Pointer to global data from wpa_supplicant_init()
3378 * Returns: 0 after successful event loop run, -1 on failure
3379 *
3380 * This function starts the main event loop and continues running as long as
3381 * there are any remaining events. In most cases, this function is running as
3382 * long as the %wpa_supplicant process in still in use.
3383 */
3384int wpa_supplicant_run(struct wpa_global *global)
3385{
3386 struct wpa_supplicant *wpa_s;
3387
3388 if (global->params.daemonize &&
3389 wpa_supplicant_daemon(global->params.pid_file))
3390 return -1;
3391
3392 if (global->params.wait_for_monitor) {
3393 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3394 if (wpa_s->ctrl_iface)
3395 wpa_supplicant_ctrl_iface_wait(
3396 wpa_s->ctrl_iface);
3397 }
3398
3399 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3400 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3401
3402 eloop_run();
3403
3404 return 0;
3405}
3406
3407
3408/**
3409 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3410 * @global: Pointer to global data from wpa_supplicant_init()
3411 *
3412 * This function is called to deinitialize %wpa_supplicant and to free all
3413 * allocated resources. Remaining network interfaces will also be removed.
3414 */
3415void wpa_supplicant_deinit(struct wpa_global *global)
3416{
3417 int i;
3418
3419 if (global == NULL)
3420 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003421
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003422#ifdef CONFIG_WIFI_DISPLAY
3423 wifi_display_deinit(global);
3424#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425#ifdef CONFIG_P2P
3426 wpas_p2p_deinit_global(global);
3427#endif /* CONFIG_P2P */
3428
3429 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003430 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431
3432 if (global->ctrl_iface)
3433 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3434
3435 wpas_notify_supplicant_deinitialized(global);
3436
3437 eap_peer_unregister_methods();
3438#ifdef CONFIG_AP
3439 eap_server_unregister_methods();
3440#endif /* CONFIG_AP */
3441
3442 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3443 if (!global->drv_priv[i])
3444 continue;
3445 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3446 }
3447 os_free(global->drv_priv);
3448
3449 random_deinit();
3450
3451 eloop_destroy();
3452
3453 if (global->params.pid_file) {
3454 os_daemonize_terminate(global->params.pid_file);
3455 os_free(global->params.pid_file);
3456 }
3457 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003458 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 os_free(global->params.override_driver);
3460 os_free(global->params.override_ctrl_interface);
3461
Dmitry Shmidt04949592012-07-19 12:16:46 -07003462 os_free(global->p2p_disallow_freq);
3463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003464 os_free(global);
3465 wpa_debug_close_syslog();
3466 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003467 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468}
3469
3470
3471void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3472{
3473 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3474 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3475 char country[3];
3476 country[0] = wpa_s->conf->country[0];
3477 country[1] = wpa_s->conf->country[1];
3478 country[2] = '\0';
3479 if (wpa_drv_set_country(wpa_s, country) < 0) {
3480 wpa_printf(MSG_ERROR, "Failed to set country code "
3481 "'%s'", country);
3482 }
3483 }
3484
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003485 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3486 wpas_init_ext_pw(wpa_s);
3487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003488#ifdef CONFIG_WPS
3489 wpas_wps_update_config(wpa_s);
3490#endif /* CONFIG_WPS */
3491
3492#ifdef CONFIG_P2P
3493 wpas_p2p_update_config(wpa_s);
3494#endif /* CONFIG_P2P */
3495
3496 wpa_s->conf->changed_parameters = 0;
3497}
3498
3499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003500static void add_freq(int *freqs, int *num_freqs, int freq)
3501{
3502 int i;
3503
3504 for (i = 0; i < *num_freqs; i++) {
3505 if (freqs[i] == freq)
3506 return;
3507 }
3508
3509 freqs[*num_freqs] = freq;
3510 (*num_freqs)++;
3511}
3512
3513
3514static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3515{
3516 struct wpa_bss *bss, *cbss;
3517 const int max_freqs = 10;
3518 int *freqs;
3519 int num_freqs = 0;
3520
3521 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3522 if (freqs == NULL)
3523 return NULL;
3524
3525 cbss = wpa_s->current_bss;
3526
3527 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3528 if (bss == cbss)
3529 continue;
3530 if (bss->ssid_len == cbss->ssid_len &&
3531 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3532 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3533 add_freq(freqs, &num_freqs, bss->freq);
3534 if (num_freqs == max_freqs)
3535 break;
3536 }
3537 }
3538
3539 if (num_freqs == 0) {
3540 os_free(freqs);
3541 freqs = NULL;
3542 }
3543
3544 return freqs;
3545}
3546
3547
3548void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3549{
3550 int timeout;
3551 int count;
3552 int *freqs = NULL;
3553
3554 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003555 * Remove possible authentication timeout since the connection failed.
3556 */
3557 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3558
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003559 if (wpa_s->disconnected) {
3560 /*
3561 * There is no point in blacklisting the AP if this event is
3562 * generated based on local request to disconnect.
3563 */
3564 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
3565 "indication since interface has been put into "
3566 "disconnected state");
3567 return;
3568 }
3569
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003570 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 * Add the failed BSSID into the blacklist and speed up next scan
3572 * attempt if there could be other APs that could accept association.
3573 * The current blacklist count indicates how many times we have tried
3574 * connecting to this AP and multiple attempts mean that other APs are
3575 * either not available or has already been tried, so that we can start
3576 * increasing the delay here to avoid constant scanning.
3577 */
3578 count = wpa_blacklist_add(wpa_s, bssid);
3579 if (count == 1 && wpa_s->current_bss) {
3580 /*
3581 * This BSS was not in the blacklist before. If there is
3582 * another BSS available for the same ESS, we should try that
3583 * next. Otherwise, we may as well try this one once more
3584 * before allowing other, likely worse, ESSes to be considered.
3585 */
3586 freqs = get_bss_freqs_in_ess(wpa_s);
3587 if (freqs) {
3588 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3589 "has been seen; try it next");
3590 wpa_blacklist_add(wpa_s, bssid);
3591 /*
3592 * On the next scan, go through only the known channels
3593 * used in this ESS based on previous scans to speed up
3594 * common load balancing use case.
3595 */
3596 os_free(wpa_s->next_scan_freqs);
3597 wpa_s->next_scan_freqs = freqs;
3598 }
3599 }
3600
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003601 /*
3602 * Add previous failure count in case the temporary blacklist was
3603 * cleared due to no other BSSes being available.
3604 */
3605 count += wpa_s->extra_blacklist_count;
3606
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003607 if (count > 3 && wpa_s->current_ssid) {
3608 wpa_printf(MSG_DEBUG, "Continuous association failures - "
3609 "consider temporary network disabling");
3610 wpas_auth_failed(wpa_s);
3611 }
3612
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 switch (count) {
3614 case 1:
3615 timeout = 100;
3616 break;
3617 case 2:
3618 timeout = 500;
3619 break;
3620 case 3:
3621 timeout = 1000;
3622 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003623 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003625 break;
3626 default:
3627 timeout = 10000;
3628 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 }
3630
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003631 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3632 "ms", count, timeout);
3633
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 /*
3635 * TODO: if more than one possible AP is available in scan results,
3636 * could try the other ones before requesting a new scan.
3637 */
3638 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3639 1000 * (timeout % 1000));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003640
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07003641 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003643
3644
3645int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3646{
3647 return wpa_s->conf->ap_scan == 2 ||
3648 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3649}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003650
Dmitry Shmidt04949592012-07-19 12:16:46 -07003651
3652#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3653int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3654 struct wpa_ssid *ssid,
3655 const char *field,
3656 const char *value)
3657{
3658#ifdef IEEE8021X_EAPOL
3659 struct eap_peer_config *eap = &ssid->eap;
3660
3661 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3662 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3663 (const u8 *) value, os_strlen(value));
3664
3665 switch (wpa_supplicant_ctrl_req_from_string(field)) {
3666 case WPA_CTRL_REQ_EAP_IDENTITY:
3667 os_free(eap->identity);
3668 eap->identity = (u8 *) os_strdup(value);
3669 eap->identity_len = os_strlen(value);
3670 eap->pending_req_identity = 0;
3671 if (ssid == wpa_s->current_ssid)
3672 wpa_s->reassociate = 1;
3673 break;
3674 case WPA_CTRL_REQ_EAP_PASSWORD:
3675 os_free(eap->password);
3676 eap->password = (u8 *) os_strdup(value);
3677 eap->password_len = os_strlen(value);
3678 eap->pending_req_password = 0;
3679 if (ssid == wpa_s->current_ssid)
3680 wpa_s->reassociate = 1;
3681 break;
3682 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3683 os_free(eap->new_password);
3684 eap->new_password = (u8 *) os_strdup(value);
3685 eap->new_password_len = os_strlen(value);
3686 eap->pending_req_new_password = 0;
3687 if (ssid == wpa_s->current_ssid)
3688 wpa_s->reassociate = 1;
3689 break;
3690 case WPA_CTRL_REQ_EAP_PIN:
3691 os_free(eap->pin);
3692 eap->pin = os_strdup(value);
3693 eap->pending_req_pin = 0;
3694 if (ssid == wpa_s->current_ssid)
3695 wpa_s->reassociate = 1;
3696 break;
3697 case WPA_CTRL_REQ_EAP_OTP:
3698 os_free(eap->otp);
3699 eap->otp = (u8 *) os_strdup(value);
3700 eap->otp_len = os_strlen(value);
3701 os_free(eap->pending_req_otp);
3702 eap->pending_req_otp = NULL;
3703 eap->pending_req_otp_len = 0;
3704 break;
3705 case WPA_CTRL_REQ_EAP_PASSPHRASE:
3706 os_free(eap->private_key_passwd);
3707 eap->private_key_passwd = (u8 *) os_strdup(value);
3708 eap->pending_req_passphrase = 0;
3709 if (ssid == wpa_s->current_ssid)
3710 wpa_s->reassociate = 1;
3711 break;
3712 default:
3713 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3714 return -1;
3715 }
3716
3717 return 0;
3718#else /* IEEE8021X_EAPOL */
3719 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3720 return -1;
3721#endif /* IEEE8021X_EAPOL */
3722}
3723#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3724
3725
3726int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3727{
3728 int i;
3729 unsigned int drv_enc;
3730
3731 if (ssid == NULL)
3732 return 1;
3733
3734 if (ssid->disabled)
3735 return 1;
3736
3737 if (wpa_s && wpa_s->drv_capa_known)
3738 drv_enc = wpa_s->drv_enc;
3739 else
3740 drv_enc = (unsigned int) -1;
3741
3742 for (i = 0; i < NUM_WEP_KEYS; i++) {
3743 size_t len = ssid->wep_key_len[i];
3744 if (len == 0)
3745 continue;
3746 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3747 continue;
3748 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3749 continue;
3750 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3751 continue;
3752 return 1; /* invalid WEP key */
3753 }
3754
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003755 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
3756 !ssid->ext_psk)
3757 return 1;
3758
Dmitry Shmidt04949592012-07-19 12:16:46 -07003759 return 0;
3760}
3761
3762
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003763int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003764{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003765 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003766 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003767 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003768 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003769 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003770}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003771
3772
3773void wpas_auth_failed(struct wpa_supplicant *wpa_s)
3774{
3775 struct wpa_ssid *ssid = wpa_s->current_ssid;
3776 int dur;
3777 struct os_time now;
3778
3779 if (ssid == NULL) {
3780 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3781 "SSID block");
3782 return;
3783 }
3784
3785 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3786 return;
3787
3788 ssid->auth_failures++;
3789 if (ssid->auth_failures > 50)
3790 dur = 300;
3791 else if (ssid->auth_failures > 20)
3792 dur = 120;
3793 else if (ssid->auth_failures > 10)
3794 dur = 60;
3795 else if (ssid->auth_failures > 5)
3796 dur = 30;
3797 else if (ssid->auth_failures > 1)
3798 dur = 20;
3799 else
3800 dur = 10;
3801
3802 os_get_time(&now);
3803 if (now.sec + dur <= ssid->disabled_until.sec)
3804 return;
3805
3806 ssid->disabled_until.sec = now.sec + dur;
3807
3808 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
3809 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
3810 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
3811 ssid->auth_failures, dur);
3812}
3813
3814
3815void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
3816 struct wpa_ssid *ssid, int clear_failures)
3817{
3818 if (ssid == NULL)
3819 return;
3820
3821 if (ssid->disabled_until.sec) {
3822 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
3823 "id=%d ssid=\"%s\"",
3824 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3825 }
3826 ssid->disabled_until.sec = 0;
3827 ssid->disabled_until.usec = 0;
3828 if (clear_failures)
3829 ssid->auth_failures = 0;
3830}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003831
3832
3833int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
3834{
3835 size_t i;
3836
3837 if (wpa_s->disallow_aps_bssid == NULL)
3838 return 0;
3839
3840 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
3841 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
3842 bssid, ETH_ALEN) == 0)
3843 return 1;
3844 }
3845
3846 return 0;
3847}
3848
3849
3850int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
3851 size_t ssid_len)
3852{
3853 size_t i;
3854
3855 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
3856 return 0;
3857
3858 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
3859 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
3860 if (ssid_len == s->ssid_len &&
3861 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3862 return 1;
3863 }
3864
3865 return 0;
3866}
3867
3868
3869/**
3870 * wpas_request_connection - Request a new connection
3871 * @wpa_s: Pointer to the network interface
3872 *
3873 * This function is used to request a new connection to be found. It will mark
3874 * the interface to allow reassociation and request a new scan to find a
3875 * suitable network to connect to.
3876 */
3877void wpas_request_connection(struct wpa_supplicant *wpa_s)
3878{
3879 wpa_s->normal_scans = 0;
3880 wpa_supplicant_reinit_autoscan(wpa_s);
3881 wpa_s->extra_blacklist_count = 0;
3882 wpa_s->disconnected = 0;
3883 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08003884
3885 if (wpa_supplicant_fast_associate(wpa_s) != 1)
3886 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003887}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003888
3889
3890/**
3891 * wpas_wpa_is_in_progress - Check whether a connection is in progress
3892 * @wpa_s: Pointer to wpa_supplicant data
3893 *
3894 * This function is to check if the wpa state is in beginning of the connection
3895 * during 4-way handshake or group key handshake with WPA on any shared
3896 * interface.
3897 */
3898int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
3899{
3900 const char *rn, *rn2;
3901 struct wpa_supplicant *ifs;
3902
3903 if (!wpa_s->driver->get_radio_name)
3904 return 0;
3905
3906 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3907 if (rn == NULL || rn[0] == '\0')
3908 return 0;
3909
3910 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3911 if (ifs == wpa_s || !ifs->driver->get_radio_name)
3912 continue;
3913
3914 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
3915 if (!rn2 || os_strcmp(rn, rn2) != 0)
3916 continue;
3917 if (ifs->wpa_state >= WPA_AUTHENTICATING &&
3918 ifs->wpa_state != WPA_COMPLETED) {
3919 wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
3920 "on interface %s - defer scan", ifs->ifname);
3921 return 1;
3922 }
3923 }
3924
3925 return 0;
3926}