blob: a6bd935c5e5a1a3cf602cdc8f7a4efd4eacc394c [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
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700424 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425 wpa_supplicant_cancel_scan(wpa_s);
426 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800427 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
428#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
429 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
430 wpa_s, NULL);
431#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432
433 wpas_wps_deinit(wpa_s);
434
435 wpabuf_free(wpa_s->pending_eapol_rx);
436 wpa_s->pending_eapol_rx = NULL;
437
438#ifdef CONFIG_IBSS_RSN
439 ibss_rsn_deinit(wpa_s->ibss_rsn);
440 wpa_s->ibss_rsn = NULL;
441#endif /* CONFIG_IBSS_RSN */
442
443 sme_deinit(wpa_s);
444
445#ifdef CONFIG_AP
446 wpa_supplicant_ap_deinit(wpa_s);
447#endif /* CONFIG_AP */
448
449#ifdef CONFIG_P2P
450 wpas_p2p_deinit(wpa_s);
451#endif /* CONFIG_P2P */
452
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800453#ifdef CONFIG_OFFCHANNEL
454 offchannel_deinit(wpa_s);
455#endif /* CONFIG_OFFCHANNEL */
456
457 wpa_supplicant_cancel_sched_scan(wpa_s);
458
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700459 os_free(wpa_s->next_scan_freqs);
460 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800461
462 gas_query_deinit(wpa_s->gas);
463 wpa_s->gas = NULL;
464
465 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700466
467 os_free(wpa_s->bssid_filter);
468 wpa_s->bssid_filter = NULL;
469
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800470 os_free(wpa_s->disallow_aps_bssid);
471 wpa_s->disallow_aps_bssid = NULL;
472 os_free(wpa_s->disallow_aps_ssid);
473 wpa_s->disallow_aps_ssid = NULL;
474
Dmitry Shmidt04949592012-07-19 12:16:46 -0700475 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700476#ifdef CONFIG_WNM
477 wnm_deallocate_memory(wpa_s);
478#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700479
480 ext_password_deinit(wpa_s->ext_pw);
481 wpa_s->ext_pw = NULL;
482
483 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700484
485 os_free(wpa_s->last_scan_res);
486 wpa_s->last_scan_res = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487}
488
489
490/**
491 * wpa_clear_keys - Clear keys configured for the driver
492 * @wpa_s: Pointer to wpa_supplicant data
493 * @addr: Previously used BSSID or %NULL if not available
494 *
495 * This function clears the encryption keys that has been previously configured
496 * for the driver.
497 */
498void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
499{
500 if (wpa_s->keys_cleared) {
501 /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have
502 * timing issues with keys being cleared just before new keys
503 * are set or just after association or something similar. This
504 * shows up in group key handshake failing often because of the
505 * client not receiving the first encrypted packets correctly.
506 * Skipping some of the extra key clearing steps seems to help
507 * in completing group key handshake more reliably. */
508 wpa_dbg(wpa_s, MSG_DEBUG, "No keys have been configured - "
509 "skip key clearing");
510 return;
511 }
512
513 /* MLME-DELETEKEYS.request */
514 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 0, 0, NULL, 0, NULL, 0);
515 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 1, 0, NULL, 0, NULL, 0);
516 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 2, 0, NULL, 0, NULL, 0);
517 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 3, 0, NULL, 0, NULL, 0);
518#ifdef CONFIG_IEEE80211W
519 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 4, 0, NULL, 0, NULL, 0);
520 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, 5, 0, NULL, 0, NULL, 0);
521#endif /* CONFIG_IEEE80211W */
522 if (addr) {
523 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
524 0);
525 /* MLME-SETPROTECTION.request(None) */
526 wpa_drv_mlme_setprotection(
527 wpa_s, addr,
528 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
529 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
530 }
531 wpa_s->keys_cleared = 1;
532}
533
534
535/**
536 * wpa_supplicant_state_txt - Get the connection state name as a text string
537 * @state: State (wpa_state; WPA_*)
538 * Returns: The state name as a printable text string
539 */
540const char * wpa_supplicant_state_txt(enum wpa_states state)
541{
542 switch (state) {
543 case WPA_DISCONNECTED:
544 return "DISCONNECTED";
545 case WPA_INACTIVE:
546 return "INACTIVE";
547 case WPA_INTERFACE_DISABLED:
548 return "INTERFACE_DISABLED";
549 case WPA_SCANNING:
550 return "SCANNING";
551 case WPA_AUTHENTICATING:
552 return "AUTHENTICATING";
553 case WPA_ASSOCIATING:
554 return "ASSOCIATING";
555 case WPA_ASSOCIATED:
556 return "ASSOCIATED";
557 case WPA_4WAY_HANDSHAKE:
558 return "4WAY_HANDSHAKE";
559 case WPA_GROUP_HANDSHAKE:
560 return "GROUP_HANDSHAKE";
561 case WPA_COMPLETED:
562 return "COMPLETED";
563 default:
564 return "UNKNOWN";
565 }
566}
567
568
569#ifdef CONFIG_BGSCAN
570
571static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
572{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800573 if (wpas_driver_bss_selection(wpa_s))
574 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700575 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
576 return;
577
578 bgscan_deinit(wpa_s);
579 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) {
580 if (bgscan_init(wpa_s, wpa_s->current_ssid)) {
581 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
582 "bgscan");
583 /*
584 * Live without bgscan; it is only used as a roaming
585 * optimization, so the initial connection is not
586 * affected.
587 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700588 } else {
589 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700591 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
592 0);
593 if (scan_res) {
594 bgscan_notify_scan(wpa_s, scan_res);
595 wpa_scan_results_free(scan_res);
596 }
597 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700598 } else
599 wpa_s->bgscan_ssid = NULL;
600}
601
602
603static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
604{
605 if (wpa_s->bgscan_ssid != NULL) {
606 bgscan_deinit(wpa_s);
607 wpa_s->bgscan_ssid = NULL;
608 }
609}
610
611#endif /* CONFIG_BGSCAN */
612
613
Dmitry Shmidt04949592012-07-19 12:16:46 -0700614static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
615{
616 if (autoscan_init(wpa_s, 0))
617 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
618}
619
620
621static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
622{
623 autoscan_deinit(wpa_s);
624}
625
626
627void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
628{
629 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
630 wpa_s->wpa_state == WPA_SCANNING) {
631 autoscan_deinit(wpa_s);
632 wpa_supplicant_start_autoscan(wpa_s);
633 }
634}
635
636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637/**
638 * wpa_supplicant_set_state - Set current connection state
639 * @wpa_s: Pointer to wpa_supplicant data
640 * @state: The new connection state
641 *
642 * This function is called whenever the connection state changes, e.g.,
643 * association is completed for WPA/WPA2 4-Way Handshake is started.
644 */
645void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
646 enum wpa_states state)
647{
648 enum wpa_states old_state = wpa_s->wpa_state;
649
650 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
651 wpa_supplicant_state_txt(wpa_s->wpa_state),
652 wpa_supplicant_state_txt(state));
653
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700654#ifdef ANDROID_P2P
Irfan Sheriff7db4ef72012-06-18 09:39:07 -0700655 if(state == WPA_ASSOCIATED && wpa_s->current_ssid) {
656 wpa_s->current_ssid->assoc_retry = 0;
657 }
Dmitry Shmidt98f9e762012-05-30 11:18:46 -0700658#endif /* ANDROID_P2P */
659
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660 if (state != WPA_SCANNING)
661 wpa_supplicant_notify_scanning(wpa_s, 0);
662
663 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700665#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800667 MACSTR " completed (auth) [id=%d id_str=%s]",
668 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700669 ssid ? ssid->id : -1,
670 ssid && ssid->id_str ? ssid->id_str : "");
671#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700672 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800673 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700674 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700675 wpa_drv_set_operstate(wpa_s, 1);
676#ifndef IEEE8021X_EAPOL
677 wpa_drv_set_supp_port(wpa_s, 1);
678#endif /* IEEE8021X_EAPOL */
679 wpa_s->after_wps = 0;
680#ifdef CONFIG_P2P
681 wpas_p2p_completed(wpa_s);
682#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700683
684 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
686 state == WPA_ASSOCIATED) {
687 wpa_s->new_connection = 1;
688 wpa_drv_set_operstate(wpa_s, 0);
689#ifndef IEEE8021X_EAPOL
690 wpa_drv_set_supp_port(wpa_s, 0);
691#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700692 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693 }
694 wpa_s->wpa_state = state;
695
696#ifdef CONFIG_BGSCAN
697 if (state == WPA_COMPLETED)
698 wpa_supplicant_start_bgscan(wpa_s);
699 else
700 wpa_supplicant_stop_bgscan(wpa_s);
701#endif /* CONFIG_BGSCAN */
702
Dmitry Shmidt04949592012-07-19 12:16:46 -0700703 if (state == WPA_AUTHENTICATING)
704 wpa_supplicant_stop_autoscan(wpa_s);
705
706 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
707 wpa_supplicant_start_autoscan(wpa_s);
708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709 if (wpa_s->wpa_state != old_state) {
710 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
711
712 if (wpa_s->wpa_state == WPA_COMPLETED ||
713 old_state == WPA_COMPLETED)
714 wpas_notify_auth_changed(wpa_s);
715 }
716}
717
718
719void wpa_supplicant_terminate_proc(struct wpa_global *global)
720{
721 int pending = 0;
722#ifdef CONFIG_WPS
723 struct wpa_supplicant *wpa_s = global->ifaces;
724 while (wpa_s) {
725 if (wpas_wps_terminate_pending(wpa_s) == 1)
726 pending = 1;
727 wpa_s = wpa_s->next;
728 }
729#endif /* CONFIG_WPS */
730 if (pending)
731 return;
732 eloop_terminate();
733}
734
735
736static void wpa_supplicant_terminate(int sig, void *signal_ctx)
737{
738 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 wpa_supplicant_terminate_proc(global);
740}
741
742
743void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
744{
745 enum wpa_states old_state = wpa_s->wpa_state;
746
747 wpa_s->pairwise_cipher = 0;
748 wpa_s->group_cipher = 0;
749 wpa_s->mgmt_group_cipher = 0;
750 wpa_s->key_mgmt = 0;
751 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700752 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753
754 if (wpa_s->wpa_state != old_state)
755 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
756}
757
758
759/**
760 * wpa_supplicant_reload_configuration - Reload configuration data
761 * @wpa_s: Pointer to wpa_supplicant data
762 * Returns: 0 on success or -1 if configuration parsing failed
763 *
764 * This function can be used to request that the configuration data is reloaded
765 * (e.g., after configuration file change). This function is reloading
766 * configuration only for one interface, so this may need to be called multiple
767 * times if %wpa_supplicant is controlling multiple interfaces and all
768 * interfaces need reconfiguration.
769 */
770int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
771{
772 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773 int reconf_ctrl;
774 int old_ap_scan;
775
776 if (wpa_s->confname == NULL)
777 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700778 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 if (conf == NULL) {
780 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
781 "file '%s' - exiting", wpa_s->confname);
782 return -1;
783 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700784 wpa_config_read(wpa_s->confanother, conf);
785
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786 conf->changed_parameters = (unsigned int) -1;
787
788 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
789 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
790 os_strcmp(conf->ctrl_interface,
791 wpa_s->conf->ctrl_interface) != 0);
792
793 if (reconf_ctrl && wpa_s->ctrl_iface) {
794 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
795 wpa_s->ctrl_iface = NULL;
796 }
797
798 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800799 if (wpa_s->current_ssid) {
800 wpa_supplicant_deauthenticate(wpa_s,
801 WLAN_REASON_DEAUTH_LEAVING);
802 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803
804 /*
805 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
806 * pkcs11_engine_path, pkcs11_module_path.
807 */
808 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
809 /*
810 * Clear forced success to clear EAP state for next
811 * authentication.
812 */
813 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
814 }
815 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
816 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800817 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700818 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
819 rsn_preauth_deinit(wpa_s->wpa);
820
821 old_ap_scan = wpa_s->conf->ap_scan;
822 wpa_config_free(wpa_s->conf);
823 wpa_s->conf = conf;
824 if (old_ap_scan != wpa_s->conf->ap_scan)
825 wpas_notify_ap_scan_changed(wpa_s);
826
827 if (reconf_ctrl)
828 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
829
830 wpa_supplicant_update_config(wpa_s);
831
832 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700833 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700834 wpa_s->reassociate = 1;
835 wpa_supplicant_req_scan(wpa_s, 0, 0);
836 }
837 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
838 return 0;
839}
840
841
842static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
843{
844 struct wpa_global *global = signal_ctx;
845 struct wpa_supplicant *wpa_s;
846 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
847 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
848 sig);
849 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
850 wpa_supplicant_terminate_proc(global);
851 }
852 }
853}
854
855
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700856enum wpa_key_mgmt key_mgmt2driver(int key_mgmt)
857{
858 switch (key_mgmt) {
859 case WPA_KEY_MGMT_NONE:
860 return KEY_MGMT_NONE;
861 case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
862 return KEY_MGMT_802_1X_NO_WPA;
863 case WPA_KEY_MGMT_IEEE8021X:
864 return KEY_MGMT_802_1X;
865 case WPA_KEY_MGMT_WPA_NONE:
866 return KEY_MGMT_WPA_NONE;
867 case WPA_KEY_MGMT_FT_IEEE8021X:
868 return KEY_MGMT_FT_802_1X;
869 case WPA_KEY_MGMT_FT_PSK:
870 return KEY_MGMT_FT_PSK;
871 case WPA_KEY_MGMT_IEEE8021X_SHA256:
872 return KEY_MGMT_802_1X_SHA256;
873 case WPA_KEY_MGMT_PSK_SHA256:
874 return KEY_MGMT_PSK_SHA256;
875 case WPA_KEY_MGMT_WPS:
876 return KEY_MGMT_WPS;
877 case WPA_KEY_MGMT_PSK:
878 default:
879 return KEY_MGMT_PSK;
880 }
881}
882
883
884static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
885 struct wpa_ssid *ssid,
886 struct wpa_ie_data *ie)
887{
888 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
889 if (ret) {
890 if (ret == -2) {
891 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
892 "from association info");
893 }
894 return -1;
895 }
896
897 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
898 "cipher suites");
899 if (!(ie->group_cipher & ssid->group_cipher)) {
900 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
901 "cipher 0x%x (mask 0x%x) - reject",
902 ie->group_cipher, ssid->group_cipher);
903 return -1;
904 }
905 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
906 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
907 "cipher 0x%x (mask 0x%x) - reject",
908 ie->pairwise_cipher, ssid->pairwise_cipher);
909 return -1;
910 }
911 if (!(ie->key_mgmt & ssid->key_mgmt)) {
912 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
913 "management 0x%x (mask 0x%x) - reject",
914 ie->key_mgmt, ssid->key_mgmt);
915 return -1;
916 }
917
918#ifdef CONFIG_IEEE80211W
919 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800920 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
921 wpa_s->conf->pmf : ssid->ieee80211w) ==
922 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700923 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
924 "that does not support management frame protection - "
925 "reject");
926 return -1;
927 }
928#endif /* CONFIG_IEEE80211W */
929
930 return 0;
931}
932
933
934/**
935 * wpa_supplicant_set_suites - Set authentication and encryption parameters
936 * @wpa_s: Pointer to wpa_supplicant data
937 * @bss: Scan results for the selected BSS, or %NULL if not available
938 * @ssid: Configuration data for the selected network
939 * @wpa_ie: Buffer for the WPA/RSN IE
940 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
941 * used buffer length in case the functions returns success.
942 * Returns: 0 on success or -1 on failure
943 *
944 * This function is used to configure authentication and encryption parameters
945 * based on the network configuration and scan result for the selected BSS (if
946 * available).
947 */
948int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
949 struct wpa_bss *bss, struct wpa_ssid *ssid,
950 u8 *wpa_ie, size_t *wpa_ie_len)
951{
952 struct wpa_ie_data ie;
953 int sel, proto;
954 const u8 *bss_wpa, *bss_rsn;
955
956 if (bss) {
957 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
958 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
959 } else
960 bss_wpa = bss_rsn = NULL;
961
962 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
963 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
964 (ie.group_cipher & ssid->group_cipher) &&
965 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
966 (ie.key_mgmt & ssid->key_mgmt)) {
967 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
968 proto = WPA_PROTO_RSN;
969 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
970 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
971 (ie.group_cipher & ssid->group_cipher) &&
972 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
973 (ie.key_mgmt & ssid->key_mgmt)) {
974 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
975 proto = WPA_PROTO_WPA;
976 } else if (bss) {
977 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
978 return -1;
979 } else {
980 if (ssid->proto & WPA_PROTO_RSN)
981 proto = WPA_PROTO_RSN;
982 else
983 proto = WPA_PROTO_WPA;
984 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
985 os_memset(&ie, 0, sizeof(ie));
986 ie.group_cipher = ssid->group_cipher;
987 ie.pairwise_cipher = ssid->pairwise_cipher;
988 ie.key_mgmt = ssid->key_mgmt;
989#ifdef CONFIG_IEEE80211W
990 ie.mgmt_group_cipher =
991 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
992 WPA_CIPHER_AES_128_CMAC : 0;
993#endif /* CONFIG_IEEE80211W */
994 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
995 "based on configuration");
996 } else
997 proto = ie.proto;
998 }
999
1000 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1001 "pairwise %d key_mgmt %d proto %d",
1002 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1003#ifdef CONFIG_IEEE80211W
1004 if (ssid->ieee80211w) {
1005 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1006 ie.mgmt_group_cipher);
1007 }
1008#endif /* CONFIG_IEEE80211W */
1009
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001010 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001011 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1012 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
1013 !!(ssid->proto & WPA_PROTO_RSN));
1014
1015 if (bss || !wpa_s->ap_ies_from_associnfo) {
1016 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1017 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1018 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1019 bss_rsn ? 2 + bss_rsn[1] : 0))
1020 return -1;
1021 }
1022
1023 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001024 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1025 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001026 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1027 "cipher");
1028 return -1;
1029 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001030 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1031 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032
1033 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001034 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1035 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1037 "cipher");
1038 return -1;
1039 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001040 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1041 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042
1043 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001044#ifdef CONFIG_SAE
1045 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1046 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1047#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001048 if (0) {
1049#ifdef CONFIG_IEEE80211R
1050 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1051 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1052 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1053 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1054 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1055 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1056#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001057#ifdef CONFIG_SAE
1058 } else if (sel & WPA_KEY_MGMT_SAE) {
1059 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1060 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1061 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1062 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1063 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1064#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001065#ifdef CONFIG_IEEE80211W
1066 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1067 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1068 wpa_dbg(wpa_s, MSG_DEBUG,
1069 "WPA: using KEY_MGMT 802.1X with SHA256");
1070 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1071 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1072 wpa_dbg(wpa_s, MSG_DEBUG,
1073 "WPA: using KEY_MGMT PSK with SHA256");
1074#endif /* CONFIG_IEEE80211W */
1075 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1076 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1077 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1078 } else if (sel & WPA_KEY_MGMT_PSK) {
1079 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1080 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1081 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1082 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1083 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1084 } else {
1085 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1086 "authenticated key management type");
1087 return -1;
1088 }
1089
1090 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1091 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1092 wpa_s->pairwise_cipher);
1093 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1094
1095#ifdef CONFIG_IEEE80211W
1096 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001097 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1098 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1100 sel = 0;
1101 if (sel & WPA_CIPHER_AES_128_CMAC) {
1102 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1103 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1104 "AES-128-CMAC");
1105 } else {
1106 wpa_s->mgmt_group_cipher = 0;
1107 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1108 }
1109 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1110 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001111 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1112 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1113 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001114#endif /* CONFIG_IEEE80211W */
1115
1116 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1117 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1118 return -1;
1119 }
1120
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001121 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001122 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001123#ifndef CONFIG_NO_PBKDF2
1124 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1125 ssid->passphrase) {
1126 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001127 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1128 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001129 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1130 psk, PMK_LEN);
1131 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1132 }
1133#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001134#ifdef CONFIG_EXT_PASSWORD
1135 if (ssid->ext_psk) {
1136 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1137 ssid->ext_psk);
1138 char pw_str[64 + 1];
1139 u8 psk[PMK_LEN];
1140
1141 if (pw == NULL) {
1142 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1143 "found from external storage");
1144 return -1;
1145 }
1146
1147 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1148 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1149 "PSK length %d in external storage",
1150 (int) wpabuf_len(pw));
1151 ext_password_free(pw);
1152 return -1;
1153 }
1154
1155 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1156 pw_str[wpabuf_len(pw)] = '\0';
1157
1158#ifndef CONFIG_NO_PBKDF2
1159 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1160 {
1161 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1162 4096, psk, PMK_LEN);
1163 os_memset(pw_str, 0, sizeof(pw_str));
1164 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1165 "external passphrase)",
1166 psk, PMK_LEN);
1167 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1168 } else
1169#endif /* CONFIG_NO_PBKDF2 */
1170 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1171 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1172 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1173 "Invalid PSK hex string");
1174 os_memset(pw_str, 0, sizeof(pw_str));
1175 ext_password_free(pw);
1176 return -1;
1177 }
1178 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1179 } else {
1180 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1181 "PSK available");
1182 os_memset(pw_str, 0, sizeof(pw_str));
1183 ext_password_free(pw);
1184 return -1;
1185 }
1186
1187 os_memset(pw_str, 0, sizeof(pw_str));
1188 ext_password_free(pw);
1189 }
1190#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001191 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001192 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1193
1194 return 0;
1195}
1196
1197
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001198static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1199{
1200 *pos = 0x00;
1201
1202 switch (idx) {
1203 case 0: /* Bits 0-7 */
1204 break;
1205 case 1: /* Bits 8-15 */
1206 break;
1207 case 2: /* Bits 16-23 */
1208#ifdef CONFIG_WNM
1209 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1210 *pos |= 0x08; /* Bit 19 - BSS Transition */
1211#endif /* CONFIG_WNM */
1212 break;
1213 case 3: /* Bits 24-31 */
1214#ifdef CONFIG_WNM
1215 *pos |= 0x02; /* Bit 25 - SSID List */
1216#endif /* CONFIG_WNM */
1217#ifdef CONFIG_INTERWORKING
1218 if (wpa_s->conf->interworking)
1219 *pos |= 0x80; /* Bit 31 - Interworking */
1220#endif /* CONFIG_INTERWORKING */
1221 break;
1222 case 4: /* Bits 32-39 */
1223 break;
1224 case 5: /* Bits 40-47 */
1225 break;
1226 case 6: /* Bits 48-55 */
1227 break;
1228 }
1229}
1230
1231
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001232int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1233{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001234 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001235 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001236
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001237 if (len < wpa_s->extended_capa_len)
1238 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001239
1240 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001241 *pos++ = len;
1242 for (i = 0; i < len; i++, pos++) {
1243 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001244
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001245 if (i < wpa_s->extended_capa_len) {
1246 *pos &= ~wpa_s->extended_capa_mask[i];
1247 *pos |= wpa_s->extended_capa[i];
1248 }
1249 }
1250
1251 while (len > 0 && buf[1 + len] == 0) {
1252 len--;
1253 buf[1] = len;
1254 }
1255 if (len == 0)
1256 return 0;
1257
1258 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001259}
1260
1261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262/**
1263 * wpa_supplicant_associate - Request association
1264 * @wpa_s: Pointer to wpa_supplicant data
1265 * @bss: Scan results for the selected BSS, or %NULL if not available
1266 * @ssid: Configuration data for the selected network
1267 *
1268 * This function is used to request %wpa_supplicant to associate with a BSS.
1269 */
1270void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1271 struct wpa_bss *bss, struct wpa_ssid *ssid)
1272{
1273 u8 wpa_ie[200];
1274 size_t wpa_ie_len;
1275 int use_crypt, ret, i, bssid_changed;
1276 int algs = WPA_AUTH_ALG_OPEN;
1277 enum wpa_cipher cipher_pairwise, cipher_group;
1278 struct wpa_driver_associate_params params;
1279 int wep_keys_set = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 int assoc_failed = 0;
1281 struct wpa_ssid *old_ssid;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001282 u8 ext_capab[10];
1283 int ext_capab_len;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001284#ifdef CONFIG_HT_OVERRIDES
1285 struct ieee80211_ht_capabilities htcaps;
1286 struct ieee80211_ht_capabilities htcaps_mask;
1287#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288
1289#ifdef CONFIG_IBSS_RSN
1290 ibss_rsn_deinit(wpa_s->ibss_rsn);
1291 wpa_s->ibss_rsn = NULL;
1292#endif /* CONFIG_IBSS_RSN */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001293#ifdef ANDROID_P2P
1294 int freq = 0;
1295#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296
1297 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1298 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1299#ifdef CONFIG_AP
1300 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1301 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1302 "mode");
1303 return;
1304 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001305 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1306 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1307 return;
1308 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001309 wpa_s->current_bss = bss;
1310#else /* CONFIG_AP */
1311 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1312 "the build");
1313#endif /* CONFIG_AP */
1314 return;
1315 }
1316
1317#ifdef CONFIG_TDLS
1318 if (bss)
1319 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1320 bss->ie_len);
1321#endif /* CONFIG_TDLS */
1322
1323 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1324 ssid->mode == IEEE80211_MODE_INFRA) {
1325 sme_authenticate(wpa_s, bss, ssid);
1326 return;
1327 }
1328
1329 os_memset(&params, 0, sizeof(params));
1330 wpa_s->reassociate = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001331 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332#ifdef CONFIG_IEEE80211R
1333 const u8 *ie, *md = NULL;
1334#endif /* CONFIG_IEEE80211R */
1335 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1336 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1337 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1338 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1339 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1340 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1341 if (bssid_changed)
1342 wpas_notify_bssid_changed(wpa_s);
1343#ifdef CONFIG_IEEE80211R
1344 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1345 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1346 md = ie + 2;
1347 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1348 if (md) {
1349 /* Prepare for the next transition */
1350 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1351 }
1352#endif /* CONFIG_IEEE80211R */
1353#ifdef CONFIG_WPS
1354 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1355 wpa_s->conf->ap_scan == 2 &&
1356 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1357 /* Use ap_scan==1 style network selection to find the network
1358 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001359 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001360 wpa_s->reassociate = 1;
1361 wpa_supplicant_req_scan(wpa_s, 0, 0);
1362 return;
1363#endif /* CONFIG_WPS */
1364 } else {
1365 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1366 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1367 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1368 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001369 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370 wpa_supplicant_cancel_scan(wpa_s);
1371
1372 /* Starting new association, so clear the possibly used WPA IE from the
1373 * previous association. */
1374 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1375
1376#ifdef IEEE8021X_EAPOL
1377 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1378 if (ssid->leap) {
1379 if (ssid->non_leap == 0)
1380 algs = WPA_AUTH_ALG_LEAP;
1381 else
1382 algs |= WPA_AUTH_ALG_LEAP;
1383 }
1384 }
1385#endif /* IEEE8021X_EAPOL */
1386 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1387 if (ssid->auth_alg) {
1388 algs = ssid->auth_alg;
1389 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1390 "0x%x", algs);
1391 }
1392
1393 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1394 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001395 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001397 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1398 wpa_s->conf->okc :
1399 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001400 (ssid->proto & WPA_PROTO_RSN);
1401 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001402 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1404 wpa_ie_len = sizeof(wpa_ie);
1405 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1406 wpa_ie, &wpa_ie_len)) {
1407 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1408 "key management and encryption suites");
1409 return;
1410 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001411 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1412 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1413 /*
1414 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1415 * use non-WPA since the scan results did not indicate that the
1416 * AP is using WPA or WPA2.
1417 */
1418 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1419 wpa_ie_len = 0;
1420 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001421 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001422 wpa_ie_len = sizeof(wpa_ie);
1423 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1424 wpa_ie, &wpa_ie_len)) {
1425 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1426 "key management and encryption suites (no "
1427 "scan results)");
1428 return;
1429 }
1430#ifdef CONFIG_WPS
1431 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1432 struct wpabuf *wps_ie;
1433 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1434 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1435 wpa_ie_len = wpabuf_len(wps_ie);
1436 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1437 } else
1438 wpa_ie_len = 0;
1439 wpabuf_free(wps_ie);
1440 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1441 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1442 params.wps = WPS_MODE_PRIVACY;
1443 else
1444 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001445 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446#endif /* CONFIG_WPS */
1447 } else {
1448 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1449 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001450 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451 }
1452
1453#ifdef CONFIG_P2P
1454 if (wpa_s->global->p2p) {
1455 u8 *pos;
1456 size_t len;
1457 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458 pos = wpa_ie + wpa_ie_len;
1459 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001460 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1461 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462 if (res >= 0)
1463 wpa_ie_len += res;
1464 }
1465
1466 wpa_s->cross_connect_disallowed = 0;
1467 if (bss) {
1468 struct wpabuf *p2p;
1469 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1470 if (p2p) {
1471 wpa_s->cross_connect_disallowed =
1472 p2p_get_cross_connect_disallowed(p2p);
1473 wpabuf_free(p2p);
1474 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1475 "connection",
1476 wpa_s->cross_connect_disallowed ?
1477 "disallows" : "allows");
1478 }
1479 }
1480#endif /* CONFIG_P2P */
1481
Dmitry Shmidt04949592012-07-19 12:16:46 -07001482#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001483 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001484 struct wpabuf *hs20;
1485 hs20 = wpabuf_alloc(20);
1486 if (hs20) {
1487 wpas_hs20_add_indication(hs20);
1488 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1489 wpabuf_len(hs20));
1490 wpa_ie_len += wpabuf_len(hs20);
1491 wpabuf_free(hs20);
1492 }
1493 }
1494#endif /* CONFIG_HS20 */
1495
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001496 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1497 if (ext_capab_len > 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001498 u8 *pos = wpa_ie;
1499 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1500 pos += 2 + pos[1];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001501 os_memmove(pos + ext_capab_len, pos,
1502 wpa_ie_len - (pos - wpa_ie));
1503 wpa_ie_len += ext_capab_len;
1504 os_memcpy(pos, ext_capab, ext_capab_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001505 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001507 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1508 use_crypt = 1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001509 cipher_pairwise = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher);
1510 cipher_group = wpa_cipher_to_suite_driver(wpa_s->group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1512 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1513 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1514 use_crypt = 0;
1515 if (wpa_set_wep_keys(wpa_s, ssid)) {
1516 use_crypt = 1;
1517 wep_keys_set = 1;
1518 }
1519 }
1520 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1521 use_crypt = 0;
1522
1523#ifdef IEEE8021X_EAPOL
1524 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1525 if ((ssid->eapol_flags &
1526 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1527 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1528 !wep_keys_set) {
1529 use_crypt = 0;
1530 } else {
1531 /* Assume that dynamic WEP-104 keys will be used and
1532 * set cipher suites in order for drivers to expect
1533 * encryption. */
1534 cipher_pairwise = cipher_group = CIPHER_WEP104;
1535 }
1536 }
1537#endif /* IEEE8021X_EAPOL */
1538
1539 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1540 /* Set the key before (and later after) association */
1541 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1542 }
1543
1544 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1545 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 params.ssid = bss->ssid;
1547 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001548 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1549 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1550 MACSTR " freq=%u MHz based on scan results "
1551 "(bssid_set=%d)",
1552 MAC2STR(bss->bssid), bss->freq,
1553 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001554 params.bssid = bss->bssid;
1555 params.freq = bss->freq;
1556 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557 } else {
1558 params.ssid = ssid->ssid;
1559 params.ssid_len = ssid->ssid_len;
1560 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001561
1562 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1563 wpa_s->conf->ap_scan == 2) {
1564 params.bssid = ssid->bssid;
1565 params.fixed_bssid = 1;
1566 }
1567
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001568 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1569 params.freq == 0)
1570 params.freq = ssid->frequency; /* Initial channel for IBSS */
1571 params.wpa_ie = wpa_ie;
1572 params.wpa_ie_len = wpa_ie_len;
1573 params.pairwise_suite = cipher_pairwise;
1574 params.group_suite = cipher_group;
1575 params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001576 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001577 params.auth_alg = algs;
1578 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001579 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 for (i = 0; i < NUM_WEP_KEYS; i++) {
1581 if (ssid->wep_key_len[i])
1582 params.wep_key[i] = ssid->wep_key[i];
1583 params.wep_key_len[i] = ssid->wep_key_len[i];
1584 }
1585 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1586
1587 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
1588 (params.key_mgmt_suite == KEY_MGMT_PSK ||
1589 params.key_mgmt_suite == KEY_MGMT_FT_PSK)) {
1590 params.passphrase = ssid->passphrase;
1591 if (ssid->psk_set)
1592 params.psk = ssid->psk;
1593 }
1594
1595 params.drop_unencrypted = use_crypt;
1596
1597#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001598 params.mgmt_frame_protection =
1599 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1600 wpa_s->conf->pmf : ssid->ieee80211w;
1601 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1603 struct wpa_ie_data ie;
1604 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1605 ie.capabilities &
1606 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1607 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1608 "MFP: require MFP");
1609 params.mgmt_frame_protection =
1610 MGMT_FRAME_PROTECTION_REQUIRED;
1611 }
1612 }
1613#endif /* CONFIG_IEEE80211W */
1614
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001615 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001616
1617 if (wpa_s->parent->set_sta_uapsd)
1618 params.uapsd = wpa_s->parent->sta_uapsd;
1619 else
1620 params.uapsd = -1;
1621
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001622#ifdef CONFIG_HT_OVERRIDES
1623 os_memset(&htcaps, 0, sizeof(htcaps));
1624 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1625 params.htcaps = (u8 *) &htcaps;
1626 params.htcaps_mask = (u8 *) &htcaps_mask;
1627 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1628#endif /* CONFIG_HT_OVERRIDES */
1629
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001630#ifdef ANDROID_P2P
1631 /* If multichannel concurrency is not supported, check for any frequency
1632 * conflict and take appropriate action.
1633 */
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07001634 if ((wpa_s->num_multichan_concurrent < 2) &&
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001635 ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) {
1636 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001637 , freq, params.freq);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001638 if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq, ssid) < 0)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07001639 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001640 }
1641#endif
1642 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001643 if (ret < 0) {
1644 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1645 "failed");
1646 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1647 /*
1648 * The driver is known to mean what is saying, so we
1649 * can stop right here; the association will not
1650 * succeed.
1651 */
1652 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001653 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1655 return;
1656 }
1657 /* try to continue anyway; new association will be tried again
1658 * after timeout */
1659 assoc_failed = 1;
1660 }
1661
1662 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1663 /* Set the key after the association just in case association
1664 * cleared the previously configured key. */
1665 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1666 /* No need to timeout authentication since there is no key
1667 * management. */
1668 wpa_supplicant_cancel_auth_timeout(wpa_s);
1669 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1670#ifdef CONFIG_IBSS_RSN
1671 } else if (ssid->mode == WPAS_MODE_IBSS &&
1672 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1673 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1674 /*
1675 * RSN IBSS authentication is per-STA and we can disable the
1676 * per-BSSID authentication.
1677 */
1678 wpa_supplicant_cancel_auth_timeout(wpa_s);
1679#endif /* CONFIG_IBSS_RSN */
1680 } else {
1681 /* Timeout for IEEE 802.11 authentication and association */
1682 int timeout = 60;
1683
1684 if (assoc_failed) {
1685 /* give IBSS a bit more time */
1686 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1687 } else if (wpa_s->conf->ap_scan == 1) {
1688 /* give IBSS a bit more time */
1689 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1690 }
1691 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1692 }
1693
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001694 if (wep_keys_set &&
1695 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 /* Set static WEP keys again */
1697 wpa_set_wep_keys(wpa_s, ssid);
1698 }
1699
1700 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1701 /*
1702 * Do not allow EAP session resumption between different
1703 * network configurations.
1704 */
1705 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1706 }
1707 old_ssid = wpa_s->current_ssid;
1708 wpa_s->current_ssid = ssid;
1709 wpa_s->current_bss = bss;
1710 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1711 wpa_supplicant_initiate_eapol(wpa_s);
1712 if (old_ssid != wpa_s->current_ssid)
1713 wpas_notify_network_changed(wpa_s);
1714}
1715
1716
1717static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1718 const u8 *addr)
1719{
1720 struct wpa_ssid *old_ssid;
1721
1722 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001724 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 wpa_sm_set_config(wpa_s->wpa, NULL);
1726 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1727 if (old_ssid != wpa_s->current_ssid)
1728 wpas_notify_network_changed(wpa_s);
1729 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1730}
1731
1732
1733/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001734 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1735 * @wpa_s: Pointer to wpa_supplicant data
1736 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1737 *
1738 * This function is used to request %wpa_supplicant to deauthenticate from the
1739 * current AP.
1740 */
1741void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1742 int reason_code)
1743{
1744 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001745 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001746 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001747
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001748 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1749 " pending_bssid=" MACSTR " reason=%d state=%s",
1750 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1751 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1752
1753 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001754 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001755 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1756 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1757 wpa_s->wpa_state == WPA_ASSOCIATING))
1758 addr = wpa_s->pending_bssid;
1759 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1760 /*
1761 * When using driver-based BSS selection, we may not know the
1762 * BSSID with which we are currently trying to associate. We
1763 * need to notify the driver of this disconnection even in such
1764 * a case, so use the all zeros address here.
1765 */
1766 addr = wpa_s->bssid;
1767 zero_addr = 1;
1768 }
1769
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001770#ifdef CONFIG_TDLS
1771 wpa_tdls_teardown_peers(wpa_s->wpa);
1772#endif /* CONFIG_TDLS */
1773
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001774 if (addr) {
1775 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001776 os_memset(&event, 0, sizeof(event));
1777 event.deauth_info.reason_code = (u16) reason_code;
1778 event.deauth_info.locally_generated = 1;
1779 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001780 if (zero_addr)
1781 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001782 }
1783
1784 wpa_supplicant_clear_connection(wpa_s, addr);
1785}
1786
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001787static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1788 struct wpa_ssid *ssid)
1789{
1790 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1791 return;
1792
1793 ssid->disabled = 0;
1794 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1795 wpas_notify_network_enabled_changed(wpa_s, ssid);
1796
1797 /*
1798 * Try to reassociate since there is no current configuration and a new
1799 * network was made available.
1800 */
1801 if (!wpa_s->current_ssid)
1802 wpa_s->reassociate = 1;
1803}
1804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805
1806/**
1807 * wpa_supplicant_enable_network - Mark a configured network as enabled
1808 * @wpa_s: wpa_supplicant structure for a network interface
1809 * @ssid: wpa_ssid structure for a configured network or %NULL
1810 *
1811 * Enables the specified network or all networks if no network specified.
1812 */
1813void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1814 struct wpa_ssid *ssid)
1815{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001817 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1818 wpa_supplicant_enable_one_network(wpa_s, ssid);
1819 } else
1820 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001821
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001822 if (wpa_s->reassociate) {
1823 if (wpa_s->sched_scanning) {
1824 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1825 "new network to scan filters");
1826 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 }
1828
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001829 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1830 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831 }
1832}
1833
1834
1835/**
1836 * wpa_supplicant_disable_network - Mark a configured network as disabled
1837 * @wpa_s: wpa_supplicant structure for a network interface
1838 * @ssid: wpa_ssid structure for a configured network or %NULL
1839 *
1840 * Disables the specified network or all networks if no network specified.
1841 */
1842void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1843 struct wpa_ssid *ssid)
1844{
1845 struct wpa_ssid *other_ssid;
1846 int was_disabled;
1847
1848 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001849 if (wpa_s->sched_scanning)
1850 wpa_supplicant_cancel_sched_scan(wpa_s);
1851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1853 other_ssid = other_ssid->next) {
1854 was_disabled = other_ssid->disabled;
1855 if (was_disabled == 2)
1856 continue; /* do not change persistent P2P group
1857 * data */
1858
1859 other_ssid->disabled = 1;
1860
1861 if (was_disabled != other_ssid->disabled)
1862 wpas_notify_network_enabled_changed(
1863 wpa_s, other_ssid);
1864 }
1865 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001866 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1868 } else if (ssid->disabled != 2) {
1869 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001870 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1872
1873 was_disabled = ssid->disabled;
1874
1875 ssid->disabled = 1;
1876
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001877 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001879 if (wpa_s->sched_scanning) {
1880 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1881 "to remove network from filters");
1882 wpa_supplicant_cancel_sched_scan(wpa_s);
1883 wpa_supplicant_req_scan(wpa_s, 0, 0);
1884 }
1885 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001886 }
1887}
1888
1889
1890/**
1891 * wpa_supplicant_select_network - Attempt association with a network
1892 * @wpa_s: wpa_supplicant structure for a network interface
1893 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1894 */
1895void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1896 struct wpa_ssid *ssid)
1897{
1898
1899 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001900 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001902 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001903 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001904 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001905 disconnected = 1;
1906 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001908 if (ssid)
1909 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001911 /*
1912 * Mark all other networks disabled or mark all networks enabled if no
1913 * network specified.
1914 */
1915 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1916 other_ssid = other_ssid->next) {
1917 int was_disabled = other_ssid->disabled;
1918 if (was_disabled == 2)
1919 continue; /* do not change persistent P2P group data */
1920
1921 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001922 if (was_disabled && !other_ssid->disabled)
1923 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001924
1925 if (was_disabled != other_ssid->disabled)
1926 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
1927 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001928
1929 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
1930 /* We are already associated with the selected network */
1931 wpa_printf(MSG_DEBUG, "Already associated with the "
1932 "selected network - do nothing");
1933 return;
1934 }
1935
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001936 if (ssid)
1937 wpa_s->current_ssid = ssid;
Jouni Malinen75ecf522011-06-27 15:19:46 -07001938 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939 wpa_s->disconnected = 0;
1940 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001941
1942 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1943 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001944
1945 if (ssid)
1946 wpas_notify_network_selected(wpa_s, ssid);
1947}
1948
1949
1950/**
1951 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
1952 * @wpa_s: wpa_supplicant structure for a network interface
1953 * @ap_scan: AP scan mode
1954 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
1955 *
1956 */
1957int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
1958{
1959
1960 int old_ap_scan;
1961
1962 if (ap_scan < 0 || ap_scan > 2)
1963 return -1;
1964
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001965#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001966 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
1967 wpa_s->wpa_state >= WPA_ASSOCIATING &&
1968 wpa_s->wpa_state < WPA_COMPLETED) {
1969 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
1970 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001971 return 0;
1972 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001973#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07001974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975 old_ap_scan = wpa_s->conf->ap_scan;
1976 wpa_s->conf->ap_scan = ap_scan;
1977
1978 if (old_ap_scan != wpa_s->conf->ap_scan)
1979 wpas_notify_ap_scan_changed(wpa_s);
1980
1981 return 0;
1982}
1983
1984
1985/**
1986 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
1987 * @wpa_s: wpa_supplicant structure for a network interface
1988 * @expire_age: Expiration age in seconds
1989 * Returns: 0 if succeed or -1 if expire_age has an invalid value
1990 *
1991 */
1992int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
1993 unsigned int bss_expire_age)
1994{
1995 if (bss_expire_age < 10) {
1996 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
1997 bss_expire_age);
1998 return -1;
1999 }
2000 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2001 bss_expire_age);
2002 wpa_s->conf->bss_expiration_age = bss_expire_age;
2003
2004 return 0;
2005}
2006
2007
2008/**
2009 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2010 * @wpa_s: wpa_supplicant structure for a network interface
2011 * @expire_count: number of scans after which an unseen BSS is reclaimed
2012 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2013 *
2014 */
2015int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2016 unsigned int bss_expire_count)
2017{
2018 if (bss_expire_count < 1) {
2019 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2020 bss_expire_count);
2021 return -1;
2022 }
2023 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2024 bss_expire_count);
2025 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2026
2027 return 0;
2028}
2029
2030
2031/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002032 * wpa_supplicant_set_scan_interval - Set scan interval
2033 * @wpa_s: wpa_supplicant structure for a network interface
2034 * @scan_interval: scan interval in seconds
2035 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2036 *
2037 */
2038int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2039 int scan_interval)
2040{
2041 if (scan_interval < 0) {
2042 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2043 scan_interval);
2044 return -1;
2045 }
2046 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2047 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002048 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002049
2050 return 0;
2051}
2052
2053
2054/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055 * wpa_supplicant_set_debug_params - Set global debug params
2056 * @global: wpa_global structure
2057 * @debug_level: debug level
2058 * @debug_timestamp: determines if show timestamp in debug data
2059 * @debug_show_keys: determines if show keys in debug data
2060 * Returns: 0 if succeed or -1 if debug_level has wrong value
2061 */
2062int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2063 int debug_timestamp, int debug_show_keys)
2064{
2065
2066 int old_level, old_timestamp, old_show_keys;
2067
2068 /* check for allowed debuglevels */
2069 if (debug_level != MSG_EXCESSIVE &&
2070 debug_level != MSG_MSGDUMP &&
2071 debug_level != MSG_DEBUG &&
2072 debug_level != MSG_INFO &&
2073 debug_level != MSG_WARNING &&
2074 debug_level != MSG_ERROR)
2075 return -1;
2076
2077 old_level = wpa_debug_level;
2078 old_timestamp = wpa_debug_timestamp;
2079 old_show_keys = wpa_debug_show_keys;
2080
2081 wpa_debug_level = debug_level;
2082 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2083 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2084
2085 if (wpa_debug_level != old_level)
2086 wpas_notify_debug_level_changed(global);
2087 if (wpa_debug_timestamp != old_timestamp)
2088 wpas_notify_debug_timestamp_changed(global);
2089 if (wpa_debug_show_keys != old_show_keys)
2090 wpas_notify_debug_show_keys_changed(global);
2091
2092 return 0;
2093}
2094
2095
2096/**
2097 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2098 * @wpa_s: Pointer to wpa_supplicant data
2099 * Returns: A pointer to the current network structure or %NULL on failure
2100 */
2101struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2102{
2103 struct wpa_ssid *entry;
2104 u8 ssid[MAX_SSID_LEN];
2105 int res;
2106 size_t ssid_len;
2107 u8 bssid[ETH_ALEN];
2108 int wired;
2109
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002110 res = wpa_drv_get_ssid(wpa_s, ssid);
2111 if (res < 0) {
2112 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2113 "driver");
2114 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002116 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002118 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002119 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2120 "driver");
2121 return NULL;
2122 }
2123
2124 wired = wpa_s->conf->ap_scan == 0 &&
2125 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2126
2127 entry = wpa_s->conf->ssid;
2128 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002129 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002130 ((ssid_len == entry->ssid_len &&
2131 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2132 (!entry->bssid_set ||
2133 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2134 return entry;
2135#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002136 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2138 (entry->ssid == NULL || entry->ssid_len == 0) &&
2139 (!entry->bssid_set ||
2140 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2141 return entry;
2142#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002143
Dmitry Shmidt04949592012-07-19 12:16:46 -07002144 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002145 entry->ssid_len == 0 &&
2146 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2147 return entry;
2148
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002149 entry = entry->next;
2150 }
2151
2152 return NULL;
2153}
2154
2155
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002156static int select_driver(struct wpa_supplicant *wpa_s, int i)
2157{
2158 struct wpa_global *global = wpa_s->global;
2159
2160 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2161 global->drv_priv[i] = wpa_drivers[i]->global_init();
2162 if (global->drv_priv[i] == NULL) {
2163 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2164 "'%s'", wpa_drivers[i]->name);
2165 return -1;
2166 }
2167 }
2168
2169 wpa_s->driver = wpa_drivers[i];
2170 wpa_s->global_drv_priv = global->drv_priv[i];
2171
2172 return 0;
2173}
2174
2175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2177 const char *name)
2178{
2179 int i;
2180 size_t len;
2181 const char *pos, *driver = name;
2182
2183 if (wpa_s == NULL)
2184 return -1;
2185
2186 if (wpa_drivers[0] == NULL) {
2187 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2188 "wpa_supplicant");
2189 return -1;
2190 }
2191
2192 if (name == NULL) {
2193 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002194 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 }
2196
2197 do {
2198 pos = os_strchr(driver, ',');
2199 if (pos)
2200 len = pos - driver;
2201 else
2202 len = os_strlen(driver);
2203
2204 for (i = 0; wpa_drivers[i]; i++) {
2205 if (os_strlen(wpa_drivers[i]->name) == len &&
2206 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002207 0) {
2208 /* First driver that succeeds wins */
2209 if (select_driver(wpa_s, i) == 0)
2210 return 0;
2211 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212 }
2213
2214 driver = pos + 1;
2215 } while (pos);
2216
2217 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2218 return -1;
2219}
2220
2221
2222/**
2223 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2224 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2225 * with struct wpa_driver_ops::init()
2226 * @src_addr: Source address of the EAPOL frame
2227 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2228 * @len: Length of the EAPOL data
2229 *
2230 * This function is called for each received EAPOL frame. Most driver
2231 * interfaces rely on more generic OS mechanism for receiving frames through
2232 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2233 * take care of received EAPOL frames and deliver them to the core supplicant
2234 * code by calling this function.
2235 */
2236void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2237 const u8 *buf, size_t len)
2238{
2239 struct wpa_supplicant *wpa_s = ctx;
2240
2241 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2242 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2243
Jouni Malinena05074c2012-12-21 21:35:35 +02002244 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2245 (wpa_s->last_eapol_matches_bssid &&
2246#ifdef CONFIG_AP
2247 !wpa_s->ap_iface &&
2248#endif /* CONFIG_AP */
2249 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002250 /*
2251 * There is possible race condition between receiving the
2252 * association event and the EAPOL frame since they are coming
2253 * through different paths from the driver. In order to avoid
2254 * issues in trying to process the EAPOL frame before receiving
2255 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002256 * the association event is received. This may also be needed in
2257 * driver-based roaming case, so also use src_addr != BSSID as a
2258 * trigger if we have previously confirmed that the
2259 * Authenticator uses BSSID as the src_addr (which is not the
2260 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002261 */
2262 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002263 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2264 wpa_supplicant_state_txt(wpa_s->wpa_state),
2265 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002266 wpabuf_free(wpa_s->pending_eapol_rx);
2267 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2268 if (wpa_s->pending_eapol_rx) {
2269 os_get_time(&wpa_s->pending_eapol_rx_time);
2270 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2271 ETH_ALEN);
2272 }
2273 return;
2274 }
2275
Jouni Malinena05074c2012-12-21 21:35:35 +02002276 wpa_s->last_eapol_matches_bssid =
2277 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279#ifdef CONFIG_AP
2280 if (wpa_s->ap_iface) {
2281 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2282 return;
2283 }
2284#endif /* CONFIG_AP */
2285
2286 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2287 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2288 "no key management is configured");
2289 return;
2290 }
2291
2292 if (wpa_s->eapol_received == 0 &&
2293 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2294 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2295 wpa_s->wpa_state != WPA_COMPLETED) &&
2296 (wpa_s->current_ssid == NULL ||
2297 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2298 /* Timeout for completing IEEE 802.1X and WPA authentication */
2299 wpa_supplicant_req_auth_timeout(
2300 wpa_s,
2301 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2302 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2303 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2304 70 : 10, 0);
2305 }
2306 wpa_s->eapol_received++;
2307
2308 if (wpa_s->countermeasures) {
2309 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2310 "EAPOL packet");
2311 return;
2312 }
2313
2314#ifdef CONFIG_IBSS_RSN
2315 if (wpa_s->current_ssid &&
2316 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2317 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2318 return;
2319 }
2320#endif /* CONFIG_IBSS_RSN */
2321
2322 /* Source address of the incoming EAPOL frame could be compared to the
2323 * current BSSID. However, it is possible that a centralized
2324 * Authenticator could be using another MAC address than the BSSID of
2325 * an AP, so just allow any address to be used for now. The replies are
2326 * still sent to the current BSSID (if available), though. */
2327
2328 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2329 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2330 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2331 return;
2332 wpa_drv_poll(wpa_s);
2333 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2334 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2335 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2336 /*
2337 * Set portValid = TRUE here since we are going to skip 4-way
2338 * handshake processing which would normally set portValid. We
2339 * need this to allow the EAPOL state machines to be completed
2340 * without going through EAPOL-Key handshake.
2341 */
2342 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2343 }
2344}
2345
2346
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002347int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349 if (wpa_s->driver->send_eapol) {
2350 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2351 if (addr)
2352 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002353 } else if ((!wpa_s->p2p_mgmt ||
2354 !(wpa_s->drv_flags &
2355 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2356 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002358 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2360 wpa_drv_get_mac_addr(wpa_s),
2361 ETH_P_EAPOL,
2362 wpa_supplicant_rx_eapol, wpa_s, 0);
2363 if (wpa_s->l2 == NULL)
2364 return -1;
2365 } else {
2366 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2367 if (addr)
2368 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2369 }
2370
2371 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2372 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2373 return -1;
2374 }
2375
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002376 return 0;
2377}
2378
2379
Dmitry Shmidt04949592012-07-19 12:16:46 -07002380static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2381 const u8 *buf, size_t len)
2382{
2383 struct wpa_supplicant *wpa_s = ctx;
2384 const struct l2_ethhdr *eth;
2385
2386 if (len < sizeof(*eth))
2387 return;
2388 eth = (const struct l2_ethhdr *) buf;
2389
2390 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2391 !(eth->h_dest[0] & 0x01)) {
2392 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2393 " (bridge - not for this interface - ignore)",
2394 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2395 return;
2396 }
2397
2398 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2399 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2400 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2401 len - sizeof(*eth));
2402}
2403
2404
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002405/**
2406 * wpa_supplicant_driver_init - Initialize driver interface parameters
2407 * @wpa_s: Pointer to wpa_supplicant data
2408 * Returns: 0 on success, -1 on failure
2409 *
2410 * This function is called to initialize driver interface parameters.
2411 * wpa_drv_init() must have been called before this function to initialize the
2412 * driver interface.
2413 */
2414int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2415{
2416 static int interface_count = 0;
2417
2418 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2419 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002421 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2422 MAC2STR(wpa_s->own_addr));
2423 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425 if (wpa_s->bridge_ifname[0]) {
2426 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2427 "interface '%s'", wpa_s->bridge_ifname);
2428 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2429 wpa_s->own_addr,
2430 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002431 wpa_supplicant_rx_eapol_bridge,
2432 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 if (wpa_s->l2_br == NULL) {
2434 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2435 "connection for the bridge interface '%s'",
2436 wpa_s->bridge_ifname);
2437 return -1;
2438 }
2439 }
2440
2441 wpa_clear_keys(wpa_s, NULL);
2442
2443 /* Make sure that TKIP countermeasures are not left enabled (could
2444 * happen if wpa_supplicant is killed during countermeasures. */
2445 wpa_drv_set_countermeasures(wpa_s, 0);
2446
2447 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2448 wpa_drv_flush_pmkid(wpa_s);
2449
2450 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002451 wpa_s->prev_scan_wildcard = 0;
2452
Dmitry Shmidt04949592012-07-19 12:16:46 -07002453 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002454 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2455 100000))
2456 wpa_supplicant_req_scan(wpa_s, interface_count,
2457 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 interface_count++;
2459 } else
2460 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2461
2462 return 0;
2463}
2464
2465
2466static int wpa_supplicant_daemon(const char *pid_file)
2467{
2468 wpa_printf(MSG_DEBUG, "Daemonize..");
2469 return os_daemonize(pid_file);
2470}
2471
2472
2473static struct wpa_supplicant * wpa_supplicant_alloc(void)
2474{
2475 struct wpa_supplicant *wpa_s;
2476
2477 wpa_s = os_zalloc(sizeof(*wpa_s));
2478 if (wpa_s == NULL)
2479 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002480 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 wpa_s->scan_interval = 5;
2482 wpa_s->new_connection = 1;
2483 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002484 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485
2486 return wpa_s;
2487}
2488
2489
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002490#ifdef CONFIG_HT_OVERRIDES
2491
2492static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2493 struct ieee80211_ht_capabilities *htcaps,
2494 struct ieee80211_ht_capabilities *htcaps_mask,
2495 const char *ht_mcs)
2496{
2497 /* parse ht_mcs into hex array */
2498 int i;
2499 const char *tmp = ht_mcs;
2500 char *end = NULL;
2501
2502 /* If ht_mcs is null, do not set anything */
2503 if (!ht_mcs)
2504 return 0;
2505
2506 /* This is what we are setting in the kernel */
2507 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2508
2509 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2510
2511 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2512 errno = 0;
2513 long v = strtol(tmp, &end, 16);
2514 if (errno == 0) {
2515 wpa_msg(wpa_s, MSG_DEBUG,
2516 "htcap value[%i]: %ld end: %p tmp: %p",
2517 i, v, end, tmp);
2518 if (end == tmp)
2519 break;
2520
2521 htcaps->supported_mcs_set[i] = v;
2522 tmp = end;
2523 } else {
2524 wpa_msg(wpa_s, MSG_ERROR,
2525 "Failed to parse ht-mcs: %s, error: %s\n",
2526 ht_mcs, strerror(errno));
2527 return -1;
2528 }
2529 }
2530
2531 /*
2532 * If we were able to parse any values, then set mask for the MCS set.
2533 */
2534 if (i) {
2535 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2536 IEEE80211_HT_MCS_MASK_LEN - 1);
2537 /* skip the 3 reserved bits */
2538 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2539 0x1f;
2540 }
2541
2542 return 0;
2543}
2544
2545
2546static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2547 struct ieee80211_ht_capabilities *htcaps,
2548 struct ieee80211_ht_capabilities *htcaps_mask,
2549 int disabled)
2550{
2551 u16 msk;
2552
2553 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2554
2555 if (disabled == -1)
2556 return 0;
2557
2558 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2559 htcaps_mask->ht_capabilities_info |= msk;
2560 if (disabled)
2561 htcaps->ht_capabilities_info &= msk;
2562 else
2563 htcaps->ht_capabilities_info |= msk;
2564
2565 return 0;
2566}
2567
2568
2569static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2570 struct ieee80211_ht_capabilities *htcaps,
2571 struct ieee80211_ht_capabilities *htcaps_mask,
2572 int factor)
2573{
2574 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2575
2576 if (factor == -1)
2577 return 0;
2578
2579 if (factor < 0 || factor > 3) {
2580 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2581 "Must be 0-3 or -1", factor);
2582 return -EINVAL;
2583 }
2584
2585 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2586 htcaps->a_mpdu_params &= ~0x3;
2587 htcaps->a_mpdu_params |= factor & 0x3;
2588
2589 return 0;
2590}
2591
2592
2593static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2594 struct ieee80211_ht_capabilities *htcaps,
2595 struct ieee80211_ht_capabilities *htcaps_mask,
2596 int density)
2597{
2598 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2599
2600 if (density == -1)
2601 return 0;
2602
2603 if (density < 0 || density > 7) {
2604 wpa_msg(wpa_s, MSG_ERROR,
2605 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2606 density);
2607 return -EINVAL;
2608 }
2609
2610 htcaps_mask->a_mpdu_params |= 0x1C;
2611 htcaps->a_mpdu_params &= ~(0x1C);
2612 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2613
2614 return 0;
2615}
2616
2617
2618static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2619 struct ieee80211_ht_capabilities *htcaps,
2620 struct ieee80211_ht_capabilities *htcaps_mask,
2621 int disabled)
2622{
2623 /* Masking these out disables HT40 */
2624 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2625 HT_CAP_INFO_SHORT_GI40MHZ);
2626
2627 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2628
2629 if (disabled)
2630 htcaps->ht_capabilities_info &= ~msk;
2631 else
2632 htcaps->ht_capabilities_info |= msk;
2633
2634 htcaps_mask->ht_capabilities_info |= msk;
2635
2636 return 0;
2637}
2638
2639
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002640static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2641 struct ieee80211_ht_capabilities *htcaps,
2642 struct ieee80211_ht_capabilities *htcaps_mask,
2643 int disabled)
2644{
2645 /* Masking these out disables SGI */
2646 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2647 HT_CAP_INFO_SHORT_GI40MHZ);
2648
2649 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2650
2651 if (disabled)
2652 htcaps->ht_capabilities_info &= ~msk;
2653 else
2654 htcaps->ht_capabilities_info |= msk;
2655
2656 htcaps_mask->ht_capabilities_info |= msk;
2657
2658 return 0;
2659}
2660
2661
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002662void wpa_supplicant_apply_ht_overrides(
2663 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2664 struct wpa_driver_associate_params *params)
2665{
2666 struct ieee80211_ht_capabilities *htcaps;
2667 struct ieee80211_ht_capabilities *htcaps_mask;
2668
2669 if (!ssid)
2670 return;
2671
2672 params->disable_ht = ssid->disable_ht;
2673 if (!params->htcaps || !params->htcaps_mask)
2674 return;
2675
2676 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2677 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2678 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2679 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2680 ssid->disable_max_amsdu);
2681 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2682 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2683 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002684 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002685}
2686
2687#endif /* CONFIG_HT_OVERRIDES */
2688
2689
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002690#ifdef CONFIG_VHT_OVERRIDES
2691void wpa_supplicant_apply_vht_overrides(
2692 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2693 struct wpa_driver_associate_params *params)
2694{
2695 struct ieee80211_vht_capabilities *vhtcaps;
2696 struct ieee80211_vht_capabilities *vhtcaps_mask;
2697
2698 if (!ssid)
2699 return;
2700
2701 params->disable_vht = ssid->disable_vht;
2702
2703 vhtcaps = (void *) params->vhtcaps;
2704 vhtcaps_mask = (void *) params->vhtcaps_mask;
2705
2706 if (!vhtcaps || !vhtcaps_mask)
2707 return;
2708
2709 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2710 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2711
2712#define OVERRIDE_MCS(i) \
2713 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2714 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2715 3 << 2 * (i - 1); \
2716 vhtcaps->vht_supported_mcs_set.tx_map |= \
2717 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2718 } \
2719 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2720 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2721 3 << 2 * (i - 1); \
2722 vhtcaps->vht_supported_mcs_set.rx_map |= \
2723 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2724 }
2725
2726 OVERRIDE_MCS(1);
2727 OVERRIDE_MCS(2);
2728 OVERRIDE_MCS(3);
2729 OVERRIDE_MCS(4);
2730 OVERRIDE_MCS(5);
2731 OVERRIDE_MCS(6);
2732 OVERRIDE_MCS(7);
2733 OVERRIDE_MCS(8);
2734}
2735#endif /* CONFIG_VHT_OVERRIDES */
2736
2737
Dmitry Shmidt04949592012-07-19 12:16:46 -07002738static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2739{
2740#ifdef PCSC_FUNCS
2741 size_t len;
2742
2743 if (!wpa_s->conf->pcsc_reader)
2744 return 0;
2745
2746 wpa_s->scard = scard_init(SCARD_TRY_BOTH, wpa_s->conf->pcsc_reader);
2747 if (!wpa_s->scard)
2748 return 1;
2749
2750 if (wpa_s->conf->pcsc_pin &&
2751 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2752 scard_deinit(wpa_s->scard);
2753 wpa_s->scard = NULL;
2754 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2755 return -1;
2756 }
2757
2758 len = sizeof(wpa_s->imsi) - 1;
2759 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2760 scard_deinit(wpa_s->scard);
2761 wpa_s->scard = NULL;
2762 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2763 return -1;
2764 }
2765 wpa_s->imsi[len] = '\0';
2766
2767 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2768
2769 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2770 wpa_s->imsi, wpa_s->mnc_len);
2771
2772 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2773 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2774#endif /* PCSC_FUNCS */
2775
2776 return 0;
2777}
2778
2779
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2781{
2782 char *val, *pos;
2783
2784 ext_password_deinit(wpa_s->ext_pw);
2785 wpa_s->ext_pw = NULL;
2786 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2787
2788 if (!wpa_s->conf->ext_password_backend)
2789 return 0;
2790
2791 val = os_strdup(wpa_s->conf->ext_password_backend);
2792 if (val == NULL)
2793 return -1;
2794 pos = os_strchr(val, ':');
2795 if (pos)
2796 *pos++ = '\0';
2797
2798 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2799
2800 wpa_s->ext_pw = ext_password_init(val, pos);
2801 os_free(val);
2802 if (wpa_s->ext_pw == NULL) {
2803 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2804 return -1;
2805 }
2806 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2807
2808 return 0;
2809}
2810
2811
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
2813 struct wpa_interface *iface)
2814{
2815 const char *ifname, *driver;
2816 struct wpa_driver_capa capa;
2817
2818 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
2819 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
2820 iface->confname ? iface->confname : "N/A",
2821 iface->driver ? iface->driver : "default",
2822 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
2823 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
2824
2825 if (iface->confname) {
2826#ifdef CONFIG_BACKEND_FILE
2827 wpa_s->confname = os_rel2abs_path(iface->confname);
2828 if (wpa_s->confname == NULL) {
2829 wpa_printf(MSG_ERROR, "Failed to get absolute path "
2830 "for configuration file '%s'.",
2831 iface->confname);
2832 return -1;
2833 }
2834 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
2835 iface->confname, wpa_s->confname);
2836#else /* CONFIG_BACKEND_FILE */
2837 wpa_s->confname = os_strdup(iface->confname);
2838#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002839 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840 if (wpa_s->conf == NULL) {
2841 wpa_printf(MSG_ERROR, "Failed to read or parse "
2842 "configuration '%s'.", wpa_s->confname);
2843 return -1;
2844 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07002845 wpa_s->confanother = os_rel2abs_path(iface->confanother);
2846 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002847
2848 /*
2849 * Override ctrl_interface and driver_param if set on command
2850 * line.
2851 */
2852 if (iface->ctrl_interface) {
2853 os_free(wpa_s->conf->ctrl_interface);
2854 wpa_s->conf->ctrl_interface =
2855 os_strdup(iface->ctrl_interface);
2856 }
2857
2858 if (iface->driver_param) {
2859 os_free(wpa_s->conf->driver_param);
2860 wpa_s->conf->driver_param =
2861 os_strdup(iface->driver_param);
2862 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002863
2864 if (iface->p2p_mgmt && !iface->ctrl_interface) {
2865 os_free(wpa_s->conf->ctrl_interface);
2866 wpa_s->conf->ctrl_interface = NULL;
2867 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002868 } else
2869 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
2870 iface->driver_param);
2871
2872 if (wpa_s->conf == NULL) {
2873 wpa_printf(MSG_ERROR, "\nNo configuration found.");
2874 return -1;
2875 }
2876
2877 if (iface->ifname == NULL) {
2878 wpa_printf(MSG_ERROR, "\nInterface name is required.");
2879 return -1;
2880 }
2881 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
2882 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
2883 iface->ifname);
2884 return -1;
2885 }
2886 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
2887
2888 if (iface->bridge_ifname) {
2889 if (os_strlen(iface->bridge_ifname) >=
2890 sizeof(wpa_s->bridge_ifname)) {
2891 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
2892 "name '%s'.", iface->bridge_ifname);
2893 return -1;
2894 }
2895 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
2896 sizeof(wpa_s->bridge_ifname));
2897 }
2898
2899 /* RSNA Supplicant Key Management - INITIALIZE */
2900 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
2901 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
2902
2903 /* Initialize driver interface and register driver event handler before
2904 * L2 receive handler so that association events are processed before
2905 * EAPOL-Key packets if both become available for the same select()
2906 * call. */
2907 driver = iface->driver;
2908next_driver:
2909 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
2910 return -1;
2911
2912 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
2913 if (wpa_s->drv_priv == NULL) {
2914 const char *pos;
2915 pos = driver ? os_strchr(driver, ',') : NULL;
2916 if (pos) {
2917 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
2918 "driver interface - try next driver wrapper");
2919 driver = pos + 1;
2920 goto next_driver;
2921 }
2922 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
2923 "interface");
2924 return -1;
2925 }
2926 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
2927 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
2928 "driver_param '%s'", wpa_s->conf->driver_param);
2929 return -1;
2930 }
2931
2932 ifname = wpa_drv_get_ifname(wpa_s);
2933 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
2934 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
2935 "interface name with '%s'", ifname);
2936 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
2937 }
2938
2939 if (wpa_supplicant_init_wpa(wpa_s) < 0)
2940 return -1;
2941
2942 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
2943 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
2944 NULL);
2945 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
2946
2947 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
2948 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
2949 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
2950 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2951 "dot11RSNAConfigPMKLifetime");
2952 return -1;
2953 }
2954
2955 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
2956 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
2957 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
2958 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2959 "dot11RSNAConfigPMKReauthThreshold");
2960 return -1;
2961 }
2962
2963 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
2964 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
2965 wpa_s->conf->dot11RSNAConfigSATimeout)) {
2966 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
2967 "dot11RSNAConfigSATimeout");
2968 return -1;
2969 }
2970
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002971 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
2972 &wpa_s->hw.num_modes,
2973 &wpa_s->hw.flags);
2974
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002975 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002976 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002978 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002979 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002981 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
2982 wpa_s->sched_scan_supported = capa.sched_scan_supported;
2983 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002984 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
2985 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002986 wpa_s->extended_capa = capa.extended_capa;
2987 wpa_s->extended_capa_mask = capa.extended_capa_mask;
2988 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002989 wpa_s->num_multichan_concurrent =
2990 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002991 }
2992 if (wpa_s->max_remain_on_chan == 0)
2993 wpa_s->max_remain_on_chan = 1000;
2994
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002995 /*
2996 * Only take p2p_mgmt parameters when P2P Device is supported.
2997 * Doing it here as it determines whether l2_packet_init() will be done
2998 * during wpa_supplicant_driver_init().
2999 */
3000 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3001 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3002 else
3003 iface->p2p_mgmt = 1;
3004
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003005 if (wpa_s->num_multichan_concurrent == 0)
3006 wpa_s->num_multichan_concurrent = 1;
3007
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003008 if (wpa_supplicant_driver_init(wpa_s) < 0)
3009 return -1;
3010
3011#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003012 if ((!iface->p2p_mgmt ||
3013 !(wpa_s->drv_flags &
3014 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3015 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016 return -1;
3017#endif /* CONFIG_TDLS */
3018
3019 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3020 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3021 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3022 return -1;
3023 }
3024
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003025 if (wpas_wps_init(wpa_s))
3026 return -1;
3027
3028 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3029 return -1;
3030 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3031
3032 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3033 if (wpa_s->ctrl_iface == NULL) {
3034 wpa_printf(MSG_ERROR,
3035 "Failed to initialize control interface '%s'.\n"
3036 "You may have another wpa_supplicant process "
3037 "already running or the file was\n"
3038 "left by an unclean termination of wpa_supplicant "
3039 "in which case you will need\n"
3040 "to manually remove this file before starting "
3041 "wpa_supplicant again.\n",
3042 wpa_s->conf->ctrl_interface);
3043 return -1;
3044 }
3045
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003046 wpa_s->gas = gas_query_init(wpa_s);
3047 if (wpa_s->gas == NULL) {
3048 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3049 return -1;
3050 }
3051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003052#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003053 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3055 return -1;
3056 }
3057#endif /* CONFIG_P2P */
3058
3059 if (wpa_bss_init(wpa_s) < 0)
3060 return -1;
3061
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003062#ifdef CONFIG_EAP_PROXY
3063{
3064 size_t len;
3065 wpa_s->mnc_len = eap_proxy_get_imsi(wpa_s->imsi, &len);
3066 if (wpa_s->mnc_len > 0) {
3067 wpa_s->imsi[len] = '\0';
3068 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3069 wpa_s->imsi, wpa_s->mnc_len);
3070 } else {
3071 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3072 }
3073}
3074#endif /* CONFIG_EAP_PROXY */
3075
Dmitry Shmidt04949592012-07-19 12:16:46 -07003076 if (pcsc_reader_init(wpa_s) < 0)
3077 return -1;
3078
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003079 if (wpas_init_ext_pw(wpa_s) < 0)
3080 return -1;
3081
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082 return 0;
3083}
3084
3085
3086static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003087 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003089 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003090 if (wpa_s->drv_priv) {
3091 wpa_supplicant_deauthenticate(wpa_s,
3092 WLAN_REASON_DEAUTH_LEAVING);
3093
3094 wpa_drv_set_countermeasures(wpa_s, 0);
3095 wpa_clear_keys(wpa_s, NULL);
3096 }
3097
3098 wpa_supplicant_cleanup(wpa_s);
3099
Dmitry Shmidt04949592012-07-19 12:16:46 -07003100#ifdef CONFIG_P2P
3101 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3102 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3103 "the management interface is being removed");
3104 wpas_p2p_deinit_global(wpa_s->global);
3105 }
3106#endif /* CONFIG_P2P */
3107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108 if (wpa_s->drv_priv)
3109 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003110
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003111 if (notify)
3112 wpas_notify_iface_removed(wpa_s);
3113
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003114 if (terminate)
3115 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003116
3117 if (wpa_s->ctrl_iface) {
3118 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3119 wpa_s->ctrl_iface = NULL;
3120 }
3121
3122 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003123 wpa_config_free(wpa_s->conf);
3124 wpa_s->conf = NULL;
3125 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003126
3127 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003128}
3129
3130
3131/**
3132 * wpa_supplicant_add_iface - Add a new network interface
3133 * @global: Pointer to global data from wpa_supplicant_init()
3134 * @iface: Interface configuration options
3135 * Returns: Pointer to the created interface or %NULL on failure
3136 *
3137 * This function is used to add new network interfaces for %wpa_supplicant.
3138 * This can be called before wpa_supplicant_run() to add interfaces before the
3139 * main event loop has been started. In addition, new interfaces can be added
3140 * dynamically while %wpa_supplicant is already running. This could happen,
3141 * e.g., when a hotplug network adapter is inserted.
3142 */
3143struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3144 struct wpa_interface *iface)
3145{
3146 struct wpa_supplicant *wpa_s;
3147 struct wpa_interface t_iface;
3148 struct wpa_ssid *ssid;
3149
3150 if (global == NULL || iface == NULL)
3151 return NULL;
3152
3153 wpa_s = wpa_supplicant_alloc();
3154 if (wpa_s == NULL)
3155 return NULL;
3156
3157 wpa_s->global = global;
3158
3159 t_iface = *iface;
3160 if (global->params.override_driver) {
3161 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3162 "('%s' -> '%s')",
3163 iface->driver, global->params.override_driver);
3164 t_iface.driver = global->params.override_driver;
3165 }
3166 if (global->params.override_ctrl_interface) {
3167 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3168 "ctrl_interface ('%s' -> '%s')",
3169 iface->ctrl_interface,
3170 global->params.override_ctrl_interface);
3171 t_iface.ctrl_interface =
3172 global->params.override_ctrl_interface;
3173 }
3174 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3175 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3176 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003177 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003178 return NULL;
3179 }
3180
3181 /* Notify the control interfaces about new iface */
3182 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003183 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 return NULL;
3185 }
3186
3187 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3188 wpas_notify_network_added(wpa_s, ssid);
3189
3190 wpa_s->next = global->ifaces;
3191 global->ifaces = wpa_s;
3192
3193 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003194 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195
3196 return wpa_s;
3197}
3198
3199
3200/**
3201 * wpa_supplicant_remove_iface - Remove a network interface
3202 * @global: Pointer to global data from wpa_supplicant_init()
3203 * @wpa_s: Pointer to the network interface to be removed
3204 * Returns: 0 if interface was removed, -1 if interface was not found
3205 *
3206 * This function can be used to dynamically remove network interfaces from
3207 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3208 * addition, this function is used to remove all remaining interfaces when
3209 * %wpa_supplicant is terminated.
3210 */
3211int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003212 struct wpa_supplicant *wpa_s,
3213 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003214{
3215 struct wpa_supplicant *prev;
3216
3217 /* Remove interface from the global list of interfaces */
3218 prev = global->ifaces;
3219 if (prev == wpa_s) {
3220 global->ifaces = wpa_s->next;
3221 } else {
3222 while (prev && prev->next != wpa_s)
3223 prev = prev->next;
3224 if (prev == NULL)
3225 return -1;
3226 prev->next = wpa_s->next;
3227 }
3228
3229 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3230
3231 if (global->p2p_group_formation == wpa_s)
3232 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003233 if (global->p2p_invite_group == wpa_s)
3234 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003235 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236
3237 return 0;
3238}
3239
3240
3241/**
3242 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3243 * @wpa_s: Pointer to the network interface
3244 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3245 */
3246const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3247{
3248 const char *eapol_method;
3249
3250 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3251 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3252 return "NO-EAP";
3253 }
3254
3255 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3256 if (eapol_method == NULL)
3257 return "UNKNOWN-EAP";
3258
3259 return eapol_method;
3260}
3261
3262
3263/**
3264 * wpa_supplicant_get_iface - Get a new network interface
3265 * @global: Pointer to global data from wpa_supplicant_init()
3266 * @ifname: Interface name
3267 * Returns: Pointer to the interface or %NULL if not found
3268 */
3269struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3270 const char *ifname)
3271{
3272 struct wpa_supplicant *wpa_s;
3273
3274 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3275 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3276 return wpa_s;
3277 }
3278 return NULL;
3279}
3280
3281
3282#ifndef CONFIG_NO_WPA_MSG
3283static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3284{
3285 struct wpa_supplicant *wpa_s = ctx;
3286 if (wpa_s == NULL)
3287 return NULL;
3288 return wpa_s->ifname;
3289}
3290#endif /* CONFIG_NO_WPA_MSG */
3291
3292
3293/**
3294 * wpa_supplicant_init - Initialize %wpa_supplicant
3295 * @params: Parameters for %wpa_supplicant
3296 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3297 *
3298 * This function is used to initialize %wpa_supplicant. After successful
3299 * initialization, the returned data pointer can be used to add and remove
3300 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3301 */
3302struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3303{
3304 struct wpa_global *global;
3305 int ret, i;
3306
3307 if (params == NULL)
3308 return NULL;
3309
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003310#ifdef CONFIG_DRIVER_NDIS
3311 {
3312 void driver_ndis_init_ops(void);
3313 driver_ndis_init_ops();
3314 }
3315#endif /* CONFIG_DRIVER_NDIS */
3316
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003317#ifndef CONFIG_NO_WPA_MSG
3318 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3319#endif /* CONFIG_NO_WPA_MSG */
3320
3321 wpa_debug_open_file(params->wpa_debug_file_path);
3322 if (params->wpa_debug_syslog)
3323 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003324 if (params->wpa_debug_tracing) {
3325 ret = wpa_debug_open_linux_tracing();
3326 if (ret) {
3327 wpa_printf(MSG_ERROR,
3328 "Failed to enable trace logging");
3329 return NULL;
3330 }
3331 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332
3333 ret = eap_register_methods();
3334 if (ret) {
3335 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3336 if (ret == -2)
3337 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3338 "the same EAP type.");
3339 return NULL;
3340 }
3341
3342 global = os_zalloc(sizeof(*global));
3343 if (global == NULL)
3344 return NULL;
3345 dl_list_init(&global->p2p_srv_bonjour);
3346 dl_list_init(&global->p2p_srv_upnp);
3347 global->params.daemonize = params->daemonize;
3348 global->params.wait_for_monitor = params->wait_for_monitor;
3349 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3350 if (params->pid_file)
3351 global->params.pid_file = os_strdup(params->pid_file);
3352 if (params->ctrl_interface)
3353 global->params.ctrl_interface =
3354 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003355 if (params->ctrl_interface_group)
3356 global->params.ctrl_interface_group =
3357 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358 if (params->override_driver)
3359 global->params.override_driver =
3360 os_strdup(params->override_driver);
3361 if (params->override_ctrl_interface)
3362 global->params.override_ctrl_interface =
3363 os_strdup(params->override_ctrl_interface);
3364 wpa_debug_level = global->params.wpa_debug_level =
3365 params->wpa_debug_level;
3366 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3367 params->wpa_debug_show_keys;
3368 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3369 params->wpa_debug_timestamp;
3370
3371 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3372
3373 if (eloop_init()) {
3374 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3375 wpa_supplicant_deinit(global);
3376 return NULL;
3377 }
3378
Jouni Malinen75ecf522011-06-27 15:19:46 -07003379 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380
3381 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3382 if (global->ctrl_iface == NULL) {
3383 wpa_supplicant_deinit(global);
3384 return NULL;
3385 }
3386
3387 if (wpas_notify_supplicant_initialized(global)) {
3388 wpa_supplicant_deinit(global);
3389 return NULL;
3390 }
3391
3392 for (i = 0; wpa_drivers[i]; i++)
3393 global->drv_count++;
3394 if (global->drv_count == 0) {
3395 wpa_printf(MSG_ERROR, "No drivers enabled");
3396 wpa_supplicant_deinit(global);
3397 return NULL;
3398 }
3399 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3400 if (global->drv_priv == NULL) {
3401 wpa_supplicant_deinit(global);
3402 return NULL;
3403 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003405#ifdef CONFIG_WIFI_DISPLAY
3406 if (wifi_display_init(global) < 0) {
3407 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3408 wpa_supplicant_deinit(global);
3409 return NULL;
3410 }
3411#endif /* CONFIG_WIFI_DISPLAY */
3412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003413 return global;
3414}
3415
3416
3417/**
3418 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3419 * @global: Pointer to global data from wpa_supplicant_init()
3420 * Returns: 0 after successful event loop run, -1 on failure
3421 *
3422 * This function starts the main event loop and continues running as long as
3423 * there are any remaining events. In most cases, this function is running as
3424 * long as the %wpa_supplicant process in still in use.
3425 */
3426int wpa_supplicant_run(struct wpa_global *global)
3427{
3428 struct wpa_supplicant *wpa_s;
3429
3430 if (global->params.daemonize &&
3431 wpa_supplicant_daemon(global->params.pid_file))
3432 return -1;
3433
3434 if (global->params.wait_for_monitor) {
3435 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3436 if (wpa_s->ctrl_iface)
3437 wpa_supplicant_ctrl_iface_wait(
3438 wpa_s->ctrl_iface);
3439 }
3440
3441 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3442 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3443
3444 eloop_run();
3445
3446 return 0;
3447}
3448
3449
3450/**
3451 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3452 * @global: Pointer to global data from wpa_supplicant_init()
3453 *
3454 * This function is called to deinitialize %wpa_supplicant and to free all
3455 * allocated resources. Remaining network interfaces will also be removed.
3456 */
3457void wpa_supplicant_deinit(struct wpa_global *global)
3458{
3459 int i;
3460
3461 if (global == NULL)
3462 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003463
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003464#ifdef CONFIG_WIFI_DISPLAY
3465 wifi_display_deinit(global);
3466#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467
3468 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003469 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470
3471 if (global->ctrl_iface)
3472 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3473
3474 wpas_notify_supplicant_deinitialized(global);
3475
3476 eap_peer_unregister_methods();
3477#ifdef CONFIG_AP
3478 eap_server_unregister_methods();
3479#endif /* CONFIG_AP */
3480
3481 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3482 if (!global->drv_priv[i])
3483 continue;
3484 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3485 }
3486 os_free(global->drv_priv);
3487
3488 random_deinit();
3489
3490 eloop_destroy();
3491
3492 if (global->params.pid_file) {
3493 os_daemonize_terminate(global->params.pid_file);
3494 os_free(global->params.pid_file);
3495 }
3496 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003497 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498 os_free(global->params.override_driver);
3499 os_free(global->params.override_ctrl_interface);
3500
Dmitry Shmidt04949592012-07-19 12:16:46 -07003501 os_free(global->p2p_disallow_freq);
3502
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003503 os_free(global);
3504 wpa_debug_close_syslog();
3505 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003506 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003507}
3508
3509
3510void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3511{
3512 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3513 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3514 char country[3];
3515 country[0] = wpa_s->conf->country[0];
3516 country[1] = wpa_s->conf->country[1];
3517 country[2] = '\0';
3518 if (wpa_drv_set_country(wpa_s, country) < 0) {
3519 wpa_printf(MSG_ERROR, "Failed to set country code "
3520 "'%s'", country);
3521 }
3522 }
3523
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003524 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3525 wpas_init_ext_pw(wpa_s);
3526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527#ifdef CONFIG_WPS
3528 wpas_wps_update_config(wpa_s);
3529#endif /* CONFIG_WPS */
3530
3531#ifdef CONFIG_P2P
3532 wpas_p2p_update_config(wpa_s);
3533#endif /* CONFIG_P2P */
3534
3535 wpa_s->conf->changed_parameters = 0;
3536}
3537
3538
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539static void add_freq(int *freqs, int *num_freqs, int freq)
3540{
3541 int i;
3542
3543 for (i = 0; i < *num_freqs; i++) {
3544 if (freqs[i] == freq)
3545 return;
3546 }
3547
3548 freqs[*num_freqs] = freq;
3549 (*num_freqs)++;
3550}
3551
3552
3553static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3554{
3555 struct wpa_bss *bss, *cbss;
3556 const int max_freqs = 10;
3557 int *freqs;
3558 int num_freqs = 0;
3559
3560 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3561 if (freqs == NULL)
3562 return NULL;
3563
3564 cbss = wpa_s->current_bss;
3565
3566 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3567 if (bss == cbss)
3568 continue;
3569 if (bss->ssid_len == cbss->ssid_len &&
3570 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3571 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3572 add_freq(freqs, &num_freqs, bss->freq);
3573 if (num_freqs == max_freqs)
3574 break;
3575 }
3576 }
3577
3578 if (num_freqs == 0) {
3579 os_free(freqs);
3580 freqs = NULL;
3581 }
3582
3583 return freqs;
3584}
3585
3586
3587void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
3588{
3589 int timeout;
3590 int count;
3591 int *freqs = NULL;
3592
3593 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003594 * Remove possible authentication timeout since the connection failed.
3595 */
3596 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
3597
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003598 if (wpa_s->disconnected) {
3599 /*
3600 * There is no point in blacklisting the AP if this event is
3601 * generated based on local request to disconnect.
3602 */
3603 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
3604 "indication since interface has been put into "
3605 "disconnected state");
3606 return;
3607 }
3608
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003609 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610 * Add the failed BSSID into the blacklist and speed up next scan
3611 * attempt if there could be other APs that could accept association.
3612 * The current blacklist count indicates how many times we have tried
3613 * connecting to this AP and multiple attempts mean that other APs are
3614 * either not available or has already been tried, so that we can start
3615 * increasing the delay here to avoid constant scanning.
3616 */
3617 count = wpa_blacklist_add(wpa_s, bssid);
3618 if (count == 1 && wpa_s->current_bss) {
3619 /*
3620 * This BSS was not in the blacklist before. If there is
3621 * another BSS available for the same ESS, we should try that
3622 * next. Otherwise, we may as well try this one once more
3623 * before allowing other, likely worse, ESSes to be considered.
3624 */
3625 freqs = get_bss_freqs_in_ess(wpa_s);
3626 if (freqs) {
3627 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
3628 "has been seen; try it next");
3629 wpa_blacklist_add(wpa_s, bssid);
3630 /*
3631 * On the next scan, go through only the known channels
3632 * used in this ESS based on previous scans to speed up
3633 * common load balancing use case.
3634 */
3635 os_free(wpa_s->next_scan_freqs);
3636 wpa_s->next_scan_freqs = freqs;
3637 }
3638 }
3639
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003640 /*
3641 * Add previous failure count in case the temporary blacklist was
3642 * cleared due to no other BSSes being available.
3643 */
3644 count += wpa_s->extra_blacklist_count;
3645
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003646 if (count > 3 && wpa_s->current_ssid) {
3647 wpa_printf(MSG_DEBUG, "Continuous association failures - "
3648 "consider temporary network disabling");
3649 wpas_auth_failed(wpa_s);
3650 }
3651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 switch (count) {
3653 case 1:
3654 timeout = 100;
3655 break;
3656 case 2:
3657 timeout = 500;
3658 break;
3659 case 3:
3660 timeout = 1000;
3661 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003662 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003664 break;
3665 default:
3666 timeout = 10000;
3667 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668 }
3669
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003670 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
3671 "ms", count, timeout);
3672
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673 /*
3674 * TODO: if more than one possible AP is available in scan results,
3675 * could try the other ones before requesting a new scan.
3676 */
3677 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
3678 1000 * (timeout % 1000));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003679
Dmitry Shmidt37d4d6a2013-03-18 13:09:42 -07003680 wpas_p2p_continue_after_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003682
3683
3684int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
3685{
3686 return wpa_s->conf->ap_scan == 2 ||
3687 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
3688}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003689
Dmitry Shmidt04949592012-07-19 12:16:46 -07003690
3691#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
3692int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
3693 struct wpa_ssid *ssid,
3694 const char *field,
3695 const char *value)
3696{
3697#ifdef IEEE8021X_EAPOL
3698 struct eap_peer_config *eap = &ssid->eap;
3699
3700 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
3701 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
3702 (const u8 *) value, os_strlen(value));
3703
3704 switch (wpa_supplicant_ctrl_req_from_string(field)) {
3705 case WPA_CTRL_REQ_EAP_IDENTITY:
3706 os_free(eap->identity);
3707 eap->identity = (u8 *) os_strdup(value);
3708 eap->identity_len = os_strlen(value);
3709 eap->pending_req_identity = 0;
3710 if (ssid == wpa_s->current_ssid)
3711 wpa_s->reassociate = 1;
3712 break;
3713 case WPA_CTRL_REQ_EAP_PASSWORD:
3714 os_free(eap->password);
3715 eap->password = (u8 *) os_strdup(value);
3716 eap->password_len = os_strlen(value);
3717 eap->pending_req_password = 0;
3718 if (ssid == wpa_s->current_ssid)
3719 wpa_s->reassociate = 1;
3720 break;
3721 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
3722 os_free(eap->new_password);
3723 eap->new_password = (u8 *) os_strdup(value);
3724 eap->new_password_len = os_strlen(value);
3725 eap->pending_req_new_password = 0;
3726 if (ssid == wpa_s->current_ssid)
3727 wpa_s->reassociate = 1;
3728 break;
3729 case WPA_CTRL_REQ_EAP_PIN:
3730 os_free(eap->pin);
3731 eap->pin = os_strdup(value);
3732 eap->pending_req_pin = 0;
3733 if (ssid == wpa_s->current_ssid)
3734 wpa_s->reassociate = 1;
3735 break;
3736 case WPA_CTRL_REQ_EAP_OTP:
3737 os_free(eap->otp);
3738 eap->otp = (u8 *) os_strdup(value);
3739 eap->otp_len = os_strlen(value);
3740 os_free(eap->pending_req_otp);
3741 eap->pending_req_otp = NULL;
3742 eap->pending_req_otp_len = 0;
3743 break;
3744 case WPA_CTRL_REQ_EAP_PASSPHRASE:
3745 os_free(eap->private_key_passwd);
3746 eap->private_key_passwd = (u8 *) os_strdup(value);
3747 eap->pending_req_passphrase = 0;
3748 if (ssid == wpa_s->current_ssid)
3749 wpa_s->reassociate = 1;
3750 break;
3751 default:
3752 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
3753 return -1;
3754 }
3755
3756 return 0;
3757#else /* IEEE8021X_EAPOL */
3758 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
3759 return -1;
3760#endif /* IEEE8021X_EAPOL */
3761}
3762#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
3763
3764
3765int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
3766{
3767 int i;
3768 unsigned int drv_enc;
3769
3770 if (ssid == NULL)
3771 return 1;
3772
3773 if (ssid->disabled)
3774 return 1;
3775
3776 if (wpa_s && wpa_s->drv_capa_known)
3777 drv_enc = wpa_s->drv_enc;
3778 else
3779 drv_enc = (unsigned int) -1;
3780
3781 for (i = 0; i < NUM_WEP_KEYS; i++) {
3782 size_t len = ssid->wep_key_len[i];
3783 if (len == 0)
3784 continue;
3785 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
3786 continue;
3787 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
3788 continue;
3789 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
3790 continue;
3791 return 1; /* invalid WEP key */
3792 }
3793
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003794 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
3795 !ssid->ext_psk)
3796 return 1;
3797
Dmitry Shmidt04949592012-07-19 12:16:46 -07003798 return 0;
3799}
3800
3801
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003802int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003803{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003804 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003805 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003806 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003807 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07003808 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003809}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003810
3811
3812void wpas_auth_failed(struct wpa_supplicant *wpa_s)
3813{
3814 struct wpa_ssid *ssid = wpa_s->current_ssid;
3815 int dur;
3816 struct os_time now;
3817
3818 if (ssid == NULL) {
3819 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
3820 "SSID block");
3821 return;
3822 }
3823
3824 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
3825 return;
3826
3827 ssid->auth_failures++;
3828 if (ssid->auth_failures > 50)
3829 dur = 300;
3830 else if (ssid->auth_failures > 20)
3831 dur = 120;
3832 else if (ssid->auth_failures > 10)
3833 dur = 60;
3834 else if (ssid->auth_failures > 5)
3835 dur = 30;
3836 else if (ssid->auth_failures > 1)
3837 dur = 20;
3838 else
3839 dur = 10;
3840
3841 os_get_time(&now);
3842 if (now.sec + dur <= ssid->disabled_until.sec)
3843 return;
3844
3845 ssid->disabled_until.sec = now.sec + dur;
3846
3847 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
3848 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
3849 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
3850 ssid->auth_failures, dur);
3851}
3852
3853
3854void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
3855 struct wpa_ssid *ssid, int clear_failures)
3856{
3857 if (ssid == NULL)
3858 return;
3859
3860 if (ssid->disabled_until.sec) {
3861 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
3862 "id=%d ssid=\"%s\"",
3863 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
3864 }
3865 ssid->disabled_until.sec = 0;
3866 ssid->disabled_until.usec = 0;
3867 if (clear_failures)
3868 ssid->auth_failures = 0;
3869}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003870
3871
3872int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
3873{
3874 size_t i;
3875
3876 if (wpa_s->disallow_aps_bssid == NULL)
3877 return 0;
3878
3879 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
3880 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
3881 bssid, ETH_ALEN) == 0)
3882 return 1;
3883 }
3884
3885 return 0;
3886}
3887
3888
3889int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
3890 size_t ssid_len)
3891{
3892 size_t i;
3893
3894 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
3895 return 0;
3896
3897 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
3898 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
3899 if (ssid_len == s->ssid_len &&
3900 os_memcmp(ssid, s->ssid, ssid_len) == 0)
3901 return 1;
3902 }
3903
3904 return 0;
3905}
3906
3907
3908/**
3909 * wpas_request_connection - Request a new connection
3910 * @wpa_s: Pointer to the network interface
3911 *
3912 * This function is used to request a new connection to be found. It will mark
3913 * the interface to allow reassociation and request a new scan to find a
3914 * suitable network to connect to.
3915 */
3916void wpas_request_connection(struct wpa_supplicant *wpa_s)
3917{
3918 wpa_s->normal_scans = 0;
3919 wpa_supplicant_reinit_autoscan(wpa_s);
3920 wpa_s->extra_blacklist_count = 0;
3921 wpa_s->disconnected = 0;
3922 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08003923
3924 if (wpa_supplicant_fast_associate(wpa_s) != 1)
3925 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003926}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003927
3928
3929/**
3930 * wpas_wpa_is_in_progress - Check whether a connection is in progress
3931 * @wpa_s: Pointer to wpa_supplicant data
3932 *
3933 * This function is to check if the wpa state is in beginning of the connection
3934 * during 4-way handshake or group key handshake with WPA on any shared
3935 * interface.
3936 */
3937int wpas_wpa_is_in_progress(struct wpa_supplicant *wpa_s)
3938{
3939 const char *rn, *rn2;
3940 struct wpa_supplicant *ifs;
3941
3942 if (!wpa_s->driver->get_radio_name)
3943 return 0;
3944
3945 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3946 if (rn == NULL || rn[0] == '\0')
3947 return 0;
3948
3949 for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
3950 if (ifs == wpa_s || !ifs->driver->get_radio_name)
3951 continue;
3952
3953 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
3954 if (!rn2 || os_strcmp(rn, rn2) != 0)
3955 continue;
3956 if (ifs->wpa_state >= WPA_AUTHENTICATING &&
3957 ifs->wpa_state != WPA_COMPLETED) {
3958 wpa_dbg(wpa_s, MSG_DEBUG, "Connection is in progress "
3959 "on interface %s - defer scan", ifs->ifname);
3960 return 1;
3961 }
3962 }
3963
3964 return 0;
3965}
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003966
3967
3968/*
3969 * Find the operating frequencies of any of the virtual interfaces that
3970 * are using the same radio as the current interface.
3971 */
3972int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
3973 int *freq_array, unsigned int len)
3974{
3975 const char *rn, *rn2;
3976 struct wpa_supplicant *ifs;
3977 u8 bssid[ETH_ALEN];
3978 int freq;
3979 unsigned int idx = 0, i;
3980
3981 os_memset(freq_array, 0, sizeof(int) * len);
3982
3983 /* First add the frequency of the local interface */
3984 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
3985 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
3986 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
3987 freq_array[idx++] = wpa_s->current_ssid->frequency;
3988 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
3989 freq_array[idx++] = wpa_s->assoc_freq;
3990 }
3991
3992 /* If get_radio_name is not supported, use only the local freq */
3993 if (!wpa_s->driver->get_radio_name) {
3994 freq = wpa_drv_shared_freq(wpa_s);
3995 if (freq > 0 && idx < len &&
3996 (idx == 0 || freq_array[0] != freq))
3997 freq_array[idx++] = freq;
3998 return idx;
3999 }
4000
4001 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
4002 if (rn == NULL || rn[0] == '\0')
4003 return idx;
4004
4005 for (ifs = wpa_s->global->ifaces, idx = 0; ifs && idx < len;
4006 ifs = ifs->next) {
4007 if (wpa_s == ifs || !ifs->driver->get_radio_name)
4008 continue;
4009
4010 rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
4011 if (!rn2 || os_strcmp(rn, rn2) != 0)
4012 continue;
4013
4014 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4015 continue;
4016
4017 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4018 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4019 freq = ifs->current_ssid->frequency;
4020 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4021 freq = ifs->assoc_freq;
4022 else
4023 continue;
4024
4025 /* Hold only distinct freqs */
4026 for (i = 0; i < idx; i++)
4027 if (freq_array[i] == freq)
4028 break;
4029
4030 if (i == idx)
4031 freq_array[idx++] = freq;
4032 }
4033 return idx;
4034}