blob: f6b881b1533369e80d77db58b51f1af918c0d740 [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"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070020#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "eap_server/eap_methods.h"
22#include "rsn_supp/wpa.h"
23#include "eloop.h"
24#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070025#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "l2_packet/l2_packet.h"
27#include "wpa_supplicant_i.h"
28#include "driver_i.h"
29#include "ctrl_iface.h"
30#include "pcsc_funcs.h"
31#include "common/version.h"
32#include "rsn_supp/preauth.h"
33#include "rsn_supp/pmksa_cache.h"
34#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035#include "common/ieee802_11_defs.h"
36#include "p2p/p2p.h"
37#include "blacklist.h"
38#include "wpas_glue.h"
39#include "wps_supplicant.h"
40#include "ibss_rsn.h"
41#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "ap.h"
44#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070045#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "notify.h"
47#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070048#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "bss.h"
50#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080051#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070052#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070053#include "wnm_sta.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054
55const char *wpa_supplicant_version =
56"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080057"Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058
59const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080060"This software may be distributed under the terms of the BSD license.\n"
61"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062#ifdef EAP_TLS_OPENSSL
63"\nThis product includes software developed by the OpenSSL Project\n"
64"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
65#endif /* EAP_TLS_OPENSSL */
66;
67
68#ifndef CONFIG_NO_STDOUT_DEBUG
69/* Long text divided into parts in order to fit in C89 strings size limits. */
70const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080071"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080073"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074"\n"
75"Redistribution and use in source and binary forms, with or without\n"
76"modification, are permitted provided that the following conditions are\n"
77"met:\n"
78"\n";
79const char *wpa_supplicant_full_license3 =
80"1. Redistributions of source code must retain the above copyright\n"
81" notice, this list of conditions and the following disclaimer.\n"
82"\n"
83"2. Redistributions in binary form must reproduce the above copyright\n"
84" notice, this list of conditions and the following disclaimer in the\n"
85" documentation and/or other materials provided with the distribution.\n"
86"\n";
87const char *wpa_supplicant_full_license4 =
88"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
89" names of its contributors may be used to endorse or promote products\n"
90" derived from this software without specific prior written permission.\n"
91"\n"
92"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
93"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
94"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
95"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
96const char *wpa_supplicant_full_license5 =
97"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
98"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
99"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
100"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
101"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
102"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
103"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
104"\n";
105#endif /* CONFIG_NO_STDOUT_DEBUG */
106
107extern int wpa_debug_level;
108extern int wpa_debug_show_keys;
109extern int wpa_debug_timestamp;
110extern struct wpa_driver_ops *wpa_drivers[];
111
112/* Configure default/group WEP keys for static WEP */
113int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
114{
115 int i, set = 0;
116
117 for (i = 0; i < NUM_WEP_KEYS; i++) {
118 if (ssid->wep_key_len[i] == 0)
119 continue;
120
121 set = 1;
122 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
123 i, i == ssid->wep_tx_keyidx, NULL, 0,
124 ssid->wep_key[i], ssid->wep_key_len[i]);
125 }
126
127 return set;
128}
129
130
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700131int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
132 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700133{
134 u8 key[32];
135 size_t keylen;
136 enum wpa_alg alg;
137 u8 seq[6] = { 0 };
138
139 /* IBSS/WPA-None uses only one key (Group) for both receiving and
140 * sending unicast and multicast packets. */
141
142 if (ssid->mode != WPAS_MODE_IBSS) {
143 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
144 "IBSS/ad-hoc) for WPA-None", ssid->mode);
145 return -1;
146 }
147
148 if (!ssid->psk_set) {
149 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
150 "WPA-None");
151 return -1;
152 }
153
154 switch (wpa_s->group_cipher) {
155 case WPA_CIPHER_CCMP:
156 os_memcpy(key, ssid->psk, 16);
157 keylen = 16;
158 alg = WPA_ALG_CCMP;
159 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700160 case WPA_CIPHER_GCMP:
161 os_memcpy(key, ssid->psk, 16);
162 keylen = 16;
163 alg = WPA_ALG_GCMP;
164 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700165 case WPA_CIPHER_TKIP:
166 /* WPA-None uses the same Michael MIC key for both TX and RX */
167 os_memcpy(key, ssid->psk, 16 + 8);
168 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
169 keylen = 32;
170 alg = WPA_ALG_TKIP;
171 break;
172 default:
173 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
174 "WPA-None", wpa_s->group_cipher);
175 return -1;
176 }
177
178 /* TODO: should actually remember the previously used seq#, both for TX
179 * and RX from each STA.. */
180
181 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
182}
183
184
185static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
186{
187 struct wpa_supplicant *wpa_s = eloop_ctx;
188 const u8 *bssid = wpa_s->bssid;
189 if (is_zero_ether_addr(bssid))
190 bssid = wpa_s->pending_bssid;
191 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
192 MAC2STR(bssid));
193 wpa_blacklist_add(wpa_s, bssid);
194 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800195 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700196 wpa_s->reassociate = 1;
197
198 /*
199 * If we timed out, the AP or the local radio may be busy.
200 * So, wait a second until scanning again.
201 */
202 wpa_supplicant_req_scan(wpa_s, 1, 0);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700203
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -0700204 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700205}
206
207
208/**
209 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
210 * @wpa_s: Pointer to wpa_supplicant data
211 * @sec: Number of seconds after which to time out authentication
212 * @usec: Number of microseconds after which to time out authentication
213 *
214 * This function is used to schedule a timeout for the current authentication
215 * attempt.
216 */
217void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
218 int sec, int usec)
219{
220 if (wpa_s->conf && wpa_s->conf->ap_scan == 0 &&
221 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
222 return;
223
224 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
225 "%d usec", sec, usec);
226 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
227 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
228}
229
230
231/**
232 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
233 * @wpa_s: Pointer to wpa_supplicant data
234 *
235 * This function is used to cancel authentication timeout scheduled with
236 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
237 * been completed.
238 */
239void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
240{
241 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
242 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
243 wpa_blacklist_del(wpa_s, wpa_s->bssid);
244}
245
246
247/**
248 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
249 * @wpa_s: Pointer to wpa_supplicant data
250 *
251 * This function is used to configure EAPOL state machine based on the selected
252 * authentication mode.
253 */
254void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
255{
256#ifdef IEEE8021X_EAPOL
257 struct eapol_config eapol_conf;
258 struct wpa_ssid *ssid = wpa_s->current_ssid;
259
260#ifdef CONFIG_IBSS_RSN
261 if (ssid->mode == WPAS_MODE_IBSS &&
262 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
263 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
264 /*
265 * RSN IBSS authentication is per-STA and we can disable the
266 * per-BSSID EAPOL authentication.
267 */
268 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
269 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
270 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
271 return;
272 }
273#endif /* CONFIG_IBSS_RSN */
274
275 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
276 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
277
278 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
279 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
280 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
281 else
282 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
283
284 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
286 eapol_conf.accept_802_1x_keys = 1;
287 eapol_conf.required_keys = 0;
288 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
289 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
290 }
291 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
292 eapol_conf.required_keys |=
293 EAPOL_REQUIRE_KEY_BROADCAST;
294 }
295
296 if (wpa_s->conf && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
297 eapol_conf.required_keys = 0;
298 }
299 if (wpa_s->conf)
300 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
301 eapol_conf.workaround = ssid->eap_workaround;
302 eapol_conf.eap_disabled =
303 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
304 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
305 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
306 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
307#endif /* IEEE8021X_EAPOL */
308}
309
310
311/**
312 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
313 * @wpa_s: Pointer to wpa_supplicant data
314 * @ssid: Configuration data for the network
315 *
316 * This function is used to configure WPA state machine and related parameters
317 * to a mode where WPA is not enabled. This is called as part of the
318 * authentication configuration when the selected network does not use WPA.
319 */
320void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
321 struct wpa_ssid *ssid)
322{
323 int i;
324
325 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
326 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
327 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
328 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
329 else
330 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
331 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
332 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
333 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
334 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
335 wpa_s->group_cipher = WPA_CIPHER_NONE;
336 wpa_s->mgmt_group_cipher = 0;
337
338 for (i = 0; i < NUM_WEP_KEYS; i++) {
339 if (ssid->wep_key_len[i] > 5) {
340 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
341 wpa_s->group_cipher = WPA_CIPHER_WEP104;
342 break;
343 } else if (ssid->wep_key_len[i] > 0) {
344 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
345 wpa_s->group_cipher = WPA_CIPHER_WEP40;
346 break;
347 }
348 }
349
350 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
351 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
352 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
353 wpa_s->pairwise_cipher);
354 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
355#ifdef CONFIG_IEEE80211W
356 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
357 wpa_s->mgmt_group_cipher);
358#endif /* CONFIG_IEEE80211W */
359
360 pmksa_cache_clear_current(wpa_s->wpa);
361}
362
363
Dmitry Shmidt04949592012-07-19 12:16:46 -0700364void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800365{
366 int i;
367 if (wpa_s->hw.modes == NULL)
368 return;
369
370 for (i = 0; i < wpa_s->hw.num_modes; i++) {
371 os_free(wpa_s->hw.modes[i].channels);
372 os_free(wpa_s->hw.modes[i].rates);
373 }
374
375 os_free(wpa_s->hw.modes);
376 wpa_s->hw.modes = NULL;
377}
378
379
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700380static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
381{
382 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700383 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700384 scard_deinit(wpa_s->scard);
385 wpa_s->scard = NULL;
386 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
387 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
388 l2_packet_deinit(wpa_s->l2);
389 wpa_s->l2 = NULL;
390 if (wpa_s->l2_br) {
391 l2_packet_deinit(wpa_s->l2_br);
392 wpa_s->l2_br = NULL;
393 }
394
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700395 if (wpa_s->conf != NULL) {
396 struct wpa_ssid *ssid;
397 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
398 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399 }
400
401 os_free(wpa_s->confname);
402 wpa_s->confname = NULL;
403
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700404 os_free(wpa_s->confanother);
405 wpa_s->confanother = NULL;
406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700407 wpa_sm_set_eapol(wpa_s->wpa, NULL);
408 eapol_sm_deinit(wpa_s->eapol);
409 wpa_s->eapol = NULL;
410
411 rsn_preauth_deinit(wpa_s->wpa);
412
413#ifdef CONFIG_TDLS
414 wpa_tdls_deinit(wpa_s->wpa);
415#endif /* CONFIG_TDLS */
416
417 pmksa_candidate_free(wpa_s->wpa);
418 wpa_sm_deinit(wpa_s->wpa);
419 wpa_s->wpa = NULL;
420 wpa_blacklist_clear(wpa_s);
421
422 wpa_bss_deinit(wpa_s);
423
424 wpa_supplicant_cancel_scan(wpa_s);
425 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800426 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
427#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
428 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
429 wpa_s, NULL);
430#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431
432 wpas_wps_deinit(wpa_s);
433
434 wpabuf_free(wpa_s->pending_eapol_rx);
435 wpa_s->pending_eapol_rx = NULL;
436
437#ifdef CONFIG_IBSS_RSN
438 ibss_rsn_deinit(wpa_s->ibss_rsn);
439 wpa_s->ibss_rsn = NULL;
440#endif /* CONFIG_IBSS_RSN */
441
442 sme_deinit(wpa_s);
443
444#ifdef CONFIG_AP
445 wpa_supplicant_ap_deinit(wpa_s);
446#endif /* CONFIG_AP */
447
448#ifdef CONFIG_P2P
449 wpas_p2p_deinit(wpa_s);
450#endif /* CONFIG_P2P */
451
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800452#ifdef CONFIG_OFFCHANNEL
453 offchannel_deinit(wpa_s);
454#endif /* CONFIG_OFFCHANNEL */
455
456 wpa_supplicant_cancel_sched_scan(wpa_s);
457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700458 os_free(wpa_s->next_scan_freqs);
459 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800460
461 gas_query_deinit(wpa_s->gas);
462 wpa_s->gas = NULL;
463
464 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700465
466 os_free(wpa_s->bssid_filter);
467 wpa_s->bssid_filter = NULL;
468
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800469 os_free(wpa_s->disallow_aps_bssid);
470 wpa_s->disallow_aps_bssid = NULL;
471 os_free(wpa_s->disallow_aps_ssid);
472 wpa_s->disallow_aps_ssid = NULL;
473
Dmitry Shmidt04949592012-07-19 12:16:46 -0700474 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700475#ifdef CONFIG_WNM
476 wnm_deallocate_memory(wpa_s);
477#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700478
479 ext_password_deinit(wpa_s->ext_pw);
480 wpa_s->ext_pw = NULL;
481
482 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700483
484 os_free(wpa_s->last_scan_res);
485 wpa_s->last_scan_res = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486}
487
488
489/**
490 * wpa_clear_keys - Clear keys configured for the driver
491 * @wpa_s: Pointer to wpa_supplicant data
492 * @addr: Previously used BSSID or %NULL if not available
493 *
494 * This function clears the encryption keys that has been previously configured
495 * for the driver.
496 */
497void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
498{
499 if (wpa_s->keys_cleared) {
500 /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
501 * timing issues with keys being cleared just before new keys
502 * are set or just after association or something similar. This
503 * shows up in group key handshake failing often because of the
504 * client not receiving the first encrypted packets correctly.
505 * Skipping some of the extra key clearing steps seems to help
506 * in completing group key handshake more reliably. */
507 wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
508 "skip key clearing");
509 return;
510 }
511
512 /* MLME-DELETEKEYS.request */
513 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
514 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
515 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
516 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
517#ifdef CONFIG_IEEE80211W
518 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
519 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
520#endif /* CONFIG_IEEE80211W */
521 if (addr) {
522 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
523 0);
524 /* MLME-SETPROTECTION.request(None) */
525 wpa_drv_mlme_setprotection(
526 wpa_s, addr,
527 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
528 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
529 }
530 wpa_s->keys_cleared = 1;
531}
532
533
534/**
535 * wpa_supplicant_state_txt - Get the connection state name as a text string
536 * @state: State (wpa_state; WPA_*)
537 * Returns: The state name as a printable text string
538 */
539const char * wpa_supplicant_state_txt(enum wpa_states state)
540{
541 switch (state) {
542 case WPA_DISCONNECTED:
543 return "DISCONNECTED";
544 case WPA_INACTIVE:
545 return "INACTIVE";
546 case WPA_INTERFACE_DISABLED:
547 return "INTERFACE_DISABLED";
548 case WPA_SCANNING:
549 return "SCANNING";
550 case WPA_AUTHENTICATING:
551 return "AUTHENTICATING";
552 case WPA_ASSOCIATING:
553 return "ASSOCIATING";
554 case WPA_ASSOCIATED:
555 return "ASSOCIATED";
556 case WPA_4WAY_HANDSHAKE:
557 return "4WAY_HANDSHAKE";
558 case WPA_GROUP_HANDSHAKE:
559 return "GROUP_HANDSHAKE";
560 case WPA_COMPLETED:
561 return "COMPLETED";
562 default:
563 return "UNKNOWN";
564 }
565}
566
567
568#ifdef CONFIG_BGSCAN
569
570static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
571{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800572 if (wpas_driver_bss_selection(wpa_s))
573 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700574 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
575 return;
576
577 bgscan_deinit(wpa_s);
578 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
579 if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
580 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
581 "bgscan");
582 /*
583 * Live without bgscan; it is only used as a roaming
584 * optimization, so the initial connection is not
585 * affected.
586 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700587 } else {
588 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700589 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700590 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
591 0);
592 if (scan_res) {
593 bgscan_notify_scan(wpa_s, scan_res);
594 wpa_scan_results_free(scan_res);
595 }
596 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 } else
598 wpa_s->bgscan_ssid = NULL;
599}
600
601
602static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
603{
604 if (wpa_s->bgscan_ssid != NULL) {
605 bgscan_deinit(wpa_s);
606 wpa_s->bgscan_ssid = NULL;
607 }
608}
609
610#endif /* CONFIG_BGSCAN */
611
612
Dmitry Shmidt04949592012-07-19 12:16:46 -0700613static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
614{
615 if (autoscan_init(wpa_s, 0))
616 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
617}
618
619
620static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
621{
622 autoscan_deinit(wpa_s);
623}
624
625
626void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
627{
628 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
629 wpa_s->wpa_state == WPA_SCANNING) {
630 autoscan_deinit(wpa_s);
631 wpa_supplicant_start_autoscan(wpa_s);
632 }
633}
634
635
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700636/**
637 * wpa_supplicant_set_state - Set current connection state
638 * @wpa_s: Pointer to wpa_supplicant data
639 * @state: The new connection state
640 *
641 * This function is called whenever the connection state changes, e.g.,
642 * association is completed for WPA/WPA2 4-Way Handshake is started.
643 */
644void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
645 enum wpa_states state)
646{
647 enum wpa_states old_state = wpa_s->wpa_state;
648
649 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
650 wpa_supplicant_state_txt(wpa_s->wpa_state),
651 wpa_supplicant_state_txt(state));
652
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700653#ifdef ANDROID_P2P
Irfan Sheriff7db4ef72012-06-18 09:39:07 -0700654 if(state == WPA_ASSOCIATED && wpa_s->current_ssid) {
655 wpa_s->current_ssid->assoc_retry = 0;
656 }
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700657#endif /* ANDROID_P2P */
658
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700659 if (state != WPA_SCANNING)
660 wpa_supplicant_notify_scanning(wpa_s, 0);
661
662 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700664#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800666 MACSTR " completed (auth) [id=%d id_str=%s]",
667 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668 ssid ? ssid->id : -1,
669 ssid && ssid->id_str ? ssid->id_str : "");
670#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700671 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800672 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700674 wpa_drv_set_operstate(wpa_s, 1);
675#ifndef IEEE8021X_EAPOL
676 wpa_drv_set_supp_port(wpa_s, 1);
677#endif /* IEEE8021X_EAPOL */
678 wpa_s->after_wps = 0;
679#ifdef CONFIG_P2P
680 wpas_p2p_completed(wpa_s);
681#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700682
683 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
685 state == WPA_ASSOCIATED) {
686 wpa_s->new_connection = 1;
687 wpa_drv_set_operstate(wpa_s, 0);
688#ifndef IEEE8021X_EAPOL
689 wpa_drv_set_supp_port(wpa_s, 0);
690#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700691 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 }
693 wpa_s->wpa_state = state;
694
695#ifdef CONFIG_BGSCAN
696 if (state == WPA_COMPLETED)
697 wpa_supplicant_start_bgscan(wpa_s);
698 else
699 wpa_supplicant_stop_bgscan(wpa_s);
700#endif /* CONFIG_BGSCAN */
701
Dmitry Shmidt04949592012-07-19 12:16:46 -0700702 if (state == WPA_AUTHENTICATING)
703 wpa_supplicant_stop_autoscan(wpa_s);
704
705 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
706 wpa_supplicant_start_autoscan(wpa_s);
707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708 if (wpa_s->wpa_state != old_state) {
709 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
710
711 if (wpa_s->wpa_state == WPA_COMPLETED ||
712 old_state == WPA_COMPLETED)
713 wpas_notify_auth_changed(wpa_s);
714 }
715}
716
717
718void wpa_supplicant_terminate_proc(struct wpa_global *global)
719{
720 int pending = 0;
721#ifdef CONFIG_WPS
722 struct wpa_supplicant *wpa_s = global->ifaces;
723 while (wpa_s) {
724 if (wpas_wps_terminate_pending(wpa_s) == 1)
725 pending = 1;
726 wpa_s = wpa_s->next;
727 }
728#endif /* CONFIG_WPS */
729 if (pending)
730 return;
731 eloop_terminate();
732}
733
734
735static void wpa_supplicant_terminate(int sig, void *signal_ctx)
736{
737 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 wpa_supplicant_terminate_proc(global);
739}
740
741
742void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
743{
744 enum wpa_states old_state = wpa_s->wpa_state;
745
746 wpa_s->pairwise_cipher = 0;
747 wpa_s->group_cipher = 0;
748 wpa_s->mgmt_group_cipher = 0;
749 wpa_s->key_mgmt = 0;
750 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700751 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700752
753 if (wpa_s->wpa_state != old_state)
754 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
755}
756
757
758/**
759 * wpa_supplicant_reload_configuration - Reload configuration data
760 * @wpa_s: Pointer to wpa_supplicant data
761 * Returns: 0 on success or -1 if configuration parsing failed
762 *
763 * This function can be used to request that the configuration data is reloaded
764 * (e.g., after configuration file change). This function is reloading
765 * configuration only for one interface, so this may need to be called multiple
766 * times if %wpa_supplicant is controlling multiple interfaces and all
767 * interfaces need reconfiguration.
768 */
769int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
770{
771 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 int reconf_ctrl;
773 int old_ap_scan;
774
775 if (wpa_s->confname == NULL)
776 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700777 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778 if (conf == NULL) {
779 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
780 "file '%s' - exiting", wpa_s->confname);
781 return -1;
782 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700783 wpa_config_read(wpa_s->confanother, conf);
784
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 conf->changed_parameters = (unsigned int) -1;
786
787 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
788 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
789 os_strcmp(conf->ctrl_interface,
790 wpa_s->conf->ctrl_interface) != 0);
791
792 if (reconf_ctrl && wpa_s->ctrl_iface) {
793 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
794 wpa_s->ctrl_iface = NULL;
795 }
796
797 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800798 if (wpa_s->current_ssid) {
799 wpa_supplicant_deauthenticate(wpa_s,
800 WLAN_REASON_DEAUTH_LEAVING);
801 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802
803 /*
804 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
805 * pkcs11_engine_path, pkcs11_module_path.
806 */
807 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
808 /*
809 * Clear forced success to clear EAP state for next
810 * authentication.
811 */
812 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
813 }
814 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
815 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800816 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700817 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
818 rsn_preauth_deinit(wpa_s->wpa);
819
820 old_ap_scan = wpa_s->conf->ap_scan;
821 wpa_config_free(wpa_s->conf);
822 wpa_s->conf = conf;
823 if (old_ap_scan != wpa_s->conf->ap_scan)
824 wpas_notify_ap_scan_changed(wpa_s);
825
826 if (reconf_ctrl)
827 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
828
829 wpa_supplicant_update_config(wpa_s);
830
831 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700832 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 wpa_s->reassociate = 1;
834 wpa_supplicant_req_scan(wpa_s, 0, 0);
835 }
836 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
837 return 0;
838}
839
840
841static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
842{
843 struct wpa_global *global = signal_ctx;
844 struct wpa_supplicant *wpa_s;
845 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
846 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
847 sig);
848 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
849 wpa_supplicant_terminate_proc(global);
850 }
851 }
852}
853
854
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
856{
857 switch (key_mgmt) {
858 case WPA_KEY_MGMT_NONE:
859 return KEY_MGMT_NONE;
860 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
861 return KEY_MGMT_802_1X_NO_WPA;
862 case WPA_KEY_MGMT_IEEE8021X:
863 return KEY_MGMT_802_1X;
864 case WPA_KEY_MGMT_WPA_NONE:
865 return KEY_MGMT_WPA_NONE;
866 case WPA_KEY_MGMT_FT_IEEE8021X:
867 return KEY_MGMT_FT_802_1X;
868 case WPA_KEY_MGMT_FT_PSK:
869 return KEY_MGMT_FT_PSK;
870 case WPA_KEY_MGMT_IEEE8021X_SHA256:
871 return KEY_MGMT_802_1X_SHA256;
872 case WPA_KEY_MGMT_PSK_SHA256:
873 return KEY_MGMT_PSK_SHA256;
874 case WPA_KEY_MGMT_WPS:
875 return KEY_MGMT_WPS;
876 case WPA_KEY_MGMT_PSK:
877 default:
878 return KEY_MGMT_PSK;
879 }
880}
881
882
883static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
884 struct wpa_ssid *ssid,
885 struct wpa_ie_data *ie)
886{
887 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
888 if (ret) {
889 if (ret == -2) {
890 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
891 "from association info");
892 }
893 return -1;
894 }
895
896 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
897 "cipher suites");
898 if (!(ie->group_cipher & ssid->group_cipher)) {
899 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
900 "cipher 0x%x (mask 0x%x) - reject",
901 ie->group_cipher, ssid->group_cipher);
902 return -1;
903 }
904 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
905 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
906 "cipher 0x%x (mask 0x%x) - reject",
907 ie->pairwise_cipher, ssid->pairwise_cipher);
908 return -1;
909 }
910 if (!(ie->key_mgmt & ssid->key_mgmt)) {
911 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
912 "management 0x%x (mask 0x%x) - reject",
913 ie->key_mgmt, ssid->key_mgmt);
914 return -1;
915 }
916
917#ifdef CONFIG_IEEE80211W
918 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800919 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
920 wpa_s->conf->pmf : ssid->ieee80211w) ==
921 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
923 "that does not support management frame protection - "
924 "reject");
925 return -1;
926 }
927#endif /* CONFIG_IEEE80211W */
928
929 return 0;
930}
931
932
933/**
934 * wpa_supplicant_set_suites - Set authentication and encryption parameters
935 * @wpa_s: Pointer to wpa_supplicant data
936 * @bss: Scan results for the selected BSS, or %NULL if not available
937 * @ssid: Configuration data for the selected network
938 * @wpa_ie: Buffer for the WPA/RSN IE
939 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
940 * used buffer length in case the functions returns success.
941 * Returns: 0 on success or -1 on failure
942 *
943 * This function is used to configure authentication and encryption parameters
944 * based on the network configuration and scan result for the selected BSS (if
945 * available).
946 */
947int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
948 struct wpa_bss *bss, struct wpa_ssid *ssid,
949 u8 *wpa_ie, size_t *wpa_ie_len)
950{
951 struct wpa_ie_data ie;
952 int sel, proto;
953 const u8 *bss_wpa, *bss_rsn;
954
955 if (bss) {
956 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
957 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
958 } else
959 bss_wpa = bss_rsn = NULL;
960
961 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
962 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
963 (ie.group_cipher & ssid->group_cipher) &&
964 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
965 (ie.key_mgmt & ssid->key_mgmt)) {
966 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
967 proto = WPA_PROTO_RSN;
968 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
969 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
970 (ie.group_cipher & ssid->group_cipher) &&
971 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
972 (ie.key_mgmt & ssid->key_mgmt)) {
973 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
974 proto = WPA_PROTO_WPA;
975 } else if (bss) {
976 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
977 return -1;
978 } else {
979 if (ssid->proto & WPA_PROTO_RSN)
980 proto = WPA_PROTO_RSN;
981 else
982 proto = WPA_PROTO_WPA;
983 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
984 os_memset(&ie, 0, sizeof(ie));
985 ie.group_cipher = ssid->group_cipher;
986 ie.pairwise_cipher = ssid->pairwise_cipher;
987 ie.key_mgmt = ssid->key_mgmt;
988#ifdef CONFIG_IEEE80211W
989 ie.mgmt_group_cipher =
990 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
991 WPA_CIPHER_AES_128_CMAC : 0;
992#endif /* CONFIG_IEEE80211W */
993 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
994 "based on configuration");
995 } else
996 proto = ie.proto;
997 }
998
999 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1000 "pairwise %d key_mgmt %d proto %d",
1001 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1002#ifdef CONFIG_IEEE80211W
1003 if (ssid->ieee80211w) {
1004 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1005 ie.mgmt_group_cipher);
1006 }
1007#endif /* CONFIG_IEEE80211W */
1008
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001009 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1011 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
1012 !!(ssid->proto & WPA_PROTO_RSN));
1013
1014 if (bss || !wpa_s->ap_ies_from_associnfo) {
1015 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1016 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1017 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1018 bss_rsn ? 2 + bss_rsn[1] : 0))
1019 return -1;
1020 }
1021
1022 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001023 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1024 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1026 "cipher");
1027 return -1;
1028 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001029 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1030 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001031
1032 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001033 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1034 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1036 "cipher");
1037 return -1;
1038 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001039 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1040 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001041
1042 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001043#ifdef CONFIG_SAE
1044 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1045 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1046#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 if (0) {
1048#ifdef CONFIG_IEEE80211R
1049 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1050 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1051 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1052 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1053 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1054 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1055#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001056#ifdef CONFIG_SAE
1057 } else if (sel & WPA_KEY_MGMT_SAE) {
1058 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1059 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1060 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1061 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1062 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1063#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001064#ifdef CONFIG_IEEE80211W
1065 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1066 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1067 wpa_dbg(wpa_s, MSG_DEBUG,
1068 "WPA: using KEY_MGMT 802.1X with SHA256");
1069 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1070 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1071 wpa_dbg(wpa_s, MSG_DEBUG,
1072 "WPA: using KEY_MGMT PSK with SHA256");
1073#endif /* CONFIG_IEEE80211W */
1074 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1075 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1076 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1077 } else if (sel & WPA_KEY_MGMT_PSK) {
1078 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1079 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1080 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1081 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1082 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1083 } else {
1084 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1085 "authenticated key management type");
1086 return -1;
1087 }
1088
1089 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1090 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1091 wpa_s->pairwise_cipher);
1092 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1093
1094#ifdef CONFIG_IEEE80211W
1095 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001096 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1097 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001098 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1099 sel = 0;
1100 if (sel & WPA_CIPHER_AES_128_CMAC) {
1101 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1102 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1103 "AES-128-CMAC");
1104 } else {
1105 wpa_s->mgmt_group_cipher = 0;
1106 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1107 }
1108 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1109 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001110 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1111 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1112 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113#endif /* CONFIG_IEEE80211W */
1114
1115 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1116 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1117 return -1;
1118 }
1119
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001120 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001122#ifndef CONFIG_NO_PBKDF2
1123 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1124 ssid->passphrase) {
1125 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001126 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1127 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001128 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1129 psk, PMK_LEN);
1130 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1131 }
1132#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001133#ifdef CONFIG_EXT_PASSWORD
1134 if (ssid->ext_psk) {
1135 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1136 ssid->ext_psk);
1137 char pw_str[64 + 1];
1138 u8 psk[PMK_LEN];
1139
1140 if (pw == NULL) {
1141 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1142 "found from external storage");
1143 return -1;
1144 }
1145
1146 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1147 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1148 "PSK length %d in external storage",
1149 (int) wpabuf_len(pw));
1150 ext_password_free(pw);
1151 return -1;
1152 }
1153
1154 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1155 pw_str[wpabuf_len(pw)] = '\0';
1156
1157#ifndef CONFIG_NO_PBKDF2
1158 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1159 {
1160 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1161 4096, psk, PMK_LEN);
1162 os_memset(pw_str, 0, sizeof(pw_str));
1163 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1164 "external passphrase)",
1165 psk, PMK_LEN);
1166 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1167 } else
1168#endif /* CONFIG_NO_PBKDF2 */
1169 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1170 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1171 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1172 "Invalid PSK hex string");
1173 os_memset(pw_str, 0, sizeof(pw_str));
1174 ext_password_free(pw);
1175 return -1;
1176 }
1177 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1178 } else {
1179 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1180 "PSK available");
1181 os_memset(pw_str, 0, sizeof(pw_str));
1182 ext_password_free(pw);
1183 return -1;
1184 }
1185
1186 os_memset(pw_str, 0, sizeof(pw_str));
1187 ext_password_free(pw);
1188 }
1189#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001190 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001191 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1192
1193 return 0;
1194}
1195
1196
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001197static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1198{
1199 *pos = 0x00;
1200
1201 switch (idx) {
1202 case 0: /* Bits 0-7 */
1203 break;
1204 case 1: /* Bits 8-15 */
1205 break;
1206 case 2: /* Bits 16-23 */
1207#ifdef CONFIG_WNM
1208 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1209 *pos |= 0x08; /* Bit 19 - BSS Transition */
1210#endif /* CONFIG_WNM */
1211 break;
1212 case 3: /* Bits 24-31 */
1213#ifdef CONFIG_WNM
1214 *pos |= 0x02; /* Bit 25 - SSID List */
1215#endif /* CONFIG_WNM */
1216#ifdef CONFIG_INTERWORKING
1217 if (wpa_s->conf->interworking)
1218 *pos |= 0x80; /* Bit 31 - Interworking */
1219#endif /* CONFIG_INTERWORKING */
1220 break;
1221 case 4: /* Bits 32-39 */
1222 break;
1223 case 5: /* Bits 40-47 */
1224 break;
1225 case 6: /* Bits 48-55 */
1226 break;
1227 }
1228}
1229
1230
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001231int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1232{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001233 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001234 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001235
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001236 if (len < wpa_s->extended_capa_len)
1237 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001238
1239 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001240 *pos++ = len;
1241 for (i = 0; i < len; i++, pos++) {
1242 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001243
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001244 if (i < wpa_s->extended_capa_len) {
1245 *pos &= ~wpa_s->extended_capa_mask[i];
1246 *pos |= wpa_s->extended_capa[i];
1247 }
1248 }
1249
1250 while (len > 0 && buf[1 + len] == 0) {
1251 len--;
1252 buf[1] = len;
1253 }
1254 if (len == 0)
1255 return 0;
1256
1257 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001258}
1259
1260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001261/**
1262 * wpa_supplicant_associate - Request association
1263 * @wpa_s: Pointer to wpa_supplicant data
1264 * @bss: Scan results for the selected BSS, or %NULL if not available
1265 * @ssid: Configuration data for the selected network
1266 *
1267 * This function is used to request %wpa_supplicant to associate with a BSS.
1268 */
1269void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1270 struct wpa_bss *bss, struct wpa_ssid *ssid)
1271{
1272 u8 wpa_ie[200];
1273 size_t wpa_ie_len;
1274 int use_crypt, ret, i, bssid_changed;
1275 int algs = WPA_AUTH_ALG_OPEN;
1276 enum wpa_cipher cipher_pairwise, cipher_group;
1277 struct wpa_driver_associate_params params;
1278 int wep_keys_set = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001279 int assoc_failed = 0;
1280 struct wpa_ssid *old_ssid;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001281 u8 ext_capab[10];
1282 int ext_capab_len;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001283#ifdef CONFIG_HT_OVERRIDES
1284 struct ieee80211_ht_capabilities htcaps;
1285 struct ieee80211_ht_capabilities htcaps_mask;
1286#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287
1288#ifdef CONFIG_IBSS_RSN
1289 ibss_rsn_deinit(wpa_s->ibss_rsn);
1290 wpa_s->ibss_rsn = NULL;
1291#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001292#ifdef ANDROID_P2P
1293 int freq = 0;
1294#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295
1296 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1297 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1298#ifdef CONFIG_AP
1299 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1300 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1301 "mode");
1302 return;
1303 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001304 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1305 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1306 return;
1307 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308 wpa_s->current_bss = bss;
1309#else /* CONFIG_AP */
1310 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1311 "the build");
1312#endif /* CONFIG_AP */
1313 return;
1314 }
1315
1316#ifdef CONFIG_TDLS
1317 if (bss)
1318 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1319 bss->ie_len);
1320#endif /* CONFIG_TDLS */
1321
1322 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1323 ssid->mode == IEEE80211_MODE_INFRA) {
1324 sme_authenticate(wpa_s, bss, ssid);
1325 return;
1326 }
1327
1328 os_memset(&params, 0, sizeof(params));
1329 wpa_s->reassociate = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001330 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331#ifdef CONFIG_IEEE80211R
1332 const u8 *ie, *md = NULL;
1333#endif /* CONFIG_IEEE80211R */
1334 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1335 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1336 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1337 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1338 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1339 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1340 if (bssid_changed)
1341 wpas_notify_bssid_changed(wpa_s);
1342#ifdef CONFIG_IEEE80211R
1343 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1344 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1345 md = ie + 2;
1346 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1347 if (md) {
1348 /* Prepare for the next transition */
1349 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1350 }
1351#endif /* CONFIG_IEEE80211R */
1352#ifdef CONFIG_WPS
1353 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1354 wpa_s->conf->ap_scan == 2 &&
1355 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1356 /* Use ap_scan==1 style network selection to find the network
1357 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001358 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001359 wpa_s->reassociate = 1;
1360 wpa_supplicant_req_scan(wpa_s, 0, 0);
1361 return;
1362#endif /* CONFIG_WPS */
1363 } else {
1364 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1365 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1366 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1367 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001368 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001369 wpa_supplicant_cancel_scan(wpa_s);
1370
1371 /* Starting new association, so clear the possibly used WPA IE from the
1372 * previous association. */
1373 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1374
1375#ifdef IEEE8021X_EAPOL
1376 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1377 if (ssid->leap) {
1378 if (ssid->non_leap == 0)
1379 algs = WPA_AUTH_ALG_LEAP;
1380 else
1381 algs |= WPA_AUTH_ALG_LEAP;
1382 }
1383 }
1384#endif /* IEEE8021X_EAPOL */
1385 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1386 if (ssid->auth_alg) {
1387 algs = ssid->auth_alg;
1388 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1389 "0x%x", algs);
1390 }
1391
1392 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1393 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001394 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001396 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1397 wpa_s->conf->okc :
1398 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399 (ssid->proto & WPA_PROTO_RSN);
1400 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001401 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1403 wpa_ie_len = sizeof(wpa_ie);
1404 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1405 wpa_ie, &wpa_ie_len)) {
1406 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1407 "key management and encryption suites");
1408 return;
1409 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001410 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1411 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1412 /*
1413 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1414 * use non-WPA since the scan results did not indicate that the
1415 * AP is using WPA or WPA2.
1416 */
1417 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1418 wpa_ie_len = 0;
1419 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001420 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421 wpa_ie_len = sizeof(wpa_ie);
1422 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1423 wpa_ie, &wpa_ie_len)) {
1424 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1425 "key management and encryption suites (no "
1426 "scan results)");
1427 return;
1428 }
1429#ifdef CONFIG_WPS
1430 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1431 struct wpabuf *wps_ie;
1432 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1433 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1434 wpa_ie_len = wpabuf_len(wps_ie);
1435 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1436 } else
1437 wpa_ie_len = 0;
1438 wpabuf_free(wps_ie);
1439 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1440 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1441 params.wps = WPS_MODE_PRIVACY;
1442 else
1443 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001444 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445#endif /* CONFIG_WPS */
1446 } else {
1447 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1448 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001449 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001450 }
1451
1452#ifdef CONFIG_P2P
1453 if (wpa_s->global->p2p) {
1454 u8 *pos;
1455 size_t len;
1456 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001457 pos = wpa_ie + wpa_ie_len;
1458 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001459 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1460 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461 if (res >= 0)
1462 wpa_ie_len += res;
1463 }
1464
1465 wpa_s->cross_connect_disallowed = 0;
1466 if (bss) {
1467 struct wpabuf *p2p;
1468 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1469 if (p2p) {
1470 wpa_s->cross_connect_disallowed =
1471 p2p_get_cross_connect_disallowed(p2p);
1472 wpabuf_free(p2p);
1473 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1474 "connection",
1475 wpa_s->cross_connect_disallowed ?
1476 "disallows" : "allows");
1477 }
1478 }
1479#endif /* CONFIG_P2P */
1480
Dmitry Shmidt04949592012-07-19 12:16:46 -07001481#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001482 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001483 struct wpabuf *hs20;
1484 hs20 = wpabuf_alloc(20);
1485 if (hs20) {
1486 wpas_hs20_add_indication(hs20);
1487 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1488 wpabuf_len(hs20));
1489 wpa_ie_len += wpabuf_len(hs20);
1490 wpabuf_free(hs20);
1491 }
1492 }
1493#endif /* CONFIG_HS20 */
1494
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001495 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1496 if (ext_capab_len > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001497 u8 *pos = wpa_ie;
1498 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1499 pos += 2 + pos[1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001500 os_memmove(pos + ext_capab_len, pos,
1501 wpa_ie_len - (pos - wpa_ie));
1502 wpa_ie_len += ext_capab_len;
1503 os_memcpy(pos, ext_capab, ext_capab_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001504 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1507 use_crypt = 1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001508 cipher_pairwise = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
1509 cipher_group = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1511 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1512 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1513 use_crypt = 0;
1514 if (wpa_set_wep_keys(wpa_s, ssid)) {
1515 use_crypt = 1;
1516 wep_keys_set = 1;
1517 }
1518 }
1519 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1520 use_crypt = 0;
1521
1522#ifdef IEEE8021X_EAPOL
1523 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1524 if ((ssid->eapol_flags &
1525 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1526 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1527 !wep_keys_set) {
1528 use_crypt = 0;
1529 } else {
1530 /* Assume that dynamic WEP-104 keys will be used and
1531 * set cipher suites in order for drivers to expect
1532 * encryption. */
1533 cipher_pairwise = cipher_group = CIPHER_WEP104;
1534 }
1535 }
1536#endif /* IEEE8021X_EAPOL */
1537
1538 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1539 /* Set the key before (and later after) association */
1540 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1541 }
1542
1543 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1544 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545 params.ssid = bss->ssid;
1546 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001547 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1548 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1549 MACSTR " freq=%u MHz based on scan results "
1550 "(bssid_set=%d)",
1551 MAC2STR(bss->bssid), bss->freq,
1552 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001553 params.bssid = bss->bssid;
1554 params.freq = bss->freq;
1555 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001556 } else {
1557 params.ssid = ssid->ssid;
1558 params.ssid_len = ssid->ssid_len;
1559 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001560
1561 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1562 wpa_s->conf->ap_scan == 2) {
1563 params.bssid = ssid->bssid;
1564 params.fixed_bssid = 1;
1565 }
1566
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001567 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1568 params.freq == 0)
1569 params.freq = ssid->frequency; /* Initial channel for IBSS */
1570 params.wpa_ie = wpa_ie;
1571 params.wpa_ie_len = wpa_ie_len;
1572 params.pairwise_suite = cipher_pairwise;
1573 params.group_suite = cipher_group;
1574 params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001575 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001576 params.auth_alg = algs;
1577 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001578 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001579 for (i = 0; i < NUM_WEP_KEYS; i++) {
1580 if (ssid->wep_key_len[i])
1581 params.wep_key[i] = ssid->wep_key[i];
1582 params.wep_key_len[i] = ssid->wep_key_len[i];
1583 }
1584 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1585
1586 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1587 (params.key_mgmt_suite == KEY_MGMT_PSK ||
1588 params.key_mgmt_suite == KEY_MGMT_FT_PSK)) {
1589 params.passphrase = ssid->passphrase;
1590 if (ssid->psk_set)
1591 params.psk = ssid->psk;
1592 }
1593
1594 params.drop_unencrypted = use_crypt;
1595
1596#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001597 params.mgmt_frame_protection =
1598 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1599 wpa_s->conf->pmf : ssid->ieee80211w;
1600 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1602 struct wpa_ie_data ie;
1603 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1604 ie.capabilities &
1605 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1606 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1607 "MFP: require MFP");
1608 params.mgmt_frame_protection =
1609 MGMT_FRAME_PROTECTION_REQUIRED;
1610 }
1611 }
1612#endif /* CONFIG_IEEE80211W */
1613
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001614 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001615
1616 if (wpa_s->parent->set_sta_uapsd)
1617 params.uapsd = wpa_s->parent->sta_uapsd;
1618 else
1619 params.uapsd = -1;
1620
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001621#ifdef CONFIG_HT_OVERRIDES
1622 os_memset(&htcaps, 0, sizeof(htcaps));
1623 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1624 params.htcaps = (u8 *) &htcaps;
1625 params.htcaps_mask = (u8 *) &htcaps_mask;
1626 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1627#endif /* CONFIG_HT_OVERRIDES */
1628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001629#ifdef ANDROID_P2P
1630 /* If multichannel concurrency is not supported, check for any frequency
1631 * conflict and take appropriate action.
1632 */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001633 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) &&
1634 ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
1635 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001636 , freq, params.freq);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001637 if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07001638 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001639 }
1640#endif
1641 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001642 if (ret < 0) {
1643 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1644 "failed");
1645 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1646 /*
1647 * The driver is known to mean what is saying, so we
1648 * can stop right here; the association will not
1649 * succeed.
1650 */
1651 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001652 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001653 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1654 return;
1655 }
1656 /* try to continue anyway; new association will be tried again
1657 * after timeout */
1658 assoc_failed = 1;
1659 }
1660
1661 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1662 /* Set the key after the association just in case association
1663 * cleared the previously configured key. */
1664 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1665 /* No need to timeout authentication since there is no key
1666 * management. */
1667 wpa_supplicant_cancel_auth_timeout(wpa_s);
1668 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1669#ifdef CONFIG_IBSS_RSN
1670 } else if (ssid->mode == WPAS_MODE_IBSS &&
1671 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1672 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1673 /*
1674 * RSN IBSS authentication is per-STA and we can disable the
1675 * per-BSSID authentication.
1676 */
1677 wpa_supplicant_cancel_auth_timeout(wpa_s);
1678#endif /* CONFIG_IBSS_RSN */
1679 } else {
1680 /* Timeout for IEEE 802.11 authentication and association */
1681 int timeout = 60;
1682
1683 if (assoc_failed) {
1684 /* give IBSS a bit more time */
1685 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1686 } else if (wpa_s->conf->ap_scan == 1) {
1687 /* give IBSS a bit more time */
1688 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1689 }
1690 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1691 }
1692
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001693 if (wep_keys_set &&
1694 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695 /* Set static WEP keys again */
1696 wpa_set_wep_keys(wpa_s, ssid);
1697 }
1698
1699 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1700 /*
1701 * Do not allow EAP session resumption between different
1702 * network configurations.
1703 */
1704 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1705 }
1706 old_ssid = wpa_s->current_ssid;
1707 wpa_s->current_ssid = ssid;
1708 wpa_s->current_bss = bss;
1709 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1710 wpa_supplicant_initiate_eapol(wpa_s);
1711 if (old_ssid != wpa_s->current_ssid)
1712 wpas_notify_network_changed(wpa_s);
1713}
1714
1715
1716static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1717 const u8 *addr)
1718{
1719 struct wpa_ssid *old_ssid;
1720
1721 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001723 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001724 wpa_sm_set_config(wpa_s->wpa, NULL);
1725 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1726 if (old_ssid != wpa_s->current_ssid)
1727 wpas_notify_network_changed(wpa_s);
1728 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1729}
1730
1731
1732/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001733 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1734 * @wpa_s: Pointer to wpa_supplicant data
1735 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1736 *
1737 * This function is used to request %wpa_supplicant to deauthenticate from the
1738 * current AP.
1739 */
1740void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1741 int reason_code)
1742{
1743 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001744 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001745 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001747 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1748 " pending_bssid=" MACSTR " reason=%d state=%s",
1749 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1750 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1751
1752 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001754 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1755 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1756 wpa_s->wpa_state == WPA_ASSOCIATING))
1757 addr = wpa_s->pending_bssid;
1758 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1759 /*
1760 * When using driver-based BSS selection, we may not know the
1761 * BSSID with which we are currently trying to associate. We
1762 * need to notify the driver of this disconnection even in such
1763 * a case, so use the all zeros address here.
1764 */
1765 addr = wpa_s->bssid;
1766 zero_addr = 1;
1767 }
1768
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001769#ifdef CONFIG_TDLS
1770 wpa_tdls_teardown_peers(wpa_s->wpa);
1771#endif /* CONFIG_TDLS */
1772
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001773 if (addr) {
1774 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001775 os_memset(&event, 0, sizeof(event));
1776 event.deauth_info.reason_code = (u16) reason_code;
1777 event.deauth_info.locally_generated = 1;
1778 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001779 if (zero_addr)
1780 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001781 }
1782
1783 wpa_supplicant_clear_connection(wpa_s, addr);
1784}
1785
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001786static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1787 struct wpa_ssid *ssid)
1788{
1789 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1790 return;
1791
1792 ssid->disabled = 0;
1793 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1794 wpas_notify_network_enabled_changed(wpa_s, ssid);
1795
1796 /*
1797 * Try to reassociate since there is no current configuration and a new
1798 * network was made available.
1799 */
1800 if (!wpa_s->current_ssid)
1801 wpa_s->reassociate = 1;
1802}
1803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001804
1805/**
1806 * wpa_supplicant_enable_network - Mark a configured network as enabled
1807 * @wpa_s: wpa_supplicant structure for a network interface
1808 * @ssid: wpa_ssid structure for a configured network or %NULL
1809 *
1810 * Enables the specified network or all networks if no network specified.
1811 */
1812void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1813 struct wpa_ssid *ssid)
1814{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001815 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001816 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1817 wpa_supplicant_enable_one_network(wpa_s, ssid);
1818 } else
1819 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001820
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001821 if (wpa_s->reassociate) {
1822 if (wpa_s->sched_scanning) {
1823 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1824 "new network to scan filters");
1825 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 }
1827
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001828 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1829 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830 }
1831}
1832
1833
1834/**
1835 * wpa_supplicant_disable_network - Mark a configured network as disabled
1836 * @wpa_s: wpa_supplicant structure for a network interface
1837 * @ssid: wpa_ssid structure for a configured network or %NULL
1838 *
1839 * Disables the specified network or all networks if no network specified.
1840 */
1841void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1842 struct wpa_ssid *ssid)
1843{
1844 struct wpa_ssid *other_ssid;
1845 int was_disabled;
1846
1847 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001848 if (wpa_s->sched_scanning)
1849 wpa_supplicant_cancel_sched_scan(wpa_s);
1850
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1852 other_ssid = other_ssid->next) {
1853 was_disabled = other_ssid->disabled;
1854 if (was_disabled == 2)
1855 continue; /* do not change persistent P2P group
1856 * data */
1857
1858 other_ssid->disabled = 1;
1859
1860 if (was_disabled != other_ssid->disabled)
1861 wpas_notify_network_enabled_changed(
1862 wpa_s, other_ssid);
1863 }
1864 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001865 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1867 } else if (ssid->disabled != 2) {
1868 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001869 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001870 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1871
1872 was_disabled = ssid->disabled;
1873
1874 ssid->disabled = 1;
1875
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001876 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001878 if (wpa_s->sched_scanning) {
1879 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1880 "to remove network from filters");
1881 wpa_supplicant_cancel_sched_scan(wpa_s);
1882 wpa_supplicant_req_scan(wpa_s, 0, 0);
1883 }
1884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 }
1886}
1887
1888
1889/**
1890 * wpa_supplicant_select_network - Attempt association with a network
1891 * @wpa_s: wpa_supplicant structure for a network interface
1892 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1893 */
1894void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1895 struct wpa_ssid *ssid)
1896{
1897
1898 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001899 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001901 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001902 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001903 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001904 disconnected = 1;
1905 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001907 if (ssid)
1908 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1909
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001910 /*
1911 * Mark all other networks disabled or mark all networks enabled if no
1912 * network specified.
1913 */
1914 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1915 other_ssid = other_ssid->next) {
1916 int was_disabled = other_ssid->disabled;
1917 if (was_disabled == 2)
1918 continue; /* do not change persistent P2P group data */
1919
1920 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001921 if (was_disabled && !other_ssid->disabled)
1922 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923
1924 if (was_disabled != other_ssid->disabled)
1925 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1926 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001927
1928 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
1929 /* We are already associated with the selected network */
1930 wpa_printf(MSG_DEBUG, "Already associated with the "
1931 "selected network - do nothing");
1932 return;
1933 }
1934
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001935 if (ssid)
1936 wpa_s->current_ssid = ssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001937 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 wpa_s->disconnected = 0;
1939 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001940
1941 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1942 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001943
1944 if (ssid)
1945 wpas_notify_network_selected(wpa_s, ssid);
1946}
1947
1948
1949/**
1950 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
1951 * @wpa_s: wpa_supplicant structure for a network interface
1952 * @ap_scan: AP scan mode
1953 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
1954 *
1955 */
1956int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
1957{
1958
1959 int old_ap_scan;
1960
1961 if (ap_scan < 0 || ap_scan > 2)
1962 return -1;
1963
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001964#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001965 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
1966 wpa_s->wpa_state >= WPA_ASSOCIATING &&
1967 wpa_s->wpa_state < WPA_COMPLETED) {
1968 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
1969 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001970 return 0;
1971 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001972#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 old_ap_scan = wpa_s->conf->ap_scan;
1975 wpa_s->conf->ap_scan = ap_scan;
1976
1977 if (old_ap_scan != wpa_s->conf->ap_scan)
1978 wpas_notify_ap_scan_changed(wpa_s);
1979
1980 return 0;
1981}
1982
1983
1984/**
1985 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
1986 * @wpa_s: wpa_supplicant structure for a network interface
1987 * @expire_age: Expiration age in seconds
1988 * Returns: 0 if succeed or -1 if expire_age has an invalid value
1989 *
1990 */
1991int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
1992 unsigned int bss_expire_age)
1993{
1994 if (bss_expire_age < 10) {
1995 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
1996 bss_expire_age);
1997 return -1;
1998 }
1999 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2000 bss_expire_age);
2001 wpa_s->conf->bss_expiration_age = bss_expire_age;
2002
2003 return 0;
2004}
2005
2006
2007/**
2008 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2009 * @wpa_s: wpa_supplicant structure for a network interface
2010 * @expire_count: number of scans after which an unseen BSS is reclaimed
2011 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2012 *
2013 */
2014int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2015 unsigned int bss_expire_count)
2016{
2017 if (bss_expire_count < 1) {
2018 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2019 bss_expire_count);
2020 return -1;
2021 }
2022 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2023 bss_expire_count);
2024 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2025
2026 return 0;
2027}
2028
2029
2030/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002031 * wpa_supplicant_set_scan_interval - Set scan interval
2032 * @wpa_s: wpa_supplicant structure for a network interface
2033 * @scan_interval: scan interval in seconds
2034 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2035 *
2036 */
2037int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2038 int scan_interval)
2039{
2040 if (scan_interval < 0) {
2041 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2042 scan_interval);
2043 return -1;
2044 }
2045 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2046 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002047 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002048
2049 return 0;
2050}
2051
2052
2053/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 * wpa_supplicant_set_debug_params - Set global debug params
2055 * @global: wpa_global structure
2056 * @debug_level: debug level
2057 * @debug_timestamp: determines if show timestamp in debug data
2058 * @debug_show_keys: determines if show keys in debug data
2059 * Returns: 0 if succeed or -1 if debug_level has wrong value
2060 */
2061int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2062 int debug_timestamp, int debug_show_keys)
2063{
2064
2065 int old_level, old_timestamp, old_show_keys;
2066
2067 /* check for allowed debuglevels */
2068 if (debug_level != MSG_EXCESSIVE &&
2069 debug_level != MSG_MSGDUMP &&
2070 debug_level != MSG_DEBUG &&
2071 debug_level != MSG_INFO &&
2072 debug_level != MSG_WARNING &&
2073 debug_level != MSG_ERROR)
2074 return -1;
2075
2076 old_level = wpa_debug_level;
2077 old_timestamp = wpa_debug_timestamp;
2078 old_show_keys = wpa_debug_show_keys;
2079
2080 wpa_debug_level = debug_level;
2081 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2082 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2083
2084 if (wpa_debug_level != old_level)
2085 wpas_notify_debug_level_changed(global);
2086 if (wpa_debug_timestamp != old_timestamp)
2087 wpas_notify_debug_timestamp_changed(global);
2088 if (wpa_debug_show_keys != old_show_keys)
2089 wpas_notify_debug_show_keys_changed(global);
2090
2091 return 0;
2092}
2093
2094
2095/**
2096 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2097 * @wpa_s: Pointer to wpa_supplicant data
2098 * Returns: A pointer to the current network structure or %NULL on failure
2099 */
2100struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2101{
2102 struct wpa_ssid *entry;
2103 u8 ssid[MAX_SSID_LEN];
2104 int res;
2105 size_t ssid_len;
2106 u8 bssid[ETH_ALEN];
2107 int wired;
2108
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002109 res = wpa_drv_get_ssid(wpa_s, ssid);
2110 if (res < 0) {
2111 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2112 "driver");
2113 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002114 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002115 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002116
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002117 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2119 "driver");
2120 return NULL;
2121 }
2122
2123 wired = wpa_s->conf->ap_scan == 0 &&
2124 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2125
2126 entry = wpa_s->conf->ssid;
2127 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002128 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002129 ((ssid_len == entry->ssid_len &&
2130 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2131 (!entry->bssid_set ||
2132 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2133 return entry;
2134#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002135 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002136 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2137 (entry->ssid == NULL || entry->ssid_len == 0) &&
2138 (!entry->bssid_set ||
2139 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2140 return entry;
2141#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002142
Dmitry Shmidt04949592012-07-19 12:16:46 -07002143 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002144 entry->ssid_len == 0 &&
2145 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2146 return entry;
2147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 entry = entry->next;
2149 }
2150
2151 return NULL;
2152}
2153
2154
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002155static int select_driver(struct wpa_supplicant *wpa_s, int i)
2156{
2157 struct wpa_global *global = wpa_s->global;
2158
2159 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2160 global->drv_priv[i] = wpa_drivers[i]->global_init();
2161 if (global->drv_priv[i] == NULL) {
2162 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2163 "'%s'", wpa_drivers[i]->name);
2164 return -1;
2165 }
2166 }
2167
2168 wpa_s->driver = wpa_drivers[i];
2169 wpa_s->global_drv_priv = global->drv_priv[i];
2170
2171 return 0;
2172}
2173
2174
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2176 const char *name)
2177{
2178 int i;
2179 size_t len;
2180 const char *pos, *driver = name;
2181
2182 if (wpa_s == NULL)
2183 return -1;
2184
2185 if (wpa_drivers[0] == NULL) {
2186 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2187 "wpa_supplicant");
2188 return -1;
2189 }
2190
2191 if (name == NULL) {
2192 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002193 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002194 }
2195
2196 do {
2197 pos = os_strchr(driver, ',');
2198 if (pos)
2199 len = pos - driver;
2200 else
2201 len = os_strlen(driver);
2202
2203 for (i = 0; wpa_drivers[i]; i++) {
2204 if (os_strlen(wpa_drivers[i]->name) == len &&
2205 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002206 0) {
2207 /* First driver that succeeds wins */
2208 if (select_driver(wpa_s, i) == 0)
2209 return 0;
2210 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 }
2212
2213 driver = pos + 1;
2214 } while (pos);
2215
2216 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2217 return -1;
2218}
2219
2220
2221/**
2222 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2223 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2224 * with struct wpa_driver_ops::init()
2225 * @src_addr: Source address of the EAPOL frame
2226 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2227 * @len: Length of the EAPOL data
2228 *
2229 * This function is called for each received EAPOL frame. Most driver
2230 * interfaces rely on more generic OS mechanism for receiving frames through
2231 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2232 * take care of received EAPOL frames and deliver them to the core supplicant
2233 * code by calling this function.
2234 */
2235void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2236 const u8 *buf, size_t len)
2237{
2238 struct wpa_supplicant *wpa_s = ctx;
2239
2240 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2241 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2242
Jouni Malinena05074c2012-12-21 21:35:35 +02002243 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2244 (wpa_s->last_eapol_matches_bssid &&
2245#ifdef CONFIG_AP
2246 !wpa_s->ap_iface &&
2247#endif /* CONFIG_AP */
2248 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 /*
2250 * There is possible race condition between receiving the
2251 * association event and the EAPOL frame since they are coming
2252 * through different paths from the driver. In order to avoid
2253 * issues in trying to process the EAPOL frame before receiving
2254 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002255 * the association event is received. This may also be needed in
2256 * driver-based roaming case, so also use src_addr != BSSID as a
2257 * trigger if we have previously confirmed that the
2258 * Authenticator uses BSSID as the src_addr (which is not the
2259 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 */
2261 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002262 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2263 wpa_supplicant_state_txt(wpa_s->wpa_state),
2264 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002265 wpabuf_free(wpa_s->pending_eapol_rx);
2266 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2267 if (wpa_s->pending_eapol_rx) {
2268 os_get_time(&wpa_s->pending_eapol_rx_time);
2269 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2270 ETH_ALEN);
2271 }
2272 return;
2273 }
2274
Jouni Malinena05074c2012-12-21 21:35:35 +02002275 wpa_s->last_eapol_matches_bssid =
2276 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278#ifdef CONFIG_AP
2279 if (wpa_s->ap_iface) {
2280 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2281 return;
2282 }
2283#endif /* CONFIG_AP */
2284
2285 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2286 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2287 "no key management is configured");
2288 return;
2289 }
2290
2291 if (wpa_s->eapol_received == 0 &&
2292 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2293 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2294 wpa_s->wpa_state != WPA_COMPLETED) &&
2295 (wpa_s->current_ssid == NULL ||
2296 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2297 /* Timeout for completing IEEE 802.1X and WPA authentication */
2298 wpa_supplicant_req_auth_timeout(
2299 wpa_s,
2300 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2301 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2302 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2303 70 : 10, 0);
2304 }
2305 wpa_s->eapol_received++;
2306
2307 if (wpa_s->countermeasures) {
2308 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2309 "EAPOL packet");
2310 return;
2311 }
2312
2313#ifdef CONFIG_IBSS_RSN
2314 if (wpa_s->current_ssid &&
2315 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2316 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2317 return;
2318 }
2319#endif /* CONFIG_IBSS_RSN */
2320
2321 /* Source address of the incoming EAPOL frame could be compared to the
2322 * current BSSID. However, it is possible that a centralized
2323 * Authenticator could be using another MAC address than the BSSID of
2324 * an AP, so just allow any address to be used for now. The replies are
2325 * still sent to the current BSSID (if available), though. */
2326
2327 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2328 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2329 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2330 return;
2331 wpa_drv_poll(wpa_s);
2332 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2333 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2334 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2335 /*
2336 * Set portValid = TRUE here since we are going to skip 4-way
2337 * handshake processing which would normally set portValid. We
2338 * need this to allow the EAPOL state machines to be completed
2339 * without going through EAPOL-Key handshake.
2340 */
2341 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2342 }
2343}
2344
2345
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002346int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 if (wpa_s->driver->send_eapol) {
2349 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2350 if (addr)
2351 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002352 } else if ((!wpa_s->p2p_mgmt ||
2353 !(wpa_s->drv_flags &
2354 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2355 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002357 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2359 wpa_drv_get_mac_addr(wpa_s),
2360 ETH_P_EAPOL,
2361 wpa_supplicant_rx_eapol, wpa_s, 0);
2362 if (wpa_s->l2 == NULL)
2363 return -1;
2364 } else {
2365 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2366 if (addr)
2367 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2368 }
2369
2370 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2371 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2372 return -1;
2373 }
2374
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002375 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
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002420 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2421 MAC2STR(wpa_s->own_addr));
2422 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2423
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 if (wpa_s->bridge_ifname[0]) {
2425 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2426 "interface '%s'", wpa_s->bridge_ifname);
2427 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2428 wpa_s->own_addr,
2429 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002430 wpa_supplicant_rx_eapol_bridge,
2431 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 if (wpa_s->l2_br == NULL) {
2433 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2434 "connection for the bridge interface '%s'",
2435 wpa_s->bridge_ifname);
2436 return -1;
2437 }
2438 }
2439
2440 wpa_clear_keys(wpa_s, NULL);
2441
2442 /* Make sure that TKIP countermeasures are not left enabled (could
2443 * happen if wpa_supplicant is killed during countermeasures. */
2444 wpa_drv_set_countermeasures(wpa_s, 0);
2445
2446 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2447 wpa_drv_flush_pmkid(wpa_s);
2448
2449 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002450 wpa_s->prev_scan_wildcard = 0;
2451
Dmitry Shmidt04949592012-07-19 12:16:46 -07002452 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002453 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2454 100000))
2455 wpa_supplicant_req_scan(wpa_s, interface_count,
2456 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 interface_count++;
2458 } else
2459 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2460
2461 return 0;
2462}
2463
2464
2465static int wpa_supplicant_daemon(const char *pid_file)
2466{
2467 wpa_printf(MSG_DEBUG, "Daemonize..");
2468 return os_daemonize(pid_file);
2469}
2470
2471
2472static struct wpa_supplicant * wpa_supplicant_alloc(void)
2473{
2474 struct wpa_supplicant *wpa_s;
2475
2476 wpa_s = os_zalloc(sizeof(*wpa_s));
2477 if (wpa_s == NULL)
2478 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002479 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 wpa_s->scan_interval = 5;
2481 wpa_s->new_connection = 1;
2482 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002483 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484
2485 return wpa_s;
2486}
2487
2488
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002489#ifdef CONFIG_HT_OVERRIDES
2490
2491static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2492 struct ieee80211_ht_capabilities *htcaps,
2493 struct ieee80211_ht_capabilities *htcaps_mask,
2494 const char *ht_mcs)
2495{
2496 /* parse ht_mcs into hex array */
2497 int i;
2498 const char *tmp = ht_mcs;
2499 char *end = NULL;
2500
2501 /* If ht_mcs is null, do not set anything */
2502 if (!ht_mcs)
2503 return 0;
2504
2505 /* This is what we are setting in the kernel */
2506 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2507
2508 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2509
2510 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2511 errno = 0;
2512 long v = strtol(tmp, &end, 16);
2513 if (errno == 0) {
2514 wpa_msg(wpa_s, MSG_DEBUG,
2515 "htcap value[%i]: %ld end: %p tmp: %p",
2516 i, v, end, tmp);
2517 if (end == tmp)
2518 break;
2519
2520 htcaps->supported_mcs_set[i] = v;
2521 tmp = end;
2522 } else {
2523 wpa_msg(wpa_s, MSG_ERROR,
2524 "Failed to parse ht-mcs: %s, error: %s\n",
2525 ht_mcs, strerror(errno));
2526 return -1;
2527 }
2528 }
2529
2530 /*
2531 * If we were able to parse any values, then set mask for the MCS set.
2532 */
2533 if (i) {
2534 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2535 IEEE80211_HT_MCS_MASK_LEN - 1);
2536 /* skip the 3 reserved bits */
2537 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2538 0x1f;
2539 }
2540
2541 return 0;
2542}
2543
2544
2545static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2546 struct ieee80211_ht_capabilities *htcaps,
2547 struct ieee80211_ht_capabilities *htcaps_mask,
2548 int disabled)
2549{
2550 u16 msk;
2551
2552 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2553
2554 if (disabled == -1)
2555 return 0;
2556
2557 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2558 htcaps_mask->ht_capabilities_info |= msk;
2559 if (disabled)
2560 htcaps->ht_capabilities_info &= msk;
2561 else
2562 htcaps->ht_capabilities_info |= msk;
2563
2564 return 0;
2565}
2566
2567
2568static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2569 struct ieee80211_ht_capabilities *htcaps,
2570 struct ieee80211_ht_capabilities *htcaps_mask,
2571 int factor)
2572{
2573 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2574
2575 if (factor == -1)
2576 return 0;
2577
2578 if (factor < 0 || factor > 3) {
2579 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2580 "Must be 0-3 or -1", factor);
2581 return -EINVAL;
2582 }
2583
2584 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2585 htcaps->a_mpdu_params &= ~0x3;
2586 htcaps->a_mpdu_params |= factor & 0x3;
2587
2588 return 0;
2589}
2590
2591
2592static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2593 struct ieee80211_ht_capabilities *htcaps,
2594 struct ieee80211_ht_capabilities *htcaps_mask,
2595 int density)
2596{
2597 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2598
2599 if (density == -1)
2600 return 0;
2601
2602 if (density < 0 || density > 7) {
2603 wpa_msg(wpa_s, MSG_ERROR,
2604 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2605 density);
2606 return -EINVAL;
2607 }
2608
2609 htcaps_mask->a_mpdu_params |= 0x1C;
2610 htcaps->a_mpdu_params &= ~(0x1C);
2611 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2612
2613 return 0;
2614}
2615
2616
2617static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2618 struct ieee80211_ht_capabilities *htcaps,
2619 struct ieee80211_ht_capabilities *htcaps_mask,
2620 int disabled)
2621{
2622 /* Masking these out disables HT40 */
2623 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2624 HT_CAP_INFO_SHORT_GI40MHZ);
2625
2626 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2627
2628 if (disabled)
2629 htcaps->ht_capabilities_info &= ~msk;
2630 else
2631 htcaps->ht_capabilities_info |= msk;
2632
2633 htcaps_mask->ht_capabilities_info |= msk;
2634
2635 return 0;
2636}
2637
2638
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002639static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2640 struct ieee80211_ht_capabilities *htcaps,
2641 struct ieee80211_ht_capabilities *htcaps_mask,
2642 int disabled)
2643{
2644 /* Masking these out disables SGI */
2645 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2646 HT_CAP_INFO_SHORT_GI40MHZ);
2647
2648 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2649
2650 if (disabled)
2651 htcaps->ht_capabilities_info &= ~msk;
2652 else
2653 htcaps->ht_capabilities_info |= msk;
2654
2655 htcaps_mask->ht_capabilities_info |= msk;
2656
2657 return 0;
2658}
2659
2660
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002661void wpa_supplicant_apply_ht_overrides(
2662 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2663 struct wpa_driver_associate_params *params)
2664{
2665 struct ieee80211_ht_capabilities *htcaps;
2666 struct ieee80211_ht_capabilities *htcaps_mask;
2667
2668 if (!ssid)
2669 return;
2670
2671 params->disable_ht = ssid->disable_ht;
2672 if (!params->htcaps || !params->htcaps_mask)
2673 return;
2674
2675 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2676 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2677 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2678 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2679 ssid->disable_max_amsdu);
2680 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2681 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2682 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002683 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002684}
2685
2686#endif /* CONFIG_HT_OVERRIDES */
2687
2688
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002689#ifdef CONFIG_VHT_OVERRIDES
2690void wpa_supplicant_apply_vht_overrides(
2691 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2692 struct wpa_driver_associate_params *params)
2693{
2694 struct ieee80211_vht_capabilities *vhtcaps;
2695 struct ieee80211_vht_capabilities *vhtcaps_mask;
2696
2697 if (!ssid)
2698 return;
2699
2700 params->disable_vht = ssid->disable_vht;
2701
2702 vhtcaps = (void *) params->vhtcaps;
2703 vhtcaps_mask = (void *) params->vhtcaps_mask;
2704
2705 if (!vhtcaps || !vhtcaps_mask)
2706 return;
2707
2708 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2709 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2710
2711#define OVERRIDE_MCS(i) \
2712 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2713 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2714 3 << 2 * (i - 1); \
2715 vhtcaps->vht_supported_mcs_set.tx_map |= \
2716 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2717 } \
2718 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2719 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2720 3 << 2 * (i - 1); \
2721 vhtcaps->vht_supported_mcs_set.rx_map |= \
2722 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2723 }
2724
2725 OVERRIDE_MCS(1);
2726 OVERRIDE_MCS(2);
2727 OVERRIDE_MCS(3);
2728 OVERRIDE_MCS(4);
2729 OVERRIDE_MCS(5);
2730 OVERRIDE_MCS(6);
2731 OVERRIDE_MCS(7);
2732 OVERRIDE_MCS(8);
2733}
2734#endif /* CONFIG_VHT_OVERRIDES */
2735
2736
Dmitry Shmidt04949592012-07-19 12:16:46 -07002737static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2738{
2739#ifdef PCSC_FUNCS
2740 size_t len;
2741
2742 if (!wpa_s->conf->pcsc_reader)
2743 return 0;
2744
2745 wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
2746 if (!wpa_s->scard)
2747 return 1;
2748
2749 if (wpa_s->conf->pcsc_pin &&
2750 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2751 scard_deinit(wpa_s->scard);
2752 wpa_s->scard = NULL;
2753 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2754 return -1;
2755 }
2756
2757 len = sizeof(wpa_s->imsi) - 1;
2758 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2759 scard_deinit(wpa_s->scard);
2760 wpa_s->scard = NULL;
2761 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2762 return -1;
2763 }
2764 wpa_s->imsi[len] = '\0';
2765
2766 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2767
2768 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2769 wpa_s->imsi, wpa_s->mnc_len);
2770
2771 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2772 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2773#endif /* PCSC_FUNCS */
2774
2775 return 0;
2776}
2777
2778
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2780{
2781 char *val, *pos;
2782
2783 ext_password_deinit(wpa_s->ext_pw);
2784 wpa_s->ext_pw = NULL;
2785 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2786
2787 if (!wpa_s->conf->ext_password_backend)
2788 return 0;
2789
2790 val = os_strdup(wpa_s->conf->ext_password_backend);
2791 if (val == NULL)
2792 return -1;
2793 pos = os_strchr(val, ':');
2794 if (pos)
2795 *pos++ = '\0';
2796
2797 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2798
2799 wpa_s->ext_pw = ext_password_init(val, pos);
2800 os_free(val);
2801 if (wpa_s->ext_pw == NULL) {
2802 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2803 return -1;
2804 }
2805 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2806
2807 return 0;
2808}
2809
2810
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2812 struct wpa_interface *iface)
2813{
2814 const char *ifname, *driver;
2815 struct wpa_driver_capa capa;
2816
2817 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
2818 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2819 iface->confname ? iface->confname : "N/A",
2820 iface->driver ? iface->driver : "default",
2821 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2822 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2823
2824 if (iface->confname) {
2825#ifdef CONFIG_BACKEND_FILE
2826 wpa_s->confname = os_rel2abs_path(iface->confname);
2827 if (wpa_s->confname == NULL) {
2828 wpa_printf(MSG_ERROR, "Failed to get absolute path "
2829 "for configuration file '%s'.",
2830 iface->confname);
2831 return -1;
2832 }
2833 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
2834 iface->confname, wpa_s->confname);
2835#else /* CONFIG_BACKEND_FILE */
2836 wpa_s->confname = os_strdup(iface->confname);
2837#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002838 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839 if (wpa_s->conf == NULL) {
2840 wpa_printf(MSG_ERROR, "Failed to read or parse "
2841 "configuration '%s'.", wpa_s->confname);
2842 return -1;
2843 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002844 wpa_s->confanother = os_rel2abs_path(iface->confanother);
2845 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002846
2847 /*
2848 * Override ctrl_interface and driver_param if set on command
2849 * line.
2850 */
2851 if (iface->ctrl_interface) {
2852 os_free(wpa_s->conf->ctrl_interface);
2853 wpa_s->conf->ctrl_interface =
2854 os_strdup(iface->ctrl_interface);
2855 }
2856
2857 if (iface->driver_param) {
2858 os_free(wpa_s->conf->driver_param);
2859 wpa_s->conf->driver_param =
2860 os_strdup(iface->driver_param);
2861 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002862
2863 if (iface->p2p_mgmt && !iface->ctrl_interface) {
2864 os_free(wpa_s->conf->ctrl_interface);
2865 wpa_s->conf->ctrl_interface = NULL;
2866 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002867 } else
2868 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
2869 iface->driver_param);
2870
2871 if (wpa_s->conf == NULL) {
2872 wpa_printf(MSG_ERROR, "\nNo configuration found.");
2873 return -1;
2874 }
2875
2876 if (iface->ifname == NULL) {
2877 wpa_printf(MSG_ERROR, "\nInterface name is required.");
2878 return -1;
2879 }
2880 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
2881 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
2882 iface->ifname);
2883 return -1;
2884 }
2885 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
2886
2887 if (iface->bridge_ifname) {
2888 if (os_strlen(iface->bridge_ifname) >=
2889 sizeof(wpa_s->bridge_ifname)) {
2890 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
2891 "name '%s'.", iface->bridge_ifname);
2892 return -1;
2893 }
2894 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
2895 sizeof(wpa_s->bridge_ifname));
2896 }
2897
2898 /* RSNA Supplicant Key Management - INITIALIZE */
2899 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2900 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2901
2902 /* Initialize driver interface and register driver event handler before
2903 * L2 receive handler so that association events are processed before
2904 * EAPOL-Key packets if both become available for the same select()
2905 * call. */
2906 driver = iface->driver;
2907next_driver:
2908 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2909 return -1;
2910
2911 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2912 if (wpa_s->drv_priv == NULL) {
2913 const char *pos;
2914 pos = driver ? os_strchr(driver, ',') : NULL;
2915 if (pos) {
2916 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2917 "driver interface - try next driver wrapper");
2918 driver = pos + 1;
2919 goto next_driver;
2920 }
2921 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2922 "interface");
2923 return -1;
2924 }
2925 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2926 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2927 "driver_param '%s'", wpa_s->conf->driver_param);
2928 return -1;
2929 }
2930
2931 ifname = wpa_drv_get_ifname(wpa_s);
2932 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2933 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2934 "interface name with '%s'", ifname);
2935 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2936 }
2937
2938 if (wpa_supplicant_init_wpa(wpa_s) < 0)
2939 return -1;
2940
2941 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
2942 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
2943 NULL);
2944 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
2945
2946 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
2947 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
2948 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
2949 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2950 "dot11RSNAConfigPMKLifetime");
2951 return -1;
2952 }
2953
2954 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
2955 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
2956 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
2957 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2958 "dot11RSNAConfigPMKReauthThreshold");
2959 return -1;
2960 }
2961
2962 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
2963 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
2964 wpa_s->conf->dot11RSNAConfigSATimeout)) {
2965 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2966 "dot11RSNAConfigSATimeout");
2967 return -1;
2968 }
2969
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002970 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
2971 &wpa_s->hw.num_modes,
2972 &wpa_s->hw.flags);
2973
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002975 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002976 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002977 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002978 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002979 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002980 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
2981 wpa_s->sched_scan_supported = capa.sched_scan_supported;
2982 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
2984 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002985 wpa_s->extended_capa = capa.extended_capa;
2986 wpa_s->extended_capa_mask = capa.extended_capa_mask;
2987 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002988 }
2989 if (wpa_s->max_remain_on_chan == 0)
2990 wpa_s->max_remain_on_chan = 1000;
2991
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002992 /*
2993 * Only take p2p_mgmt parameters when P2P Device is supported.
2994 * Doing it here as it determines whether l2_packet_init() will be done
2995 * during wpa_supplicant_driver_init().
2996 */
2997 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
2998 wpa_s->p2p_mgmt = iface->p2p_mgmt;
2999 else
3000 iface->p2p_mgmt = 1;
3001
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003002 if (wpa_supplicant_driver_init(wpa_s) < 0)
3003 return -1;
3004
3005#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003006 if ((!iface->p2p_mgmt ||
3007 !(wpa_s->drv_flags &
3008 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3009 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003010 return -1;
3011#endif /* CONFIG_TDLS */
3012
3013 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3014 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3015 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3016 return -1;
3017 }
3018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019 if (wpas_wps_init(wpa_s))
3020 return -1;
3021
3022 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3023 return -1;
3024 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3025
3026 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3027 if (wpa_s->ctrl_iface == NULL) {
3028 wpa_printf(MSG_ERROR,
3029 "Failed to initialize control interface '%s'.\n"
3030 "You may have another wpa_supplicant process "
3031 "already running or the file was\n"
3032 "left by an unclean termination of wpa_supplicant "
3033 "in which case you will need\n"
3034 "to manually remove this file before starting "
3035 "wpa_supplicant again.\n",
3036 wpa_s->conf->ctrl_interface);
3037 return -1;
3038 }
3039
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003040 wpa_s->gas = gas_query_init(wpa_s);
3041 if (wpa_s->gas == NULL) {
3042 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3043 return -1;
3044 }
3045
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003047 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003048 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3049 return -1;
3050 }
3051#endif /* CONFIG_P2P */
3052
3053 if (wpa_bss_init(wpa_s) < 0)
3054 return -1;
3055
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003056#ifdef CONFIG_EAP_PROXY
3057{
3058 size_t len;
3059 wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);
3060 if (wpa_s->mnc_len > 0) {
3061 wpa_s->imsi[len] = '\0';
3062 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3063 wpa_s->imsi, wpa_s->mnc_len);
3064 } else {
3065 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3066 }
3067}
3068#endif /* CONFIG_EAP_PROXY */
3069
Dmitry Shmidt04949592012-07-19 12:16:46 -07003070 if (pcsc_reader_init(wpa_s) < 0)
3071 return -1;
3072
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003073 if (wpas_init_ext_pw(wpa_s) < 0)
3074 return -1;
3075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076 return 0;
3077}
3078
3079
3080static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003081 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003083 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084 if (wpa_s->drv_priv) {
3085 wpa_supplicant_deauthenticate(wpa_s,
3086 WLAN_REASON_DEAUTH_LEAVING);
3087
3088 wpa_drv_set_countermeasures(wpa_s, 0);
3089 wpa_clear_keys(wpa_s, NULL);
3090 }
3091
3092 wpa_supplicant_cleanup(wpa_s);
3093
Dmitry Shmidt04949592012-07-19 12:16:46 -07003094#ifdef CONFIG_P2P
3095 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3096 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3097 "the management interface is being removed");
3098 wpas_p2p_deinit_global(wpa_s->global);
3099 }
3100#endif /* CONFIG_P2P */
3101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003102 if (wpa_s->drv_priv)
3103 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003104
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003105 if (notify)
3106 wpas_notify_iface_removed(wpa_s);
3107
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003108 if (terminate)
3109 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003110
3111 if (wpa_s->ctrl_iface) {
3112 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3113 wpa_s->ctrl_iface = NULL;
3114 }
3115
3116 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003117 wpa_config_free(wpa_s->conf);
3118 wpa_s->conf = NULL;
3119 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003120
3121 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003122}
3123
3124
3125/**
3126 * wpa_supplicant_add_iface - Add a new network interface
3127 * @global: Pointer to global data from wpa_supplicant_init()
3128 * @iface: Interface configuration options
3129 * Returns: Pointer to the created interface or %NULL on failure
3130 *
3131 * This function is used to add new network interfaces for %wpa_supplicant.
3132 * This can be called before wpa_supplicant_run() to add interfaces before the
3133 * main event loop has been started. In addition, new interfaces can be added
3134 * dynamically while %wpa_supplicant is already running. This could happen,
3135 * e.g., when a hotplug network adapter is inserted.
3136 */
3137struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3138 struct wpa_interface *iface)
3139{
3140 struct wpa_supplicant *wpa_s;
3141 struct wpa_interface t_iface;
3142 struct wpa_ssid *ssid;
3143
3144 if (global == NULL || iface == NULL)
3145 return NULL;
3146
3147 wpa_s = wpa_supplicant_alloc();
3148 if (wpa_s == NULL)
3149 return NULL;
3150
3151 wpa_s->global = global;
3152
3153 t_iface = *iface;
3154 if (global->params.override_driver) {
3155 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3156 "('%s' -> '%s')",
3157 iface->driver, global->params.override_driver);
3158 t_iface.driver = global->params.override_driver;
3159 }
3160 if (global->params.override_ctrl_interface) {
3161 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3162 "ctrl_interface ('%s' -> '%s')",
3163 iface->ctrl_interface,
3164 global->params.override_ctrl_interface);
3165 t_iface.ctrl_interface =
3166 global->params.override_ctrl_interface;
3167 }
3168 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3169 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3170 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003171 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003172 return NULL;
3173 }
3174
3175 /* Notify the control interfaces about new iface */
3176 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003177 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003178 return NULL;
3179 }
3180
3181 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3182 wpas_notify_network_added(wpa_s, ssid);
3183
3184 wpa_s->next = global->ifaces;
3185 global->ifaces = wpa_s;
3186
3187 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003188 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003189
3190 return wpa_s;
3191}
3192
3193
3194/**
3195 * wpa_supplicant_remove_iface - Remove a network interface
3196 * @global: Pointer to global data from wpa_supplicant_init()
3197 * @wpa_s: Pointer to the network interface to be removed
3198 * Returns: 0 if interface was removed, -1 if interface was not found
3199 *
3200 * This function can be used to dynamically remove network interfaces from
3201 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3202 * addition, this function is used to remove all remaining interfaces when
3203 * %wpa_supplicant is terminated.
3204 */
3205int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003206 struct wpa_supplicant *wpa_s,
3207 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003208{
3209 struct wpa_supplicant *prev;
3210
3211 /* Remove interface from the global list of interfaces */
3212 prev = global->ifaces;
3213 if (prev == wpa_s) {
3214 global->ifaces = wpa_s->next;
3215 } else {
3216 while (prev && prev->next != wpa_s)
3217 prev = prev->next;
3218 if (prev == NULL)
3219 return -1;
3220 prev->next = wpa_s->next;
3221 }
3222
3223 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3224
3225 if (global->p2p_group_formation == wpa_s)
3226 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003227 if (global->p2p_invite_group == wpa_s)
3228 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003229 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230
3231 return 0;
3232}
3233
3234
3235/**
3236 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3237 * @wpa_s: Pointer to the network interface
3238 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3239 */
3240const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3241{
3242 const char *eapol_method;
3243
3244 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3245 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3246 return "NO-EAP";
3247 }
3248
3249 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3250 if (eapol_method == NULL)
3251 return "UNKNOWN-EAP";
3252
3253 return eapol_method;
3254}
3255
3256
3257/**
3258 * wpa_supplicant_get_iface - Get a new network interface
3259 * @global: Pointer to global data from wpa_supplicant_init()
3260 * @ifname: Interface name
3261 * Returns: Pointer to the interface or %NULL if not found
3262 */
3263struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3264 const char *ifname)
3265{
3266 struct wpa_supplicant *wpa_s;
3267
3268 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3269 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3270 return wpa_s;
3271 }
3272 return NULL;
3273}
3274
3275
3276#ifndef CONFIG_NO_WPA_MSG
3277static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3278{
3279 struct wpa_supplicant *wpa_s = ctx;
3280 if (wpa_s == NULL)
3281 return NULL;
3282 return wpa_s->ifname;
3283}
3284#endif /* CONFIG_NO_WPA_MSG */
3285
3286
3287/**
3288 * wpa_supplicant_init - Initialize %wpa_supplicant
3289 * @params: Parameters for %wpa_supplicant
3290 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3291 *
3292 * This function is used to initialize %wpa_supplicant. After successful
3293 * initialization, the returned data pointer can be used to add and remove
3294 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3295 */
3296struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3297{
3298 struct wpa_global *global;
3299 int ret, i;
3300
3301 if (params == NULL)
3302 return NULL;
3303
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003304#ifdef CONFIG_DRIVER_NDIS
3305 {
3306 void driver_ndis_init_ops(void);
3307 driver_ndis_init_ops();
3308 }
3309#endif /* CONFIG_DRIVER_NDIS */
3310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311#ifndef CONFIG_NO_WPA_MSG
3312 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3313#endif /* CONFIG_NO_WPA_MSG */
3314
3315 wpa_debug_open_file(params->wpa_debug_file_path);
3316 if (params->wpa_debug_syslog)
3317 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003318 if (params->wpa_debug_tracing) {
3319 ret = wpa_debug_open_linux_tracing();
3320 if (ret) {
3321 wpa_printf(MSG_ERROR,
3322 "Failed to enable trace logging");
3323 return NULL;
3324 }
3325 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326
3327 ret = eap_register_methods();
3328 if (ret) {
3329 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3330 if (ret == -2)
3331 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3332 "the same EAP type.");
3333 return NULL;
3334 }
3335
3336 global = os_zalloc(sizeof(*global));
3337 if (global == NULL)
3338 return NULL;
3339 dl_list_init(&global->p2p_srv_bonjour);
3340 dl_list_init(&global->p2p_srv_upnp);
3341 global->params.daemonize = params->daemonize;
3342 global->params.wait_for_monitor = params->wait_for_monitor;
3343 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3344 if (params->pid_file)
3345 global->params.pid_file = os_strdup(params->pid_file);
3346 if (params->ctrl_interface)
3347 global->params.ctrl_interface =
3348 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003349 if (params->ctrl_interface_group)
3350 global->params.ctrl_interface_group =
3351 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 if (params->override_driver)
3353 global->params.override_driver =
3354 os_strdup(params->override_driver);
3355 if (params->override_ctrl_interface)
3356 global->params.override_ctrl_interface =
3357 os_strdup(params->override_ctrl_interface);
3358 wpa_debug_level = global->params.wpa_debug_level =
3359 params->wpa_debug_level;
3360 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3361 params->wpa_debug_show_keys;
3362 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3363 params->wpa_debug_timestamp;
3364
3365 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3366
3367 if (eloop_init()) {
3368 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3369 wpa_supplicant_deinit(global);
3370 return NULL;
3371 }
3372
Jouni Malinen75ecf522011-06-27 15:19:46 -07003373 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374
3375 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3376 if (global->ctrl_iface == NULL) {
3377 wpa_supplicant_deinit(global);
3378 return NULL;
3379 }
3380
3381 if (wpas_notify_supplicant_initialized(global)) {
3382 wpa_supplicant_deinit(global);
3383 return NULL;
3384 }
3385
3386 for (i = 0; wpa_drivers[i]; i++)
3387 global->drv_count++;
3388 if (global->drv_count == 0) {
3389 wpa_printf(MSG_ERROR, "No drivers enabled");
3390 wpa_supplicant_deinit(global);
3391 return NULL;
3392 }
3393 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3394 if (global->drv_priv == NULL) {
3395 wpa_supplicant_deinit(global);
3396 return NULL;
3397 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003398
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003399#ifdef CONFIG_WIFI_DISPLAY
3400 if (wifi_display_init(global) < 0) {
3401 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3402 wpa_supplicant_deinit(global);
3403 return NULL;
3404 }
3405#endif /* CONFIG_WIFI_DISPLAY */
3406
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003407 return global;
3408}
3409
3410
3411/**
3412 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3413 * @global: Pointer to global data from wpa_supplicant_init()
3414 * Returns: 0 after successful event loop run, -1 on failure
3415 *
3416 * This function starts the main event loop and continues running as long as
3417 * there are any remaining events. In most cases, this function is running as
3418 * long as the %wpa_supplicant process in still in use.
3419 */
3420int wpa_supplicant_run(struct wpa_global *global)
3421{
3422 struct wpa_supplicant *wpa_s;
3423
3424 if (global->params.daemonize &&
3425 wpa_supplicant_daemon(global->params.pid_file))
3426 return -1;
3427
3428 if (global->params.wait_for_monitor) {
3429 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3430 if (wpa_s->ctrl_iface)
3431 wpa_supplicant_ctrl_iface_wait(
3432 wpa_s->ctrl_iface);
3433 }
3434
3435 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3436 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3437
3438 eloop_run();
3439
3440 return 0;
3441}
3442
3443
3444/**
3445 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3446 * @global: Pointer to global data from wpa_supplicant_init()
3447 *
3448 * This function is called to deinitialize %wpa_supplicant and to free all
3449 * allocated resources. Remaining network interfaces will also be removed.
3450 */
3451void wpa_supplicant_deinit(struct wpa_global *global)
3452{
3453 int i;
3454
3455 if (global == NULL)
3456 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003457
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003458#ifdef CONFIG_WIFI_DISPLAY
3459 wifi_display_deinit(global);
3460#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003461
3462 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003463 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003464
3465 if (global->ctrl_iface)
3466 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3467
3468 wpas_notify_supplicant_deinitialized(global);
3469
3470 eap_peer_unregister_methods();
3471#ifdef CONFIG_AP
3472 eap_server_unregister_methods();
3473#endif /* CONFIG_AP */
3474
3475 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3476 if (!global->drv_priv[i])
3477 continue;
3478 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3479 }
3480 os_free(global->drv_priv);
3481
3482 random_deinit();
3483
3484 eloop_destroy();
3485
3486 if (global->params.pid_file) {
3487 os_daemonize_terminate(global->params.pid_file);
3488 os_free(global->params.pid_file);
3489 }
3490 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003491 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003492 os_free(global->params.override_driver);
3493 os_free(global->params.override_ctrl_interface);
3494
Dmitry Shmidt04949592012-07-19 12:16:46 -07003495 os_free(global->p2p_disallow_freq);
3496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497 os_free(global);
3498 wpa_debug_close_syslog();
3499 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003500 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501}
3502
3503
3504void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3505{
3506 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3507 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3508 char country[3];
3509 country[0] = wpa_s->conf->country[0];
3510 country[1] = wpa_s->conf->country[1];
3511 country[2] = '\0';
3512 if (wpa_drv_set_country(wpa_s, country) < 0) {
3513 wpa_printf(MSG_ERROR, "Failed to set country code "
3514 "'%s'", country);
3515 }
3516 }
3517
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003518 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3519 wpas_init_ext_pw(wpa_s);
3520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521#ifdef CONFIG_WPS
3522 wpas_wps_update_config(wpa_s);
3523#endif /* CONFIG_WPS */
3524
3525#ifdef CONFIG_P2P
3526 wpas_p2p_update_config(wpa_s);
3527#endif /* CONFIG_P2P */
3528
3529 wpa_s->conf->changed_parameters = 0;
3530}
3531
3532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533static void add_freq(int *freqs, int *num_freqs, int freq)
3534{
3535 int i;
3536
3537 for (i = 0; i < *num_freqs; i++) {
3538 if (freqs[i] == freq)
3539 return;
3540 }
3541
3542 freqs[*num_freqs] = freq;
3543 (*num_freqs)++;
3544}
3545
3546
3547static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3548{
3549 struct wpa_bss *bss, *cbss;
3550 const int max_freqs = 10;
3551 int *freqs;
3552 int num_freqs = 0;
3553
3554 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3555 if (freqs == NULL)
3556 return NULL;
3557
3558 cbss = wpa_s->current_bss;
3559
3560 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3561 if (bss == cbss)
3562 continue;
3563 if (bss->ssid_len == cbss->ssid_len &&
3564 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3565 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3566 add_freq(freqs, &num_freqs, bss->freq);
3567 if (num_freqs == max_freqs)
3568 break;
3569 }
3570 }
3571
3572 if (num_freqs == 0) {
3573 os_free(freqs);
3574 freqs = NULL;
3575 }
3576
3577 return freqs;
3578}
3579
3580
3581void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3582{
3583 int timeout;
3584 int count;
3585 int *freqs = NULL;
3586
3587 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003588 * Remove possible authentication timeout since the connection failed.
3589 */
3590 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3591
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003592 if (wpa_s->disconnected) {
3593 /*
3594 * There is no point in blacklisting the AP if this event is
3595 * generated based on local request to disconnect.
3596 */
3597 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
3598 "indication since interface has been put into "
3599 "disconnected state");
3600 return;
3601 }
3602
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003603 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003604 * Add the failed BSSID into the blacklist and speed up next scan
3605 * attempt if there could be other APs that could accept association.
3606 * The current blacklist count indicates how many times we have tried
3607 * connecting to this AP and multiple attempts mean that other APs are
3608 * either not available or has already been tried, so that we can start
3609 * increasing the delay here to avoid constant scanning.
3610 */
3611 count = wpa_blacklist_add(wpa_s, bssid);
3612 if (count == 1 && wpa_s->current_bss) {
3613 /*
3614 * This BSS was not in the blacklist before. If there is
3615 * another BSS available for the same ESS, we should try that
3616 * next. Otherwise, we may as well try this one once more
3617 * before allowing other, likely worse, ESSes to be considered.
3618 */
3619 freqs = get_bss_freqs_in_ess(wpa_s);
3620 if (freqs) {
3621 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3622 "has been seen; try it next");
3623 wpa_blacklist_add(wpa_s, bssid);
3624 /*
3625 * On the next scan, go through only the known channels
3626 * used in this ESS based on previous scans to speed up
3627 * common load balancing use case.
3628 */
3629 os_free(wpa_s->next_scan_freqs);
3630 wpa_s->next_scan_freqs = freqs;
3631 }
3632 }
3633
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003634 /*
3635 * Add previous failure count in case the temporary blacklist was
3636 * cleared due to no other BSSes being available.
3637 */
3638 count += wpa_s->extra_blacklist_count;
3639
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003640 if (count > 3 && wpa_s->current_ssid) {
3641 wpa_printf(MSG_DEBUG, "Continuous association failures - "
3642 "consider temporary network disabling");
3643 wpas_auth_failed(wpa_s);
3644 }
3645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 switch (count) {
3647 case 1:
3648 timeout = 100;
3649 break;
3650 case 2:
3651 timeout = 500;
3652 break;
3653 case 3:
3654 timeout = 1000;
3655 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003656 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003657 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003658 break;
3659 default:
3660 timeout = 10000;
3661 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662 }
3663
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003664 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3665 "ms", count, timeout);
3666
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 /*
3668 * TODO: if more than one possible AP is available in scan results,
3669 * could try the other ones before requesting a new scan.
3670 */
3671 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3672 1000 * (timeout % 1000));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003673
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07003674 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003676
3677
3678int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3679{
3680 return wpa_s->conf->ap_scan == 2 ||
3681 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3682}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003683
Dmitry Shmidt04949592012-07-19 12:16:46 -07003684
3685#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3686int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3687 struct wpa_ssid *ssid,
3688 const char *field,
3689 const char *value)
3690{
3691#ifdef IEEE8021X_EAPOL
3692 struct eap_peer_config *eap = &ssid->eap;
3693
3694 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3695 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3696 (const u8 *) value, os_strlen(value));
3697
3698 switch (wpa_supplicant_ctrl_req_from_string(field)) {
3699 case WPA_CTRL_REQ_EAP_IDENTITY:
3700 os_free(eap->identity);
3701 eap->identity = (u8 *) os_strdup(value);
3702 eap->identity_len = os_strlen(value);
3703 eap->pending_req_identity = 0;
3704 if (ssid == wpa_s->current_ssid)
3705 wpa_s->reassociate = 1;
3706 break;
3707 case WPA_CTRL_REQ_EAP_PASSWORD:
3708 os_free(eap->password);
3709 eap->password = (u8 *) os_strdup(value);
3710 eap->password_len = os_strlen(value);
3711 eap->pending_req_password = 0;
3712 if (ssid == wpa_s->current_ssid)
3713 wpa_s->reassociate = 1;
3714 break;
3715 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3716 os_free(eap->new_password);
3717 eap->new_password = (u8 *) os_strdup(value);
3718 eap->new_password_len = os_strlen(value);
3719 eap->pending_req_new_password = 0;
3720 if (ssid == wpa_s->current_ssid)
3721 wpa_s->reassociate = 1;
3722 break;
3723 case WPA_CTRL_REQ_EAP_PIN:
3724 os_free(eap->pin);
3725 eap->pin = os_strdup(value);
3726 eap->pending_req_pin = 0;
3727 if (ssid == wpa_s->current_ssid)
3728 wpa_s->reassociate = 1;
3729 break;
3730 case WPA_CTRL_REQ_EAP_OTP:
3731 os_free(eap->otp);
3732 eap->otp = (u8 *) os_strdup(value);
3733 eap->otp_len = os_strlen(value);
3734 os_free(eap->pending_req_otp);
3735 eap->pending_req_otp = NULL;
3736 eap->pending_req_otp_len = 0;
3737 break;
3738 case WPA_CTRL_REQ_EAP_PASSPHRASE:
3739 os_free(eap->private_key_passwd);
3740 eap->private_key_passwd = (u8 *) os_strdup(value);
3741 eap->pending_req_passphrase = 0;
3742 if (ssid == wpa_s->current_ssid)
3743 wpa_s->reassociate = 1;
3744 break;
3745 default:
3746 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3747 return -1;
3748 }
3749
3750 return 0;
3751#else /* IEEE8021X_EAPOL */
3752 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3753 return -1;
3754#endif /* IEEE8021X_EAPOL */
3755}
3756#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3757
3758
3759int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3760{
3761 int i;
3762 unsigned int drv_enc;
3763
3764 if (ssid == NULL)
3765 return 1;
3766
3767 if (ssid->disabled)
3768 return 1;
3769
3770 if (wpa_s && wpa_s->drv_capa_known)
3771 drv_enc = wpa_s->drv_enc;
3772 else
3773 drv_enc = (unsigned int) -1;
3774
3775 for (i = 0; i < NUM_WEP_KEYS; i++) {
3776 size_t len = ssid->wep_key_len[i];
3777 if (len == 0)
3778 continue;
3779 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3780 continue;
3781 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3782 continue;
3783 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3784 continue;
3785 return 1; /* invalid WEP key */
3786 }
3787
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003788 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
3789 !ssid->ext_psk)
3790 return 1;
3791
Dmitry Shmidt04949592012-07-19 12:16:46 -07003792 return 0;
3793}
3794
3795
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003796int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003797{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003798 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003799 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003800 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003801 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003802 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003803}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003804
3805
3806void wpas_auth_failed(struct wpa_supplicant *wpa_s)
3807{
3808 struct wpa_ssid *ssid = wpa_s->current_ssid;
3809 int dur;
3810 struct os_time now;
3811
3812 if (ssid == NULL) {
3813 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3814 "SSID block");
3815 return;
3816 }
3817
3818 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3819 return;
3820
3821 ssid->auth_failures++;
3822 if (ssid->auth_failures > 50)
3823 dur = 300;
3824 else if (ssid->auth_failures > 20)
3825 dur = 120;
3826 else if (ssid->auth_failures > 10)
3827 dur = 60;
3828 else if (ssid->auth_failures > 5)
3829 dur = 30;
3830 else if (ssid->auth_failures > 1)
3831 dur = 20;
3832 else
3833 dur = 10;
3834
3835 os_get_time(&now);
3836 if (now.sec + dur <= ssid->disabled_until.sec)
3837 return;
3838
3839 ssid->disabled_until.sec = now.sec + dur;
3840
3841 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
3842 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
3843 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
3844 ssid->auth_failures, dur);
3845}
3846
3847
3848void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
3849 struct wpa_ssid *ssid, int clear_failures)
3850{
3851 if (ssid == NULL)
3852 return;
3853
3854 if (ssid->disabled_until.sec) {
3855 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
3856 "id=%d ssid=\"%s\"",
3857 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3858 }
3859 ssid->disabled_until.sec = 0;
3860 ssid->disabled_until.usec = 0;
3861 if (clear_failures)
3862 ssid->auth_failures = 0;
3863}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003864
3865
3866int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
3867{
3868 size_t i;
3869
3870 if (wpa_s->disallow_aps_bssid == NULL)
3871 return 0;
3872
3873 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
3874 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
3875 bssid, ETH_ALEN) == 0)
3876 return 1;
3877 }
3878
3879 return 0;
3880}
3881
3882
3883int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
3884 size_t ssid_len)
3885{
3886 size_t i;
3887
3888 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
3889 return 0;
3890
3891 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
3892 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
3893 if (ssid_len == s->ssid_len &&
3894 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3895 return 1;
3896 }
3897
3898 return 0;
3899}
3900
3901
3902/**
3903 * wpas_request_connection - Request a new connection
3904 * @wpa_s: Pointer to the network interface
3905 *
3906 * This function is used to request a new connection to be found. It will mark
3907 * the interface to allow reassociation and request a new scan to find a
3908 * suitable network to connect to.
3909 */
3910void wpas_request_connection(struct wpa_supplicant *wpa_s)
3911{
3912 wpa_s->normal_scans = 0;
3913 wpa_supplicant_reinit_autoscan(wpa_s);
3914 wpa_s->extra_blacklist_count = 0;
3915 wpa_s->disconnected = 0;
3916 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08003917
3918 if (wpa_supplicant_fast_associate(wpa_s) != 1)
3919 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003920}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003921
3922
3923/**
3924 * wpas_wpa_is_in_progress - Check whether a connection is in progress
3925 * @wpa_s: Pointer to wpa_supplicant data
3926 *
3927 * This function is to check if the wpa state is in beginning of the connection
3928 * during 4-way handshake or group key handshake with WPA on any shared
3929 * interface.
3930 */
3931int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
3932{
3933 const char *rn, *rn2;
3934 struct wpa_supplicant *ifs;
3935
3936 if (!wpa_s->driver->get_radio_name)
3937 return 0;
3938
3939 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3940 if (rn == NULL || rn[0] == '\0')
3941 return 0;
3942
3943 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3944 if (ifs == wpa_s || !ifs->driver->get_radio_name)
3945 continue;
3946
3947 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
3948 if (!rn2 || os_strcmp(rn, rn2) != 0)
3949 continue;
3950 if (ifs->wpa_state >= WPA_AUTHENTICATING &&
3951 ifs->wpa_state != WPA_COMPLETED) {
3952 wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
3953 "on interface %s - defer scan", ifs->ifname);
3954 return 1;
3955 }
3956 }
3957
3958 return 0;
3959}