blob: e942b622588e19c4a0a68b0a199fa06e90d56da7 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2003-2014, 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 Shmidtfb79edc2014-01-10 10:45:54 -080057"Copyright (c) 2003-2014, 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107/* Configure default/group WEP keys for static WEP */
108int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
109{
110 int i, set = 0;
111
112 for (i = 0; i < NUM_WEP_KEYS; i++) {
113 if (ssid->wep_key_len[i] == 0)
114 continue;
115
116 set = 1;
117 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
118 i, i == ssid->wep_tx_keyidx, NULL, 0,
119 ssid->wep_key[i], ssid->wep_key_len[i]);
120 }
121
122 return set;
123}
124
125
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700126int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
127 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128{
129 u8 key[32];
130 size_t keylen;
131 enum wpa_alg alg;
132 u8 seq[6] = { 0 };
133
134 /* IBSS/WPA-None uses only one key (Group) for both receiving and
135 * sending unicast and multicast packets. */
136
137 if (ssid->mode != WPAS_MODE_IBSS) {
138 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
139 "IBSS/ad-hoc) for WPA-None", ssid->mode);
140 return -1;
141 }
142
143 if (!ssid->psk_set) {
144 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
145 "WPA-None");
146 return -1;
147 }
148
149 switch (wpa_s->group_cipher) {
150 case WPA_CIPHER_CCMP:
151 os_memcpy(key, ssid->psk, 16);
152 keylen = 16;
153 alg = WPA_ALG_CCMP;
154 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700155 case WPA_CIPHER_GCMP:
156 os_memcpy(key, ssid->psk, 16);
157 keylen = 16;
158 alg = WPA_ALG_GCMP;
159 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160 case WPA_CIPHER_TKIP:
161 /* WPA-None uses the same Michael MIC key for both TX and RX */
162 os_memcpy(key, ssid->psk, 16 + 8);
163 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
164 keylen = 32;
165 alg = WPA_ALG_TKIP;
166 break;
167 default:
168 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
169 "WPA-None", wpa_s->group_cipher);
170 return -1;
171 }
172
173 /* TODO: should actually remember the previously used seq#, both for TX
174 * and RX from each STA.. */
175
176 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
177}
178
179
180static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
181{
182 struct wpa_supplicant *wpa_s = eloop_ctx;
183 const u8 *bssid = wpa_s->bssid;
184 if (is_zero_ether_addr(bssid))
185 bssid = wpa_s->pending_bssid;
186 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
187 MAC2STR(bssid));
188 wpa_blacklist_add(wpa_s, bssid);
189 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800190 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700191 wpa_s->reassociate = 1;
192
193 /*
194 * If we timed out, the AP or the local radio may be busy.
195 * So, wait a second until scanning again.
196 */
197 wpa_supplicant_req_scan(wpa_s, 1, 0);
198}
199
200
201/**
202 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
203 * @wpa_s: Pointer to wpa_supplicant data
204 * @sec: Number of seconds after which to time out authentication
205 * @usec: Number of microseconds after which to time out authentication
206 *
207 * This function is used to schedule a timeout for the current authentication
208 * attempt.
209 */
210void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
211 int sec, int usec)
212{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700213 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
215 return;
216
217 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
218 "%d usec", sec, usec);
219 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
220 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
221}
222
223
224/**
225 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
226 * @wpa_s: Pointer to wpa_supplicant data
227 *
228 * This function is used to cancel authentication timeout scheduled with
229 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
230 * been completed.
231 */
232void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
233{
234 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
235 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
236 wpa_blacklist_del(wpa_s, wpa_s->bssid);
237}
238
239
240/**
241 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
242 * @wpa_s: Pointer to wpa_supplicant data
243 *
244 * This function is used to configure EAPOL state machine based on the selected
245 * authentication mode.
246 */
247void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
248{
249#ifdef IEEE8021X_EAPOL
250 struct eapol_config eapol_conf;
251 struct wpa_ssid *ssid = wpa_s->current_ssid;
252
253#ifdef CONFIG_IBSS_RSN
254 if (ssid->mode == WPAS_MODE_IBSS &&
255 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
256 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
257 /*
258 * RSN IBSS authentication is per-STA and we can disable the
259 * per-BSSID EAPOL authentication.
260 */
261 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
262 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
263 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
264 return;
265 }
266#endif /* CONFIG_IBSS_RSN */
267
268 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
269 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
270
271 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
272 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
273 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
274 else
275 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
276
277 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
278 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
279 eapol_conf.accept_802_1x_keys = 1;
280 eapol_conf.required_keys = 0;
281 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
282 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
283 }
284 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
285 eapol_conf.required_keys |=
286 EAPOL_REQUIRE_KEY_BROADCAST;
287 }
288
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700289 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700290 eapol_conf.required_keys = 0;
291 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700292 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700293 eapol_conf.workaround = ssid->eap_workaround;
294 eapol_conf.eap_disabled =
295 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
296 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
297 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700298 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
300#endif /* IEEE8021X_EAPOL */
301}
302
303
304/**
305 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
306 * @wpa_s: Pointer to wpa_supplicant data
307 * @ssid: Configuration data for the network
308 *
309 * This function is used to configure WPA state machine and related parameters
310 * to a mode where WPA is not enabled. This is called as part of the
311 * authentication configuration when the selected network does not use WPA.
312 */
313void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
314 struct wpa_ssid *ssid)
315{
316 int i;
317
318 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
319 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
320 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
321 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
322 else
323 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
324 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
325 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
326 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
327 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
328 wpa_s->group_cipher = WPA_CIPHER_NONE;
329 wpa_s->mgmt_group_cipher = 0;
330
331 for (i = 0; i < NUM_WEP_KEYS; i++) {
332 if (ssid->wep_key_len[i] > 5) {
333 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
334 wpa_s->group_cipher = WPA_CIPHER_WEP104;
335 break;
336 } else if (ssid->wep_key_len[i] > 0) {
337 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
338 wpa_s->group_cipher = WPA_CIPHER_WEP40;
339 break;
340 }
341 }
342
343 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
344 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
345 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
346 wpa_s->pairwise_cipher);
347 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
348#ifdef CONFIG_IEEE80211W
349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
350 wpa_s->mgmt_group_cipher);
351#endif /* CONFIG_IEEE80211W */
352
353 pmksa_cache_clear_current(wpa_s->wpa);
354}
355
356
Dmitry Shmidt04949592012-07-19 12:16:46 -0700357void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800358{
359 int i;
360 if (wpa_s->hw.modes == NULL)
361 return;
362
363 for (i = 0; i < wpa_s->hw.num_modes; i++) {
364 os_free(wpa_s->hw.modes[i].channels);
365 os_free(wpa_s->hw.modes[i].rates);
366 }
367
368 os_free(wpa_s->hw.modes);
369 wpa_s->hw.modes = NULL;
370}
371
372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700373static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
374{
375 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700376 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700377 scard_deinit(wpa_s->scard);
378 wpa_s->scard = NULL;
379 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
380 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
381 l2_packet_deinit(wpa_s->l2);
382 wpa_s->l2 = NULL;
383 if (wpa_s->l2_br) {
384 l2_packet_deinit(wpa_s->l2_br);
385 wpa_s->l2_br = NULL;
386 }
387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388 if (wpa_s->conf != NULL) {
389 struct wpa_ssid *ssid;
390 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
391 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392 }
393
394 os_free(wpa_s->confname);
395 wpa_s->confname = NULL;
396
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700397 os_free(wpa_s->confanother);
398 wpa_s->confanother = NULL;
399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700400 wpa_sm_set_eapol(wpa_s->wpa, NULL);
401 eapol_sm_deinit(wpa_s->eapol);
402 wpa_s->eapol = NULL;
403
404 rsn_preauth_deinit(wpa_s->wpa);
405
406#ifdef CONFIG_TDLS
407 wpa_tdls_deinit(wpa_s->wpa);
408#endif /* CONFIG_TDLS */
409
410 pmksa_candidate_free(wpa_s->wpa);
411 wpa_sm_deinit(wpa_s->wpa);
412 wpa_s->wpa = NULL;
413 wpa_blacklist_clear(wpa_s);
414
415 wpa_bss_deinit(wpa_s);
416
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700417 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 wpa_supplicant_cancel_scan(wpa_s);
419 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800420 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
421#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
422 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
423 wpa_s, NULL);
424#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425
426 wpas_wps_deinit(wpa_s);
427
428 wpabuf_free(wpa_s->pending_eapol_rx);
429 wpa_s->pending_eapol_rx = NULL;
430
431#ifdef CONFIG_IBSS_RSN
432 ibss_rsn_deinit(wpa_s->ibss_rsn);
433 wpa_s->ibss_rsn = NULL;
434#endif /* CONFIG_IBSS_RSN */
435
436 sme_deinit(wpa_s);
437
438#ifdef CONFIG_AP
439 wpa_supplicant_ap_deinit(wpa_s);
440#endif /* CONFIG_AP */
441
442#ifdef CONFIG_P2P
443 wpas_p2p_deinit(wpa_s);
444#endif /* CONFIG_P2P */
445
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800446#ifdef CONFIG_OFFCHANNEL
447 offchannel_deinit(wpa_s);
448#endif /* CONFIG_OFFCHANNEL */
449
450 wpa_supplicant_cancel_sched_scan(wpa_s);
451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452 os_free(wpa_s->next_scan_freqs);
453 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800454
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800455 os_free(wpa_s->manual_scan_freqs);
456 wpa_s->manual_scan_freqs = NULL;
457
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800458 gas_query_deinit(wpa_s->gas);
459 wpa_s->gas = NULL;
460
461 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700462
463 os_free(wpa_s->bssid_filter);
464 wpa_s->bssid_filter = NULL;
465
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800466 os_free(wpa_s->disallow_aps_bssid);
467 wpa_s->disallow_aps_bssid = NULL;
468 os_free(wpa_s->disallow_aps_ssid);
469 wpa_s->disallow_aps_ssid = NULL;
470
Dmitry Shmidt04949592012-07-19 12:16:46 -0700471 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700472#ifdef CONFIG_WNM
473 wnm_deallocate_memory(wpa_s);
474#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475
476 ext_password_deinit(wpa_s->ext_pw);
477 wpa_s->ext_pw = NULL;
478
479 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800480 wpa_s->last_gas_resp = NULL;
481 wpabuf_free(wpa_s->prev_gas_resp);
482 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700483
484 os_free(wpa_s->last_scan_res);
485 wpa_s->last_scan_res = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486}
487
488
489/**
490 * wpa_clear_keys - Clear keys configured for the driver
491 * @wpa_s: Pointer to wpa_supplicant data
492 * @addr: Previously used BSSID or %NULL if not available
493 *
494 * This function clears the encryption keys that has been previously configured
495 * for the driver.
496 */
497void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
498{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800499 int i, max;
500
501#ifdef CONFIG_IEEE80211W
502 max = 6;
503#else /* CONFIG_IEEE80211W */
504 max = 4;
505#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506
507 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800508 for (i = 0; i < max; i++) {
509 if (wpa_s->keys_cleared & BIT(i))
510 continue;
511 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
512 NULL, 0);
513 }
514 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
515 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
517 0);
518 /* MLME-SETPROTECTION.request(None) */
519 wpa_drv_mlme_setprotection(
520 wpa_s, addr,
521 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
522 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
523 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800524 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525}
526
527
528/**
529 * wpa_supplicant_state_txt - Get the connection state name as a text string
530 * @state: State (wpa_state; WPA_*)
531 * Returns: The state name as a printable text string
532 */
533const char * wpa_supplicant_state_txt(enum wpa_states state)
534{
535 switch (state) {
536 case WPA_DISCONNECTED:
537 return "DISCONNECTED";
538 case WPA_INACTIVE:
539 return "INACTIVE";
540 case WPA_INTERFACE_DISABLED:
541 return "INTERFACE_DISABLED";
542 case WPA_SCANNING:
543 return "SCANNING";
544 case WPA_AUTHENTICATING:
545 return "AUTHENTICATING";
546 case WPA_ASSOCIATING:
547 return "ASSOCIATING";
548 case WPA_ASSOCIATED:
549 return "ASSOCIATED";
550 case WPA_4WAY_HANDSHAKE:
551 return "4WAY_HANDSHAKE";
552 case WPA_GROUP_HANDSHAKE:
553 return "GROUP_HANDSHAKE";
554 case WPA_COMPLETED:
555 return "COMPLETED";
556 default:
557 return "UNKNOWN";
558 }
559}
560
561
562#ifdef CONFIG_BGSCAN
563
564static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
565{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800566 const char *name;
567
568 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
569 name = wpa_s->current_ssid->bgscan;
570 else
571 name = wpa_s->conf->bgscan;
572 if (name == NULL)
573 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800574 if (wpas_driver_bss_selection(wpa_s))
575 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
577 return;
578
579 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800580 if (wpa_s->current_ssid) {
581 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700582 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
583 "bgscan");
584 /*
585 * Live without bgscan; it is only used as a roaming
586 * optimization, so the initial connection is not
587 * affected.
588 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700589 } else {
590 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700592 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
593 0);
594 if (scan_res) {
595 bgscan_notify_scan(wpa_s, scan_res);
596 wpa_scan_results_free(scan_res);
597 }
598 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 } else
600 wpa_s->bgscan_ssid = NULL;
601}
602
603
604static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
605{
606 if (wpa_s->bgscan_ssid != NULL) {
607 bgscan_deinit(wpa_s);
608 wpa_s->bgscan_ssid = NULL;
609 }
610}
611
612#endif /* CONFIG_BGSCAN */
613
614
Dmitry Shmidt04949592012-07-19 12:16:46 -0700615static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
616{
617 if (autoscan_init(wpa_s, 0))
618 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
619}
620
621
622static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
623{
624 autoscan_deinit(wpa_s);
625}
626
627
628void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
629{
630 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
631 wpa_s->wpa_state == WPA_SCANNING) {
632 autoscan_deinit(wpa_s);
633 wpa_supplicant_start_autoscan(wpa_s);
634 }
635}
636
637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638/**
639 * wpa_supplicant_set_state - Set current connection state
640 * @wpa_s: Pointer to wpa_supplicant data
641 * @state: The new connection state
642 *
643 * This function is called whenever the connection state changes, e.g.,
644 * association is completed for WPA/WPA2 4-Way Handshake is started.
645 */
646void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
647 enum wpa_states state)
648{
649 enum wpa_states old_state = wpa_s->wpa_state;
650
651 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
652 wpa_supplicant_state_txt(wpa_s->wpa_state),
653 wpa_supplicant_state_txt(state));
654
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800655 if (state == WPA_INTERFACE_DISABLED) {
656 /* Assure normal scan when interface is restored */
657 wpa_s->normal_scans = 0;
658 }
659
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800660 if (state == WPA_COMPLETED)
661 wpas_connect_work_done(wpa_s);
662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663 if (state != WPA_SCANNING)
664 wpa_supplicant_notify_scanning(wpa_s, 0);
665
666 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700668#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700669 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800670 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800671 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672 ssid ? ssid->id : -1,
673 ssid && ssid->id_str ? ssid->id_str : "");
674#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700675 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800676 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678 wpa_drv_set_operstate(wpa_s, 1);
679#ifndef IEEE8021X_EAPOL
680 wpa_drv_set_supp_port(wpa_s, 1);
681#endif /* IEEE8021X_EAPOL */
682 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700683 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684#ifdef CONFIG_P2P
685 wpas_p2p_completed(wpa_s);
686#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700687
688 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
690 state == WPA_ASSOCIATED) {
691 wpa_s->new_connection = 1;
692 wpa_drv_set_operstate(wpa_s, 0);
693#ifndef IEEE8021X_EAPOL
694 wpa_drv_set_supp_port(wpa_s, 0);
695#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700696 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 }
698 wpa_s->wpa_state = state;
699
700#ifdef CONFIG_BGSCAN
701 if (state == WPA_COMPLETED)
702 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800703 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700704 wpa_supplicant_stop_bgscan(wpa_s);
705#endif /* CONFIG_BGSCAN */
706
Dmitry Shmidt04949592012-07-19 12:16:46 -0700707 if (state == WPA_AUTHENTICATING)
708 wpa_supplicant_stop_autoscan(wpa_s);
709
710 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
711 wpa_supplicant_start_autoscan(wpa_s);
712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700713 if (wpa_s->wpa_state != old_state) {
714 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
715
716 if (wpa_s->wpa_state == WPA_COMPLETED ||
717 old_state == WPA_COMPLETED)
718 wpas_notify_auth_changed(wpa_s);
719 }
720}
721
722
723void wpa_supplicant_terminate_proc(struct wpa_global *global)
724{
725 int pending = 0;
726#ifdef CONFIG_WPS
727 struct wpa_supplicant *wpa_s = global->ifaces;
728 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800729 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700730#ifdef CONFIG_P2P
731 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
732 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
733 wpas_p2p_disconnect(wpa_s);
734#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 if (wpas_wps_terminate_pending(wpa_s) == 1)
736 pending = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800737 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 }
739#endif /* CONFIG_WPS */
740 if (pending)
741 return;
742 eloop_terminate();
743}
744
745
746static void wpa_supplicant_terminate(int sig, void *signal_ctx)
747{
748 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749 wpa_supplicant_terminate_proc(global);
750}
751
752
753void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
754{
755 enum wpa_states old_state = wpa_s->wpa_state;
756
757 wpa_s->pairwise_cipher = 0;
758 wpa_s->group_cipher = 0;
759 wpa_s->mgmt_group_cipher = 0;
760 wpa_s->key_mgmt = 0;
761 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700762 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763
764 if (wpa_s->wpa_state != old_state)
765 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
766}
767
768
769/**
770 * wpa_supplicant_reload_configuration - Reload configuration data
771 * @wpa_s: Pointer to wpa_supplicant data
772 * Returns: 0 on success or -1 if configuration parsing failed
773 *
774 * This function can be used to request that the configuration data is reloaded
775 * (e.g., after configuration file change). This function is reloading
776 * configuration only for one interface, so this may need to be called multiple
777 * times if %wpa_supplicant is controlling multiple interfaces and all
778 * interfaces need reconfiguration.
779 */
780int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
781{
782 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700783 int reconf_ctrl;
784 int old_ap_scan;
785
786 if (wpa_s->confname == NULL)
787 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700788 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789 if (conf == NULL) {
790 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
791 "file '%s' - exiting", wpa_s->confname);
792 return -1;
793 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700794 wpa_config_read(wpa_s->confanother, conf);
795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 conf->changed_parameters = (unsigned int) -1;
797
798 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
799 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
800 os_strcmp(conf->ctrl_interface,
801 wpa_s->conf->ctrl_interface) != 0);
802
803 if (reconf_ctrl && wpa_s->ctrl_iface) {
804 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
805 wpa_s->ctrl_iface = NULL;
806 }
807
808 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800809 if (wpa_s->current_ssid) {
810 wpa_supplicant_deauthenticate(wpa_s,
811 WLAN_REASON_DEAUTH_LEAVING);
812 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813
814 /*
815 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
816 * pkcs11_engine_path, pkcs11_module_path.
817 */
818 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
819 /*
820 * Clear forced success to clear EAP state for next
821 * authentication.
822 */
823 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
824 }
825 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
826 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800827 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
829 rsn_preauth_deinit(wpa_s->wpa);
830
831 old_ap_scan = wpa_s->conf->ap_scan;
832 wpa_config_free(wpa_s->conf);
833 wpa_s->conf = conf;
834 if (old_ap_scan != wpa_s->conf->ap_scan)
835 wpas_notify_ap_scan_changed(wpa_s);
836
837 if (reconf_ctrl)
838 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
839
840 wpa_supplicant_update_config(wpa_s);
841
842 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700843 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 wpa_s->reassociate = 1;
845 wpa_supplicant_req_scan(wpa_s, 0, 0);
846 }
847 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
848 return 0;
849}
850
851
852static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
853{
854 struct wpa_global *global = signal_ctx;
855 struct wpa_supplicant *wpa_s;
856 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
857 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
858 sig);
859 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
860 wpa_supplicant_terminate_proc(global);
861 }
862 }
863}
864
865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
867 struct wpa_ssid *ssid,
868 struct wpa_ie_data *ie)
869{
870 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
871 if (ret) {
872 if (ret == -2) {
873 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
874 "from association info");
875 }
876 return -1;
877 }
878
879 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
880 "cipher suites");
881 if (!(ie->group_cipher & ssid->group_cipher)) {
882 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
883 "cipher 0x%x (mask 0x%x) - reject",
884 ie->group_cipher, ssid->group_cipher);
885 return -1;
886 }
887 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
888 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
889 "cipher 0x%x (mask 0x%x) - reject",
890 ie->pairwise_cipher, ssid->pairwise_cipher);
891 return -1;
892 }
893 if (!(ie->key_mgmt & ssid->key_mgmt)) {
894 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
895 "management 0x%x (mask 0x%x) - reject",
896 ie->key_mgmt, ssid->key_mgmt);
897 return -1;
898 }
899
900#ifdef CONFIG_IEEE80211W
901 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800902 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
903 wpa_s->conf->pmf : ssid->ieee80211w) ==
904 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
906 "that does not support management frame protection - "
907 "reject");
908 return -1;
909 }
910#endif /* CONFIG_IEEE80211W */
911
912 return 0;
913}
914
915
916/**
917 * wpa_supplicant_set_suites - Set authentication and encryption parameters
918 * @wpa_s: Pointer to wpa_supplicant data
919 * @bss: Scan results for the selected BSS, or %NULL if not available
920 * @ssid: Configuration data for the selected network
921 * @wpa_ie: Buffer for the WPA/RSN IE
922 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
923 * used buffer length in case the functions returns success.
924 * Returns: 0 on success or -1 on failure
925 *
926 * This function is used to configure authentication and encryption parameters
927 * based on the network configuration and scan result for the selected BSS (if
928 * available).
929 */
930int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
931 struct wpa_bss *bss, struct wpa_ssid *ssid,
932 u8 *wpa_ie, size_t *wpa_ie_len)
933{
934 struct wpa_ie_data ie;
935 int sel, proto;
936 const u8 *bss_wpa, *bss_rsn;
937
938 if (bss) {
939 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
940 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
941 } else
942 bss_wpa = bss_rsn = NULL;
943
944 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
945 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
946 (ie.group_cipher & ssid->group_cipher) &&
947 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
948 (ie.key_mgmt & ssid->key_mgmt)) {
949 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
950 proto = WPA_PROTO_RSN;
951 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
952 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
953 (ie.group_cipher & ssid->group_cipher) &&
954 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
955 (ie.key_mgmt & ssid->key_mgmt)) {
956 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
957 proto = WPA_PROTO_WPA;
958 } else if (bss) {
959 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
960 return -1;
961 } else {
962 if (ssid->proto & WPA_PROTO_RSN)
963 proto = WPA_PROTO_RSN;
964 else
965 proto = WPA_PROTO_WPA;
966 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
967 os_memset(&ie, 0, sizeof(ie));
968 ie.group_cipher = ssid->group_cipher;
969 ie.pairwise_cipher = ssid->pairwise_cipher;
970 ie.key_mgmt = ssid->key_mgmt;
971#ifdef CONFIG_IEEE80211W
972 ie.mgmt_group_cipher =
973 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
974 WPA_CIPHER_AES_128_CMAC : 0;
975#endif /* CONFIG_IEEE80211W */
976 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
977 "based on configuration");
978 } else
979 proto = ie.proto;
980 }
981
982 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
983 "pairwise %d key_mgmt %d proto %d",
984 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
985#ifdef CONFIG_IEEE80211W
986 if (ssid->ieee80211w) {
987 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
988 ie.mgmt_group_cipher);
989 }
990#endif /* CONFIG_IEEE80211W */
991
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800992 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
994 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
995 !!(ssid->proto & WPA_PROTO_RSN));
996
997 if (bss || !wpa_s->ap_ies_from_associnfo) {
998 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
999 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1000 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1001 bss_rsn ? 2 + bss_rsn[1] : 0))
1002 return -1;
1003 }
1004
1005 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001006 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1007 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1009 "cipher");
1010 return -1;
1011 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001012 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1013 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014
1015 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001016 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1017 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1019 "cipher");
1020 return -1;
1021 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1023 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001024
1025 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001026#ifdef CONFIG_SAE
1027 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1028 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1029#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (0) {
1031#ifdef CONFIG_IEEE80211R
1032 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1033 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1034 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1035 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1036 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1037 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1038#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001039#ifdef CONFIG_SAE
1040 } else if (sel & WPA_KEY_MGMT_SAE) {
1041 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1042 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1043 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1044 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1045 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1046#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047#ifdef CONFIG_IEEE80211W
1048 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1049 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1050 wpa_dbg(wpa_s, MSG_DEBUG,
1051 "WPA: using KEY_MGMT 802.1X with SHA256");
1052 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1053 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1054 wpa_dbg(wpa_s, MSG_DEBUG,
1055 "WPA: using KEY_MGMT PSK with SHA256");
1056#endif /* CONFIG_IEEE80211W */
1057 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1058 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1059 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1060 } else if (sel & WPA_KEY_MGMT_PSK) {
1061 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1062 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1063 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1064 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1065 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1066 } else {
1067 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1068 "authenticated key management type");
1069 return -1;
1070 }
1071
1072 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1073 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1074 wpa_s->pairwise_cipher);
1075 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1076
1077#ifdef CONFIG_IEEE80211W
1078 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001079 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1080 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1082 sel = 0;
1083 if (sel & WPA_CIPHER_AES_128_CMAC) {
1084 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1085 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1086 "AES-128-CMAC");
1087 } else {
1088 wpa_s->mgmt_group_cipher = 0;
1089 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1090 }
1091 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1092 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001093 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1094 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1095 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096#endif /* CONFIG_IEEE80211W */
1097
1098 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1099 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1100 return -1;
1101 }
1102
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001103 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001105#ifndef CONFIG_NO_PBKDF2
1106 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1107 ssid->passphrase) {
1108 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001109 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1110 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001111 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1112 psk, PMK_LEN);
1113 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1114 }
1115#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001116#ifdef CONFIG_EXT_PASSWORD
1117 if (ssid->ext_psk) {
1118 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1119 ssid->ext_psk);
1120 char pw_str[64 + 1];
1121 u8 psk[PMK_LEN];
1122
1123 if (pw == NULL) {
1124 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1125 "found from external storage");
1126 return -1;
1127 }
1128
1129 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1130 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1131 "PSK length %d in external storage",
1132 (int) wpabuf_len(pw));
1133 ext_password_free(pw);
1134 return -1;
1135 }
1136
1137 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1138 pw_str[wpabuf_len(pw)] = '\0';
1139
1140#ifndef CONFIG_NO_PBKDF2
1141 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1142 {
1143 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1144 4096, psk, PMK_LEN);
1145 os_memset(pw_str, 0, sizeof(pw_str));
1146 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1147 "external passphrase)",
1148 psk, PMK_LEN);
1149 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1150 } else
1151#endif /* CONFIG_NO_PBKDF2 */
1152 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1153 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1154 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1155 "Invalid PSK hex string");
1156 os_memset(pw_str, 0, sizeof(pw_str));
1157 ext_password_free(pw);
1158 return -1;
1159 }
1160 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1161 } else {
1162 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1163 "PSK available");
1164 os_memset(pw_str, 0, sizeof(pw_str));
1165 ext_password_free(pw);
1166 return -1;
1167 }
1168
1169 os_memset(pw_str, 0, sizeof(pw_str));
1170 ext_password_free(pw);
1171 }
1172#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001173 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1175
1176 return 0;
1177}
1178
1179
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001180static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1181{
1182 *pos = 0x00;
1183
1184 switch (idx) {
1185 case 0: /* Bits 0-7 */
1186 break;
1187 case 1: /* Bits 8-15 */
1188 break;
1189 case 2: /* Bits 16-23 */
1190#ifdef CONFIG_WNM
1191 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1192 *pos |= 0x08; /* Bit 19 - BSS Transition */
1193#endif /* CONFIG_WNM */
1194 break;
1195 case 3: /* Bits 24-31 */
1196#ifdef CONFIG_WNM
1197 *pos |= 0x02; /* Bit 25 - SSID List */
1198#endif /* CONFIG_WNM */
1199#ifdef CONFIG_INTERWORKING
1200 if (wpa_s->conf->interworking)
1201 *pos |= 0x80; /* Bit 31 - Interworking */
1202#endif /* CONFIG_INTERWORKING */
1203 break;
1204 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001205#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001206 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1207 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001208#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001209 break;
1210 case 5: /* Bits 40-47 */
1211 break;
1212 case 6: /* Bits 48-55 */
1213 break;
1214 }
1215}
1216
1217
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001218int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1219{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001220 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001221 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001222
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001223 if (len < wpa_s->extended_capa_len)
1224 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001225
1226 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001227 *pos++ = len;
1228 for (i = 0; i < len; i++, pos++) {
1229 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001230
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001231 if (i < wpa_s->extended_capa_len) {
1232 *pos &= ~wpa_s->extended_capa_mask[i];
1233 *pos |= wpa_s->extended_capa[i];
1234 }
1235 }
1236
1237 while (len > 0 && buf[1 + len] == 0) {
1238 len--;
1239 buf[1] = len;
1240 }
1241 if (len == 0)
1242 return 0;
1243
1244 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001245}
1246
1247
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001248static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1249 struct wpa_bss *test_bss)
1250{
1251 struct wpa_bss *bss;
1252
1253 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1254 if (bss == test_bss)
1255 return 1;
1256 }
1257
1258 return 0;
1259}
1260
1261
1262static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1263 struct wpa_ssid *test_ssid)
1264{
1265 struct wpa_ssid *ssid;
1266
1267 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1268 if (ssid == test_ssid)
1269 return 1;
1270 }
1271
1272 return 0;
1273}
1274
1275
1276int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1277 struct wpa_ssid *test_ssid)
1278{
1279 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1280 return 0;
1281
1282 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1283}
1284
1285
1286void wpas_connect_work_free(struct wpa_connect_work *cwork)
1287{
1288 if (cwork == NULL)
1289 return;
1290 os_free(cwork);
1291}
1292
1293
1294void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1295{
1296 struct wpa_connect_work *cwork;
1297 struct wpa_radio_work *work = wpa_s->connect_work;
1298
1299 if (!work)
1300 return;
1301
1302 wpa_s->connect_work = NULL;
1303 cwork = work->ctx;
1304 work->ctx = NULL;
1305 wpas_connect_work_free(cwork);
1306 radio_work_done(work);
1307}
1308
1309
1310static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1311
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312/**
1313 * wpa_supplicant_associate - Request association
1314 * @wpa_s: Pointer to wpa_supplicant data
1315 * @bss: Scan results for the selected BSS, or %NULL if not available
1316 * @ssid: Configuration data for the selected network
1317 *
1318 * This function is used to request %wpa_supplicant to associate with a BSS.
1319 */
1320void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1321 struct wpa_bss *bss, struct wpa_ssid *ssid)
1322{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001323 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001324
1325#ifdef CONFIG_IBSS_RSN
1326 ibss_rsn_deinit(wpa_s->ibss_rsn);
1327 wpa_s->ibss_rsn = NULL;
1328#endif /* CONFIG_IBSS_RSN */
1329
1330 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1331 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1332#ifdef CONFIG_AP
1333 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1334 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1335 "mode");
1336 return;
1337 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001338 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1339 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001340 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1341 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001342 return;
1343 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344 wpa_s->current_bss = bss;
1345#else /* CONFIG_AP */
1346 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1347 "the build");
1348#endif /* CONFIG_AP */
1349 return;
1350 }
1351
1352#ifdef CONFIG_TDLS
1353 if (bss)
1354 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1355 bss->ie_len);
1356#endif /* CONFIG_TDLS */
1357
1358 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1359 ssid->mode == IEEE80211_MODE_INFRA) {
1360 sme_authenticate(wpa_s, bss, ssid);
1361 return;
1362 }
1363
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001364 if (wpa_s->connect_work) {
1365 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1366 return;
1367 }
1368
1369 cwork = os_zalloc(sizeof(*cwork));
1370 if (cwork == NULL)
1371 return;
1372
1373 cwork->bss = bss;
1374 cwork->ssid = ssid;
1375
1376 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1377 wpas_start_assoc_cb, cwork) < 0) {
1378 os_free(cwork);
1379 }
1380}
1381
1382
1383static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1384{
1385 struct wpa_connect_work *cwork = work->ctx;
1386 struct wpa_bss *bss = cwork->bss;
1387 struct wpa_ssid *ssid = cwork->ssid;
1388 struct wpa_supplicant *wpa_s = work->wpa_s;
1389 u8 wpa_ie[200];
1390 size_t wpa_ie_len;
1391 int use_crypt, ret, i, bssid_changed;
1392 int algs = WPA_AUTH_ALG_OPEN;
1393 unsigned int cipher_pairwise, cipher_group;
1394 struct wpa_driver_associate_params params;
1395 int wep_keys_set = 0;
1396 int assoc_failed = 0;
1397 struct wpa_ssid *old_ssid;
1398#ifdef CONFIG_HT_OVERRIDES
1399 struct ieee80211_ht_capabilities htcaps;
1400 struct ieee80211_ht_capabilities htcaps_mask;
1401#endif /* CONFIG_HT_OVERRIDES */
1402
1403 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001404 if (work->started) {
1405 wpa_s->connect_work = NULL;
1406
1407 /* cancel possible auth. timeout */
1408 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1409 NULL);
1410 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001411 wpas_connect_work_free(cwork);
1412 return;
1413 }
1414
1415 wpa_s->connect_work = work;
1416
1417 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1418 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1419 wpas_connect_work_done(wpa_s);
1420 return;
1421 }
1422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001423 os_memset(&params, 0, sizeof(params));
1424 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001425 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001426 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427#ifdef CONFIG_IEEE80211R
1428 const u8 *ie, *md = NULL;
1429#endif /* CONFIG_IEEE80211R */
1430 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1431 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1432 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1433 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1434 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1435 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1436 if (bssid_changed)
1437 wpas_notify_bssid_changed(wpa_s);
1438#ifdef CONFIG_IEEE80211R
1439 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1440 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1441 md = ie + 2;
1442 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1443 if (md) {
1444 /* Prepare for the next transition */
1445 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1446 }
1447#endif /* CONFIG_IEEE80211R */
1448#ifdef CONFIG_WPS
1449 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1450 wpa_s->conf->ap_scan == 2 &&
1451 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1452 /* Use ap_scan==1 style network selection to find the network
1453 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001454 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455 wpa_s->reassociate = 1;
1456 wpa_supplicant_req_scan(wpa_s, 0, 0);
1457 return;
1458#endif /* CONFIG_WPS */
1459 } else {
1460 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1461 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1462 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1463 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001464 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001465 wpa_supplicant_cancel_scan(wpa_s);
1466
1467 /* Starting new association, so clear the possibly used WPA IE from the
1468 * previous association. */
1469 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1470
1471#ifdef IEEE8021X_EAPOL
1472 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1473 if (ssid->leap) {
1474 if (ssid->non_leap == 0)
1475 algs = WPA_AUTH_ALG_LEAP;
1476 else
1477 algs |= WPA_AUTH_ALG_LEAP;
1478 }
1479 }
1480#endif /* IEEE8021X_EAPOL */
1481 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1482 if (ssid->auth_alg) {
1483 algs = ssid->auth_alg;
1484 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1485 "0x%x", algs);
1486 }
1487
1488 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1489 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001490 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001492 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1493 wpa_s->conf->okc :
1494 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001495 (ssid->proto & WPA_PROTO_RSN);
1496 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001497 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1499 wpa_ie_len = sizeof(wpa_ie);
1500 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1501 wpa_ie, &wpa_ie_len)) {
1502 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1503 "key management and encryption suites");
1504 return;
1505 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001506 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1507 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1508 /*
1509 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1510 * use non-WPA since the scan results did not indicate that the
1511 * AP is using WPA or WPA2.
1512 */
1513 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1514 wpa_ie_len = 0;
1515 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001516 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001517 wpa_ie_len = sizeof(wpa_ie);
1518 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1519 wpa_ie, &wpa_ie_len)) {
1520 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1521 "key management and encryption suites (no "
1522 "scan results)");
1523 return;
1524 }
1525#ifdef CONFIG_WPS
1526 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1527 struct wpabuf *wps_ie;
1528 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1529 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1530 wpa_ie_len = wpabuf_len(wps_ie);
1531 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1532 } else
1533 wpa_ie_len = 0;
1534 wpabuf_free(wps_ie);
1535 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1536 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1537 params.wps = WPS_MODE_PRIVACY;
1538 else
1539 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001540 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541#endif /* CONFIG_WPS */
1542 } else {
1543 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1544 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001545 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 }
1547
1548#ifdef CONFIG_P2P
1549 if (wpa_s->global->p2p) {
1550 u8 *pos;
1551 size_t len;
1552 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001553 pos = wpa_ie + wpa_ie_len;
1554 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001555 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1556 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557 if (res >= 0)
1558 wpa_ie_len += res;
1559 }
1560
1561 wpa_s->cross_connect_disallowed = 0;
1562 if (bss) {
1563 struct wpabuf *p2p;
1564 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1565 if (p2p) {
1566 wpa_s->cross_connect_disallowed =
1567 p2p_get_cross_connect_disallowed(p2p);
1568 wpabuf_free(p2p);
1569 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1570 "connection",
1571 wpa_s->cross_connect_disallowed ?
1572 "disallows" : "allows");
1573 }
1574 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001575
1576 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001577#endif /* CONFIG_P2P */
1578
Dmitry Shmidt04949592012-07-19 12:16:46 -07001579#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001580 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001581 struct wpabuf *hs20;
1582 hs20 = wpabuf_alloc(20);
1583 if (hs20) {
1584 wpas_hs20_add_indication(hs20);
1585 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1586 wpabuf_len(hs20));
1587 wpa_ie_len += wpabuf_len(hs20);
1588 wpabuf_free(hs20);
1589 }
1590 }
1591#endif /* CONFIG_HS20 */
1592
Dmitry Shmidt56052862013-10-04 10:23:25 -07001593 /*
1594 * Workaround: Add Extended Capabilities element only if the AP
1595 * included this element in Beacon/Probe Response frames. Some older
1596 * APs seem to have interoperability issues if this element is
1597 * included, so while the standard may require us to include the
1598 * element in all cases, it is justifiable to skip it to avoid
1599 * interoperability issues.
1600 */
1601 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1602 u8 ext_capab[10];
1603 int ext_capab_len;
1604 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1605 if (ext_capab_len > 0) {
1606 u8 *pos = wpa_ie;
1607 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1608 pos += 2 + pos[1];
1609 os_memmove(pos + ext_capab_len, pos,
1610 wpa_ie_len - (pos - wpa_ie));
1611 wpa_ie_len += ext_capab_len;
1612 os_memcpy(pos, ext_capab, ext_capab_len);
1613 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001614 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001615
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001616 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1617 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001618 cipher_pairwise = wpa_s->pairwise_cipher;
1619 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1621 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1622 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1623 use_crypt = 0;
1624 if (wpa_set_wep_keys(wpa_s, ssid)) {
1625 use_crypt = 1;
1626 wep_keys_set = 1;
1627 }
1628 }
1629 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1630 use_crypt = 0;
1631
1632#ifdef IEEE8021X_EAPOL
1633 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1634 if ((ssid->eapol_flags &
1635 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1636 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1637 !wep_keys_set) {
1638 use_crypt = 0;
1639 } else {
1640 /* Assume that dynamic WEP-104 keys will be used and
1641 * set cipher suites in order for drivers to expect
1642 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001643 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001644 }
1645 }
1646#endif /* IEEE8021X_EAPOL */
1647
1648 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1649 /* Set the key before (and later after) association */
1650 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1651 }
1652
1653 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1654 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655 params.ssid = bss->ssid;
1656 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001657 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1658 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1659 MACSTR " freq=%u MHz based on scan results "
1660 "(bssid_set=%d)",
1661 MAC2STR(bss->bssid), bss->freq,
1662 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001663 params.bssid = bss->bssid;
1664 params.freq = bss->freq;
1665 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001666 params.bssid_hint = bss->bssid;
1667 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001668 } else {
1669 params.ssid = ssid->ssid;
1670 params.ssid_len = ssid->ssid_len;
1671 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001672
1673 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1674 wpa_s->conf->ap_scan == 2) {
1675 params.bssid = ssid->bssid;
1676 params.fixed_bssid = 1;
1677 }
1678
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1680 params.freq == 0)
1681 params.freq = ssid->frequency; /* Initial channel for IBSS */
1682 params.wpa_ie = wpa_ie;
1683 params.wpa_ie_len = wpa_ie_len;
1684 params.pairwise_suite = cipher_pairwise;
1685 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001686 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001687 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001688 params.auth_alg = algs;
1689 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001690 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001691 for (i = 0; i < NUM_WEP_KEYS; i++) {
1692 if (ssid->wep_key_len[i])
1693 params.wep_key[i] = ssid->wep_key[i];
1694 params.wep_key_len[i] = ssid->wep_key_len[i];
1695 }
1696 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1697
1698 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001699 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1700 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001701 params.passphrase = ssid->passphrase;
1702 if (ssid->psk_set)
1703 params.psk = ssid->psk;
1704 }
1705
1706 params.drop_unencrypted = use_crypt;
1707
1708#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001709 params.mgmt_frame_protection =
1710 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1711 wpa_s->conf->pmf : ssid->ieee80211w;
1712 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001713 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1714 struct wpa_ie_data ie;
1715 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1716 ie.capabilities &
1717 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1718 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1719 "MFP: require MFP");
1720 params.mgmt_frame_protection =
1721 MGMT_FRAME_PROTECTION_REQUIRED;
1722 }
1723 }
1724#endif /* CONFIG_IEEE80211W */
1725
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001726 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727
1728 if (wpa_s->parent->set_sta_uapsd)
1729 params.uapsd = wpa_s->parent->sta_uapsd;
1730 else
1731 params.uapsd = -1;
1732
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001733#ifdef CONFIG_HT_OVERRIDES
1734 os_memset(&htcaps, 0, sizeof(htcaps));
1735 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1736 params.htcaps = (u8 *) &htcaps;
1737 params.htcaps_mask = (u8 *) &htcaps_mask;
1738 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1739#endif /* CONFIG_HT_OVERRIDES */
1740
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001741#ifdef CONFIG_P2P
1742 /*
1743 * If multi-channel concurrency is not supported, check for any
1744 * frequency conflict. In case of any frequency conflict, remove the
1745 * least prioritized connection.
1746 */
1747 if (wpa_s->num_multichan_concurrent < 2) {
1748 int freq = wpa_drv_shared_freq(wpa_s);
1749 if (freq > 0 && freq != params.freq) {
1750 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1751 freq, params.freq);
1752 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1753 params.freq,
1754 ssid) < 0)
1755 return;
1756 }
1757 }
1758#endif /* CONFIG_P2P */
1759
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001760 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761 if (ret < 0) {
1762 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1763 "failed");
1764 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1765 /*
1766 * The driver is known to mean what is saying, so we
1767 * can stop right here; the association will not
1768 * succeed.
1769 */
1770 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001771 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1773 return;
1774 }
1775 /* try to continue anyway; new association will be tried again
1776 * after timeout */
1777 assoc_failed = 1;
1778 }
1779
1780 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1781 /* Set the key after the association just in case association
1782 * cleared the previously configured key. */
1783 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1784 /* No need to timeout authentication since there is no key
1785 * management. */
1786 wpa_supplicant_cancel_auth_timeout(wpa_s);
1787 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1788#ifdef CONFIG_IBSS_RSN
1789 } else if (ssid->mode == WPAS_MODE_IBSS &&
1790 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1791 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1792 /*
1793 * RSN IBSS authentication is per-STA and we can disable the
1794 * per-BSSID authentication.
1795 */
1796 wpa_supplicant_cancel_auth_timeout(wpa_s);
1797#endif /* CONFIG_IBSS_RSN */
1798 } else {
1799 /* Timeout for IEEE 802.11 authentication and association */
1800 int timeout = 60;
1801
1802 if (assoc_failed) {
1803 /* give IBSS a bit more time */
1804 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1805 } else if (wpa_s->conf->ap_scan == 1) {
1806 /* give IBSS a bit more time */
1807 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1808 }
1809 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1810 }
1811
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001812 if (wep_keys_set &&
1813 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001814 /* Set static WEP keys again */
1815 wpa_set_wep_keys(wpa_s, ssid);
1816 }
1817
1818 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1819 /*
1820 * Do not allow EAP session resumption between different
1821 * network configurations.
1822 */
1823 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1824 }
1825 old_ssid = wpa_s->current_ssid;
1826 wpa_s->current_ssid = ssid;
1827 wpa_s->current_bss = bss;
1828 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1829 wpa_supplicant_initiate_eapol(wpa_s);
1830 if (old_ssid != wpa_s->current_ssid)
1831 wpas_notify_network_changed(wpa_s);
1832}
1833
1834
1835static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1836 const u8 *addr)
1837{
1838 struct wpa_ssid *old_ssid;
1839
1840 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001842 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843 wpa_sm_set_config(wpa_s->wpa, NULL);
1844 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1845 if (old_ssid != wpa_s->current_ssid)
1846 wpas_notify_network_changed(wpa_s);
1847 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1848}
1849
1850
1851/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1853 * @wpa_s: Pointer to wpa_supplicant data
1854 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1855 *
1856 * This function is used to request %wpa_supplicant to deauthenticate from the
1857 * current AP.
1858 */
1859void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1860 int reason_code)
1861{
1862 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001863 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001864 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001866 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1867 " pending_bssid=" MACSTR " reason=%d state=%s",
1868 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1869 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1870
1871 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001872 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001873 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1874 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1875 wpa_s->wpa_state == WPA_ASSOCIATING))
1876 addr = wpa_s->pending_bssid;
1877 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1878 /*
1879 * When using driver-based BSS selection, we may not know the
1880 * BSSID with which we are currently trying to associate. We
1881 * need to notify the driver of this disconnection even in such
1882 * a case, so use the all zeros address here.
1883 */
1884 addr = wpa_s->bssid;
1885 zero_addr = 1;
1886 }
1887
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001888#ifdef CONFIG_TDLS
1889 wpa_tdls_teardown_peers(wpa_s->wpa);
1890#endif /* CONFIG_TDLS */
1891
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001892 if (addr) {
1893 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001894 os_memset(&event, 0, sizeof(event));
1895 event.deauth_info.reason_code = (u16) reason_code;
1896 event.deauth_info.locally_generated = 1;
1897 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001898 if (zero_addr)
1899 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900 }
1901
1902 wpa_supplicant_clear_connection(wpa_s, addr);
1903}
1904
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001905static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1906 struct wpa_ssid *ssid)
1907{
1908 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1909 return;
1910
1911 ssid->disabled = 0;
1912 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1913 wpas_notify_network_enabled_changed(wpa_s, ssid);
1914
1915 /*
1916 * Try to reassociate since there is no current configuration and a new
1917 * network was made available.
1918 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001919 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001920 wpa_s->reassociate = 1;
1921}
1922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923
1924/**
1925 * wpa_supplicant_enable_network - Mark a configured network as enabled
1926 * @wpa_s: wpa_supplicant structure for a network interface
1927 * @ssid: wpa_ssid structure for a configured network or %NULL
1928 *
1929 * Enables the specified network or all networks if no network specified.
1930 */
1931void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1932 struct wpa_ssid *ssid)
1933{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001935 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1936 wpa_supplicant_enable_one_network(wpa_s, ssid);
1937 } else
1938 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001939
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001940 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001941 if (wpa_s->sched_scanning) {
1942 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1943 "new network to scan filters");
1944 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945 }
1946
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001947 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1948 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001949 }
1950}
1951
1952
1953/**
1954 * wpa_supplicant_disable_network - Mark a configured network as disabled
1955 * @wpa_s: wpa_supplicant structure for a network interface
1956 * @ssid: wpa_ssid structure for a configured network or %NULL
1957 *
1958 * Disables the specified network or all networks if no network specified.
1959 */
1960void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1961 struct wpa_ssid *ssid)
1962{
1963 struct wpa_ssid *other_ssid;
1964 int was_disabled;
1965
1966 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001967 if (wpa_s->sched_scanning)
1968 wpa_supplicant_cancel_sched_scan(wpa_s);
1969
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001970 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1971 other_ssid = other_ssid->next) {
1972 was_disabled = other_ssid->disabled;
1973 if (was_disabled == 2)
1974 continue; /* do not change persistent P2P group
1975 * data */
1976
1977 other_ssid->disabled = 1;
1978
1979 if (was_disabled != other_ssid->disabled)
1980 wpas_notify_network_enabled_changed(
1981 wpa_s, other_ssid);
1982 }
1983 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001984 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1986 } else if (ssid->disabled != 2) {
1987 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001988 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1990
1991 was_disabled = ssid->disabled;
1992
1993 ssid->disabled = 1;
1994
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001995 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001997 if (wpa_s->sched_scanning) {
1998 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1999 "to remove network from filters");
2000 wpa_supplicant_cancel_sched_scan(wpa_s);
2001 wpa_supplicant_req_scan(wpa_s, 0, 0);
2002 }
2003 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002004 }
2005}
2006
2007
2008/**
2009 * wpa_supplicant_select_network - Attempt association with a network
2010 * @wpa_s: wpa_supplicant structure for a network interface
2011 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2012 */
2013void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2014 struct wpa_ssid *ssid)
2015{
2016
2017 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002018 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002019
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002020 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002021 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002023 disconnected = 1;
2024 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002026 if (ssid)
2027 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029 /*
2030 * Mark all other networks disabled or mark all networks enabled if no
2031 * network specified.
2032 */
2033 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2034 other_ssid = other_ssid->next) {
2035 int was_disabled = other_ssid->disabled;
2036 if (was_disabled == 2)
2037 continue; /* do not change persistent P2P group data */
2038
2039 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002040 if (was_disabled && !other_ssid->disabled)
2041 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042
2043 if (was_disabled != other_ssid->disabled)
2044 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2045 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002046
2047 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2048 /* We are already associated with the selected network */
2049 wpa_printf(MSG_DEBUG, "Already associated with the "
2050 "selected network - do nothing");
2051 return;
2052 }
2053
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002054 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002055 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002056 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2057 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002058 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 wpa_s->disconnected = 0;
2060 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002061
2062 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2063 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064
2065 if (ssid)
2066 wpas_notify_network_selected(wpa_s, ssid);
2067}
2068
2069
2070/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002071 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2072 * @wpa_s: wpa_supplicant structure for a network interface
2073 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2074 * @pkcs11_module_path: PKCS #11 module path or NULL
2075 * Returns: 0 on success; -1 on failure
2076 *
2077 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2078 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2079 * module path fails the paths will be reset to the default value (NULL).
2080 */
2081int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2082 const char *pkcs11_engine_path,
2083 const char *pkcs11_module_path)
2084{
2085 char *pkcs11_engine_path_copy = NULL;
2086 char *pkcs11_module_path_copy = NULL;
2087
2088 if (pkcs11_engine_path != NULL) {
2089 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2090 if (pkcs11_engine_path_copy == NULL)
2091 return -1;
2092 }
2093 if (pkcs11_module_path != NULL) {
2094 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002095 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002096 os_free(pkcs11_engine_path_copy);
2097 return -1;
2098 }
2099 }
2100
2101 os_free(wpa_s->conf->pkcs11_engine_path);
2102 os_free(wpa_s->conf->pkcs11_module_path);
2103 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2104 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2105
2106 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2107 eapol_sm_deinit(wpa_s->eapol);
2108 wpa_s->eapol = NULL;
2109 if (wpa_supplicant_init_eapol(wpa_s)) {
2110 /* Error -> Reset paths to the default value (NULL) once. */
2111 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2112 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2113 NULL);
2114
2115 return -1;
2116 }
2117 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2118
2119 return 0;
2120}
2121
2122
2123/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002124 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2125 * @wpa_s: wpa_supplicant structure for a network interface
2126 * @ap_scan: AP scan mode
2127 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2128 *
2129 */
2130int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2131{
2132
2133 int old_ap_scan;
2134
2135 if (ap_scan < 0 || ap_scan > 2)
2136 return -1;
2137
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002138#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002139 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2140 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2141 wpa_s->wpa_state < WPA_COMPLETED) {
2142 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2143 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002144 return 0;
2145 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002146#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002147
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 old_ap_scan = wpa_s->conf->ap_scan;
2149 wpa_s->conf->ap_scan = ap_scan;
2150
2151 if (old_ap_scan != wpa_s->conf->ap_scan)
2152 wpas_notify_ap_scan_changed(wpa_s);
2153
2154 return 0;
2155}
2156
2157
2158/**
2159 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2160 * @wpa_s: wpa_supplicant structure for a network interface
2161 * @expire_age: Expiration age in seconds
2162 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2163 *
2164 */
2165int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2166 unsigned int bss_expire_age)
2167{
2168 if (bss_expire_age < 10) {
2169 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2170 bss_expire_age);
2171 return -1;
2172 }
2173 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2174 bss_expire_age);
2175 wpa_s->conf->bss_expiration_age = bss_expire_age;
2176
2177 return 0;
2178}
2179
2180
2181/**
2182 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2183 * @wpa_s: wpa_supplicant structure for a network interface
2184 * @expire_count: number of scans after which an unseen BSS is reclaimed
2185 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2186 *
2187 */
2188int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2189 unsigned int bss_expire_count)
2190{
2191 if (bss_expire_count < 1) {
2192 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2193 bss_expire_count);
2194 return -1;
2195 }
2196 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2197 bss_expire_count);
2198 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2199
2200 return 0;
2201}
2202
2203
2204/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002205 * wpa_supplicant_set_scan_interval - Set scan interval
2206 * @wpa_s: wpa_supplicant structure for a network interface
2207 * @scan_interval: scan interval in seconds
2208 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2209 *
2210 */
2211int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2212 int scan_interval)
2213{
2214 if (scan_interval < 0) {
2215 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2216 scan_interval);
2217 return -1;
2218 }
2219 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2220 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002221 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002222
2223 return 0;
2224}
2225
2226
2227/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228 * wpa_supplicant_set_debug_params - Set global debug params
2229 * @global: wpa_global structure
2230 * @debug_level: debug level
2231 * @debug_timestamp: determines if show timestamp in debug data
2232 * @debug_show_keys: determines if show keys in debug data
2233 * Returns: 0 if succeed or -1 if debug_level has wrong value
2234 */
2235int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2236 int debug_timestamp, int debug_show_keys)
2237{
2238
2239 int old_level, old_timestamp, old_show_keys;
2240
2241 /* check for allowed debuglevels */
2242 if (debug_level != MSG_EXCESSIVE &&
2243 debug_level != MSG_MSGDUMP &&
2244 debug_level != MSG_DEBUG &&
2245 debug_level != MSG_INFO &&
2246 debug_level != MSG_WARNING &&
2247 debug_level != MSG_ERROR)
2248 return -1;
2249
2250 old_level = wpa_debug_level;
2251 old_timestamp = wpa_debug_timestamp;
2252 old_show_keys = wpa_debug_show_keys;
2253
2254 wpa_debug_level = debug_level;
2255 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2256 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2257
2258 if (wpa_debug_level != old_level)
2259 wpas_notify_debug_level_changed(global);
2260 if (wpa_debug_timestamp != old_timestamp)
2261 wpas_notify_debug_timestamp_changed(global);
2262 if (wpa_debug_show_keys != old_show_keys)
2263 wpas_notify_debug_show_keys_changed(global);
2264
2265 return 0;
2266}
2267
2268
2269/**
2270 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2271 * @wpa_s: Pointer to wpa_supplicant data
2272 * Returns: A pointer to the current network structure or %NULL on failure
2273 */
2274struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2275{
2276 struct wpa_ssid *entry;
2277 u8 ssid[MAX_SSID_LEN];
2278 int res;
2279 size_t ssid_len;
2280 u8 bssid[ETH_ALEN];
2281 int wired;
2282
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002283 res = wpa_drv_get_ssid(wpa_s, ssid);
2284 if (res < 0) {
2285 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2286 "driver");
2287 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002289 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002290
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002291 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2293 "driver");
2294 return NULL;
2295 }
2296
2297 wired = wpa_s->conf->ap_scan == 0 &&
2298 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2299
2300 entry = wpa_s->conf->ssid;
2301 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002302 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303 ((ssid_len == entry->ssid_len &&
2304 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2305 (!entry->bssid_set ||
2306 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2307 return entry;
2308#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002309 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2311 (entry->ssid == NULL || entry->ssid_len == 0) &&
2312 (!entry->bssid_set ||
2313 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2314 return entry;
2315#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002316
Dmitry Shmidt04949592012-07-19 12:16:46 -07002317 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002318 entry->ssid_len == 0 &&
2319 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2320 return entry;
2321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322 entry = entry->next;
2323 }
2324
2325 return NULL;
2326}
2327
2328
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002329static int select_driver(struct wpa_supplicant *wpa_s, int i)
2330{
2331 struct wpa_global *global = wpa_s->global;
2332
2333 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2334 global->drv_priv[i] = wpa_drivers[i]->global_init();
2335 if (global->drv_priv[i] == NULL) {
2336 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2337 "'%s'", wpa_drivers[i]->name);
2338 return -1;
2339 }
2340 }
2341
2342 wpa_s->driver = wpa_drivers[i];
2343 wpa_s->global_drv_priv = global->drv_priv[i];
2344
2345 return 0;
2346}
2347
2348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2350 const char *name)
2351{
2352 int i;
2353 size_t len;
2354 const char *pos, *driver = name;
2355
2356 if (wpa_s == NULL)
2357 return -1;
2358
2359 if (wpa_drivers[0] == NULL) {
2360 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2361 "wpa_supplicant");
2362 return -1;
2363 }
2364
2365 if (name == NULL) {
2366 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002367 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 }
2369
2370 do {
2371 pos = os_strchr(driver, ',');
2372 if (pos)
2373 len = pos - driver;
2374 else
2375 len = os_strlen(driver);
2376
2377 for (i = 0; wpa_drivers[i]; i++) {
2378 if (os_strlen(wpa_drivers[i]->name) == len &&
2379 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002380 0) {
2381 /* First driver that succeeds wins */
2382 if (select_driver(wpa_s, i) == 0)
2383 return 0;
2384 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 }
2386
2387 driver = pos + 1;
2388 } while (pos);
2389
2390 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2391 return -1;
2392}
2393
2394
2395/**
2396 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2397 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2398 * with struct wpa_driver_ops::init()
2399 * @src_addr: Source address of the EAPOL frame
2400 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2401 * @len: Length of the EAPOL data
2402 *
2403 * This function is called for each received EAPOL frame. Most driver
2404 * interfaces rely on more generic OS mechanism for receiving frames through
2405 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2406 * take care of received EAPOL frames and deliver them to the core supplicant
2407 * code by calling this function.
2408 */
2409void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2410 const u8 *buf, size_t len)
2411{
2412 struct wpa_supplicant *wpa_s = ctx;
2413
2414 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2415 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2416
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002417#ifdef CONFIG_PEERKEY
2418 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2419 wpa_s->current_ssid->peerkey &&
2420 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2421 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2422 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2423 return;
2424 }
2425#endif /* CONFIG_PEERKEY */
2426
Jouni Malinena05074c2012-12-21 21:35:35 +02002427 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2428 (wpa_s->last_eapol_matches_bssid &&
2429#ifdef CONFIG_AP
2430 !wpa_s->ap_iface &&
2431#endif /* CONFIG_AP */
2432 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 /*
2434 * There is possible race condition between receiving the
2435 * association event and the EAPOL frame since they are coming
2436 * through different paths from the driver. In order to avoid
2437 * issues in trying to process the EAPOL frame before receiving
2438 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002439 * the association event is received. This may also be needed in
2440 * driver-based roaming case, so also use src_addr != BSSID as a
2441 * trigger if we have previously confirmed that the
2442 * Authenticator uses BSSID as the src_addr (which is not the
2443 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 */
2445 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002446 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2447 wpa_supplicant_state_txt(wpa_s->wpa_state),
2448 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 wpabuf_free(wpa_s->pending_eapol_rx);
2450 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2451 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002452 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2454 ETH_ALEN);
2455 }
2456 return;
2457 }
2458
Jouni Malinena05074c2012-12-21 21:35:35 +02002459 wpa_s->last_eapol_matches_bssid =
2460 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462#ifdef CONFIG_AP
2463 if (wpa_s->ap_iface) {
2464 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2465 return;
2466 }
2467#endif /* CONFIG_AP */
2468
2469 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2470 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2471 "no key management is configured");
2472 return;
2473 }
2474
2475 if (wpa_s->eapol_received == 0 &&
2476 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2477 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2478 wpa_s->wpa_state != WPA_COMPLETED) &&
2479 (wpa_s->current_ssid == NULL ||
2480 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2481 /* Timeout for completing IEEE 802.1X and WPA authentication */
2482 wpa_supplicant_req_auth_timeout(
2483 wpa_s,
2484 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2485 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2486 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2487 70 : 10, 0);
2488 }
2489 wpa_s->eapol_received++;
2490
2491 if (wpa_s->countermeasures) {
2492 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2493 "EAPOL packet");
2494 return;
2495 }
2496
2497#ifdef CONFIG_IBSS_RSN
2498 if (wpa_s->current_ssid &&
2499 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2500 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2501 return;
2502 }
2503#endif /* CONFIG_IBSS_RSN */
2504
2505 /* Source address of the incoming EAPOL frame could be compared to the
2506 * current BSSID. However, it is possible that a centralized
2507 * Authenticator could be using another MAC address than the BSSID of
2508 * an AP, so just allow any address to be used for now. The replies are
2509 * still sent to the current BSSID (if available), though. */
2510
2511 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2512 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2513 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2514 return;
2515 wpa_drv_poll(wpa_s);
2516 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2517 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2518 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2519 /*
2520 * Set portValid = TRUE here since we are going to skip 4-way
2521 * handshake processing which would normally set portValid. We
2522 * need this to allow the EAPOL state machines to be completed
2523 * without going through EAPOL-Key handshake.
2524 */
2525 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2526 }
2527}
2528
2529
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002530int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 if (wpa_s->driver->send_eapol) {
2533 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2534 if (addr)
2535 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002536 } else if ((!wpa_s->p2p_mgmt ||
2537 !(wpa_s->drv_flags &
2538 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2539 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002541 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2543 wpa_drv_get_mac_addr(wpa_s),
2544 ETH_P_EAPOL,
2545 wpa_supplicant_rx_eapol, wpa_s, 0);
2546 if (wpa_s->l2 == NULL)
2547 return -1;
2548 } else {
2549 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2550 if (addr)
2551 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2552 }
2553
2554 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2555 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2556 return -1;
2557 }
2558
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002559 return 0;
2560}
2561
2562
Dmitry Shmidt04949592012-07-19 12:16:46 -07002563static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2564 const u8 *buf, size_t len)
2565{
2566 struct wpa_supplicant *wpa_s = ctx;
2567 const struct l2_ethhdr *eth;
2568
2569 if (len < sizeof(*eth))
2570 return;
2571 eth = (const struct l2_ethhdr *) buf;
2572
2573 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2574 !(eth->h_dest[0] & 0x01)) {
2575 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2576 " (bridge - not for this interface - ignore)",
2577 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2578 return;
2579 }
2580
2581 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2582 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2583 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2584 len - sizeof(*eth));
2585}
2586
2587
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002588/**
2589 * wpa_supplicant_driver_init - Initialize driver interface parameters
2590 * @wpa_s: Pointer to wpa_supplicant data
2591 * Returns: 0 on success, -1 on failure
2592 *
2593 * This function is called to initialize driver interface parameters.
2594 * wpa_drv_init() must have been called before this function to initialize the
2595 * driver interface.
2596 */
2597int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2598{
2599 static int interface_count = 0;
2600
2601 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2602 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002604 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2605 MAC2STR(wpa_s->own_addr));
2606 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2607
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 if (wpa_s->bridge_ifname[0]) {
2609 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2610 "interface '%s'", wpa_s->bridge_ifname);
2611 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2612 wpa_s->own_addr,
2613 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002614 wpa_supplicant_rx_eapol_bridge,
2615 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 if (wpa_s->l2_br == NULL) {
2617 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2618 "connection for the bridge interface '%s'",
2619 wpa_s->bridge_ifname);
2620 return -1;
2621 }
2622 }
2623
2624 wpa_clear_keys(wpa_s, NULL);
2625
2626 /* Make sure that TKIP countermeasures are not left enabled (could
2627 * happen if wpa_supplicant is killed during countermeasures. */
2628 wpa_drv_set_countermeasures(wpa_s, 0);
2629
2630 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2631 wpa_drv_flush_pmkid(wpa_s);
2632
2633 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002634 wpa_s->prev_scan_wildcard = 0;
2635
Dmitry Shmidt04949592012-07-19 12:16:46 -07002636 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002637 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2638 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2639 interface_count = 0;
2640 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002641 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2642 100000))
2643 wpa_supplicant_req_scan(wpa_s, interface_count,
2644 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 interface_count++;
2646 } else
2647 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2648
2649 return 0;
2650}
2651
2652
2653static int wpa_supplicant_daemon(const char *pid_file)
2654{
2655 wpa_printf(MSG_DEBUG, "Daemonize..");
2656 return os_daemonize(pid_file);
2657}
2658
2659
2660static struct wpa_supplicant * wpa_supplicant_alloc(void)
2661{
2662 struct wpa_supplicant *wpa_s;
2663
2664 wpa_s = os_zalloc(sizeof(*wpa_s));
2665 if (wpa_s == NULL)
2666 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002667 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 wpa_s->scan_interval = 5;
2669 wpa_s->new_connection = 1;
2670 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002671 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672
2673 return wpa_s;
2674}
2675
2676
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002677#ifdef CONFIG_HT_OVERRIDES
2678
2679static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2680 struct ieee80211_ht_capabilities *htcaps,
2681 struct ieee80211_ht_capabilities *htcaps_mask,
2682 const char *ht_mcs)
2683{
2684 /* parse ht_mcs into hex array */
2685 int i;
2686 const char *tmp = ht_mcs;
2687 char *end = NULL;
2688
2689 /* If ht_mcs is null, do not set anything */
2690 if (!ht_mcs)
2691 return 0;
2692
2693 /* This is what we are setting in the kernel */
2694 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2695
2696 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2697
2698 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2699 errno = 0;
2700 long v = strtol(tmp, &end, 16);
2701 if (errno == 0) {
2702 wpa_msg(wpa_s, MSG_DEBUG,
2703 "htcap value[%i]: %ld end: %p tmp: %p",
2704 i, v, end, tmp);
2705 if (end == tmp)
2706 break;
2707
2708 htcaps->supported_mcs_set[i] = v;
2709 tmp = end;
2710 } else {
2711 wpa_msg(wpa_s, MSG_ERROR,
2712 "Failed to parse ht-mcs: %s, error: %s\n",
2713 ht_mcs, strerror(errno));
2714 return -1;
2715 }
2716 }
2717
2718 /*
2719 * If we were able to parse any values, then set mask for the MCS set.
2720 */
2721 if (i) {
2722 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2723 IEEE80211_HT_MCS_MASK_LEN - 1);
2724 /* skip the 3 reserved bits */
2725 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2726 0x1f;
2727 }
2728
2729 return 0;
2730}
2731
2732
2733static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2734 struct ieee80211_ht_capabilities *htcaps,
2735 struct ieee80211_ht_capabilities *htcaps_mask,
2736 int disabled)
2737{
2738 u16 msk;
2739
2740 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2741
2742 if (disabled == -1)
2743 return 0;
2744
2745 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2746 htcaps_mask->ht_capabilities_info |= msk;
2747 if (disabled)
2748 htcaps->ht_capabilities_info &= msk;
2749 else
2750 htcaps->ht_capabilities_info |= msk;
2751
2752 return 0;
2753}
2754
2755
2756static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2757 struct ieee80211_ht_capabilities *htcaps,
2758 struct ieee80211_ht_capabilities *htcaps_mask,
2759 int factor)
2760{
2761 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2762
2763 if (factor == -1)
2764 return 0;
2765
2766 if (factor < 0 || factor > 3) {
2767 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2768 "Must be 0-3 or -1", factor);
2769 return -EINVAL;
2770 }
2771
2772 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2773 htcaps->a_mpdu_params &= ~0x3;
2774 htcaps->a_mpdu_params |= factor & 0x3;
2775
2776 return 0;
2777}
2778
2779
2780static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2781 struct ieee80211_ht_capabilities *htcaps,
2782 struct ieee80211_ht_capabilities *htcaps_mask,
2783 int density)
2784{
2785 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2786
2787 if (density == -1)
2788 return 0;
2789
2790 if (density < 0 || density > 7) {
2791 wpa_msg(wpa_s, MSG_ERROR,
2792 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2793 density);
2794 return -EINVAL;
2795 }
2796
2797 htcaps_mask->a_mpdu_params |= 0x1C;
2798 htcaps->a_mpdu_params &= ~(0x1C);
2799 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2800
2801 return 0;
2802}
2803
2804
2805static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2806 struct ieee80211_ht_capabilities *htcaps,
2807 struct ieee80211_ht_capabilities *htcaps_mask,
2808 int disabled)
2809{
2810 /* Masking these out disables HT40 */
2811 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2812 HT_CAP_INFO_SHORT_GI40MHZ);
2813
2814 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2815
2816 if (disabled)
2817 htcaps->ht_capabilities_info &= ~msk;
2818 else
2819 htcaps->ht_capabilities_info |= msk;
2820
2821 htcaps_mask->ht_capabilities_info |= msk;
2822
2823 return 0;
2824}
2825
2826
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002827static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2828 struct ieee80211_ht_capabilities *htcaps,
2829 struct ieee80211_ht_capabilities *htcaps_mask,
2830 int disabled)
2831{
2832 /* Masking these out disables SGI */
2833 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2834 HT_CAP_INFO_SHORT_GI40MHZ);
2835
2836 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2837
2838 if (disabled)
2839 htcaps->ht_capabilities_info &= ~msk;
2840 else
2841 htcaps->ht_capabilities_info |= msk;
2842
2843 htcaps_mask->ht_capabilities_info |= msk;
2844
2845 return 0;
2846}
2847
2848
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002849void wpa_supplicant_apply_ht_overrides(
2850 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2851 struct wpa_driver_associate_params *params)
2852{
2853 struct ieee80211_ht_capabilities *htcaps;
2854 struct ieee80211_ht_capabilities *htcaps_mask;
2855
2856 if (!ssid)
2857 return;
2858
2859 params->disable_ht = ssid->disable_ht;
2860 if (!params->htcaps || !params->htcaps_mask)
2861 return;
2862
2863 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2864 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2865 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2866 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2867 ssid->disable_max_amsdu);
2868 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2869 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2870 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002871 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002872}
2873
2874#endif /* CONFIG_HT_OVERRIDES */
2875
2876
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002877#ifdef CONFIG_VHT_OVERRIDES
2878void wpa_supplicant_apply_vht_overrides(
2879 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2880 struct wpa_driver_associate_params *params)
2881{
2882 struct ieee80211_vht_capabilities *vhtcaps;
2883 struct ieee80211_vht_capabilities *vhtcaps_mask;
2884
2885 if (!ssid)
2886 return;
2887
2888 params->disable_vht = ssid->disable_vht;
2889
2890 vhtcaps = (void *) params->vhtcaps;
2891 vhtcaps_mask = (void *) params->vhtcaps_mask;
2892
2893 if (!vhtcaps || !vhtcaps_mask)
2894 return;
2895
2896 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2897 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2898
2899#define OVERRIDE_MCS(i) \
2900 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2901 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2902 3 << 2 * (i - 1); \
2903 vhtcaps->vht_supported_mcs_set.tx_map |= \
2904 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2905 } \
2906 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2907 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2908 3 << 2 * (i - 1); \
2909 vhtcaps->vht_supported_mcs_set.rx_map |= \
2910 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2911 }
2912
2913 OVERRIDE_MCS(1);
2914 OVERRIDE_MCS(2);
2915 OVERRIDE_MCS(3);
2916 OVERRIDE_MCS(4);
2917 OVERRIDE_MCS(5);
2918 OVERRIDE_MCS(6);
2919 OVERRIDE_MCS(7);
2920 OVERRIDE_MCS(8);
2921}
2922#endif /* CONFIG_VHT_OVERRIDES */
2923
2924
Dmitry Shmidt04949592012-07-19 12:16:46 -07002925static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2926{
2927#ifdef PCSC_FUNCS
2928 size_t len;
2929
2930 if (!wpa_s->conf->pcsc_reader)
2931 return 0;
2932
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002933 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002934 if (!wpa_s->scard)
2935 return 1;
2936
2937 if (wpa_s->conf->pcsc_pin &&
2938 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2939 scard_deinit(wpa_s->scard);
2940 wpa_s->scard = NULL;
2941 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2942 return -1;
2943 }
2944
2945 len = sizeof(wpa_s->imsi) - 1;
2946 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2947 scard_deinit(wpa_s->scard);
2948 wpa_s->scard = NULL;
2949 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2950 return -1;
2951 }
2952 wpa_s->imsi[len] = '\0';
2953
2954 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2955
2956 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2957 wpa_s->imsi, wpa_s->mnc_len);
2958
2959 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2960 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2961#endif /* PCSC_FUNCS */
2962
2963 return 0;
2964}
2965
2966
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002967int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2968{
2969 char *val, *pos;
2970
2971 ext_password_deinit(wpa_s->ext_pw);
2972 wpa_s->ext_pw = NULL;
2973 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2974
2975 if (!wpa_s->conf->ext_password_backend)
2976 return 0;
2977
2978 val = os_strdup(wpa_s->conf->ext_password_backend);
2979 if (val == NULL)
2980 return -1;
2981 pos = os_strchr(val, ':');
2982 if (pos)
2983 *pos++ = '\0';
2984
2985 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2986
2987 wpa_s->ext_pw = ext_password_init(val, pos);
2988 os_free(val);
2989 if (wpa_s->ext_pw == NULL) {
2990 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2991 return -1;
2992 }
2993 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2994
2995 return 0;
2996}
2997
2998
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002999static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3000 const char *rn)
3001{
3002 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3003 struct wpa_radio *radio;
3004
3005 while (rn && iface) {
3006 radio = iface->radio;
3007 if (radio && os_strcmp(rn, radio->name) == 0) {
3008 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3009 wpa_s->ifname, rn);
3010 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3011 return radio;
3012 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003013
3014 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003015 }
3016
3017 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3018 wpa_s->ifname, rn ? rn : "N/A");
3019 radio = os_zalloc(sizeof(*radio));
3020 if (radio == NULL)
3021 return NULL;
3022
3023 if (rn)
3024 os_strlcpy(radio->name, rn, sizeof(radio->name));
3025 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003026 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003027 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3028
3029 return radio;
3030}
3031
3032
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003033static void radio_work_free(struct wpa_radio_work *work)
3034{
3035 if (work->wpa_s->scan_work == work) {
3036 /* This should not really happen. */
3037 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3038 work->type, work, work->started);
3039 work->wpa_s->scan_work = NULL;
3040 }
3041
3042#ifdef CONFIG_P2P
3043 if (work->wpa_s->p2p_scan_work == work) {
3044 /* This should not really happen. */
3045 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3046 work->type, work, work->started);
3047 work->wpa_s->p2p_scan_work = NULL;
3048 }
3049#endif /* CONFIG_P2P */
3050
3051 dl_list_del(&work->list);
3052 os_free(work);
3053}
3054
3055
3056static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3057{
3058 struct wpa_radio *radio = eloop_ctx;
3059 struct wpa_radio_work *work;
3060 struct os_reltime now, diff;
3061 struct wpa_supplicant *wpa_s;
3062
3063 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3064 if (work == NULL)
3065 return;
3066
3067 if (work->started)
3068 return; /* already started and still in progress */
3069
3070 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3071 radio_list);
3072 if (wpa_s && wpa_s->external_scan_running) {
3073 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3074 return;
3075 }
3076
3077 os_get_reltime(&now);
3078 os_reltime_sub(&now, &work->time, &diff);
3079 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3080 work->type, work, diff.sec, diff.usec);
3081 work->started = 1;
3082 work->time = now;
3083 work->cb(work, 0);
3084}
3085
3086
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003087/*
3088 * This function removes both started and pending radio works running on
3089 * the provided interface's radio.
3090 * Prior to the removal of the radio work, its callback (cb) is called with
3091 * deinit set to be 1. Each work's callback is responsible for clearing its
3092 * internal data and restoring to a correct state.
3093 * @wpa_s: wpa_supplicant data
3094 * @type: type of works to be removed
3095 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3096 * this interface's works.
3097 */
3098void radio_remove_works(struct wpa_supplicant *wpa_s,
3099 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003100{
3101 struct wpa_radio_work *work, *tmp;
3102 struct wpa_radio *radio = wpa_s->radio;
3103
3104 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3105 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003106 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003107 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003108
3109 /* skip other ifaces' works */
3110 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003111 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003112
3113 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3114 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003115 work->cb(work, 1);
3116 radio_work_free(work);
3117 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003118
3119 /* in case we removed the started work */
3120 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003121}
3122
3123
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003124static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3125{
3126 struct wpa_radio *radio = wpa_s->radio;
3127
3128 if (!radio)
3129 return;
3130
3131 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3132 wpa_s->ifname, radio->name);
3133 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003134 if (!dl_list_empty(&radio->ifaces)) {
3135 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003136 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003137 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003138
3139 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003140 radio_remove_works(wpa_s, NULL, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003141 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3142 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003143 os_free(radio);
3144}
3145
3146
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003147void radio_work_check_next(struct wpa_supplicant *wpa_s)
3148{
3149 struct wpa_radio *radio = wpa_s->radio;
3150
3151 if (dl_list_empty(&radio->work))
3152 return;
3153 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3154 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3155}
3156
3157
3158/**
3159 * radio_add_work - Add a radio work item
3160 * @wpa_s: Pointer to wpa_supplicant data
3161 * @freq: Frequency of the offchannel operation in MHz or 0
3162 * @type: Unique identifier for each type of work
3163 * @next: Force as the next work to be executed
3164 * @cb: Callback function for indicating when radio is available
3165 * @ctx: Context pointer for the work (work->ctx in cb())
3166 * Returns: 0 on success, -1 on failure
3167 *
3168 * This function is used to request time for an operation that requires
3169 * exclusive radio control. Once the radio is available, the registered callback
3170 * function will be called. radio_work_done() must be called once the exclusive
3171 * radio operation has been completed, so that the radio is freed for other
3172 * operations. The special case of deinit=1 is used to free the context data
3173 * during interface removal. That does not allow the callback function to start
3174 * the radio operation, i.e., it must free any resources allocated for the radio
3175 * work and return.
3176 *
3177 * The @freq parameter can be used to indicate a single channel on which the
3178 * offchannel operation will occur. This may allow multiple radio work
3179 * operations to be performed in parallel if they apply for the same channel.
3180 * Setting this to 0 indicates that the work item may use multiple channels or
3181 * requires exclusive control of the radio.
3182 */
3183int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3184 const char *type, int next,
3185 void (*cb)(struct wpa_radio_work *work, int deinit),
3186 void *ctx)
3187{
3188 struct wpa_radio_work *work;
3189 int was_empty;
3190
3191 work = os_zalloc(sizeof(*work));
3192 if (work == NULL)
3193 return -1;
3194 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3195 os_get_reltime(&work->time);
3196 work->freq = freq;
3197 work->type = type;
3198 work->wpa_s = wpa_s;
3199 work->cb = cb;
3200 work->ctx = ctx;
3201
3202 was_empty = dl_list_empty(&wpa_s->radio->work);
3203 if (next)
3204 dl_list_add(&wpa_s->radio->work, &work->list);
3205 else
3206 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3207 if (was_empty) {
3208 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3209 radio_work_check_next(wpa_s);
3210 }
3211
3212 return 0;
3213}
3214
3215
3216/**
3217 * radio_work_done - Indicate that a radio work item has been completed
3218 * @work: Completed work
3219 *
3220 * This function is called once the callback function registered with
3221 * radio_add_work() has completed its work.
3222 */
3223void radio_work_done(struct wpa_radio_work *work)
3224{
3225 struct wpa_supplicant *wpa_s = work->wpa_s;
3226 struct os_reltime now, diff;
3227 unsigned int started = work->started;
3228
3229 os_get_reltime(&now);
3230 os_reltime_sub(&now, &work->time, &diff);
3231 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3232 work->type, work, started ? "done" : "canceled",
3233 diff.sec, diff.usec);
3234 radio_work_free(work);
3235 if (started)
3236 radio_work_check_next(wpa_s);
3237}
3238
3239
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003240static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3241 struct wpa_interface *iface)
3242{
3243 const char *ifname, *driver, *rn;
3244
3245 driver = iface->driver;
3246next_driver:
3247 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3248 return -1;
3249
3250 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3251 if (wpa_s->drv_priv == NULL) {
3252 const char *pos;
3253 pos = driver ? os_strchr(driver, ',') : NULL;
3254 if (pos) {
3255 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3256 "driver interface - try next driver wrapper");
3257 driver = pos + 1;
3258 goto next_driver;
3259 }
3260 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3261 "interface");
3262 return -1;
3263 }
3264 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3265 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3266 "driver_param '%s'", wpa_s->conf->driver_param);
3267 return -1;
3268 }
3269
3270 ifname = wpa_drv_get_ifname(wpa_s);
3271 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3272 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3273 "interface name with '%s'", ifname);
3274 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3275 }
3276
3277 if (wpa_s->driver->get_radio_name)
3278 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3279 else
3280 rn = NULL;
3281 if (rn && rn[0] == '\0')
3282 rn = NULL;
3283
3284 wpa_s->radio = radio_add_interface(wpa_s, rn);
3285 if (wpa_s->radio == NULL)
3286 return -1;
3287
3288 return 0;
3289}
3290
3291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3293 struct wpa_interface *iface)
3294{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003295 struct wpa_driver_capa capa;
3296
3297 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3298 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3299 iface->confname ? iface->confname : "N/A",
3300 iface->driver ? iface->driver : "default",
3301 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3302 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3303
3304 if (iface->confname) {
3305#ifdef CONFIG_BACKEND_FILE
3306 wpa_s->confname = os_rel2abs_path(iface->confname);
3307 if (wpa_s->confname == NULL) {
3308 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3309 "for configuration file '%s'.",
3310 iface->confname);
3311 return -1;
3312 }
3313 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3314 iface->confname, wpa_s->confname);
3315#else /* CONFIG_BACKEND_FILE */
3316 wpa_s->confname = os_strdup(iface->confname);
3317#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003318 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 if (wpa_s->conf == NULL) {
3320 wpa_printf(MSG_ERROR, "Failed to read or parse "
3321 "configuration '%s'.", wpa_s->confname);
3322 return -1;
3323 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003324 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3325 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326
3327 /*
3328 * Override ctrl_interface and driver_param if set on command
3329 * line.
3330 */
3331 if (iface->ctrl_interface) {
3332 os_free(wpa_s->conf->ctrl_interface);
3333 wpa_s->conf->ctrl_interface =
3334 os_strdup(iface->ctrl_interface);
3335 }
3336
3337 if (iface->driver_param) {
3338 os_free(wpa_s->conf->driver_param);
3339 wpa_s->conf->driver_param =
3340 os_strdup(iface->driver_param);
3341 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003342
3343 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3344 os_free(wpa_s->conf->ctrl_interface);
3345 wpa_s->conf->ctrl_interface = NULL;
3346 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003347 } else
3348 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3349 iface->driver_param);
3350
3351 if (wpa_s->conf == NULL) {
3352 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3353 return -1;
3354 }
3355
3356 if (iface->ifname == NULL) {
3357 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3358 return -1;
3359 }
3360 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3361 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3362 iface->ifname);
3363 return -1;
3364 }
3365 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3366
3367 if (iface->bridge_ifname) {
3368 if (os_strlen(iface->bridge_ifname) >=
3369 sizeof(wpa_s->bridge_ifname)) {
3370 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3371 "name '%s'.", iface->bridge_ifname);
3372 return -1;
3373 }
3374 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3375 sizeof(wpa_s->bridge_ifname));
3376 }
3377
3378 /* RSNA Supplicant Key Management - INITIALIZE */
3379 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3380 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3381
3382 /* Initialize driver interface and register driver event handler before
3383 * L2 receive handler so that association events are processed before
3384 * EAPOL-Key packets if both become available for the same select()
3385 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003386 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003387 return -1;
3388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003389 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3390 return -1;
3391
3392 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3393 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3394 NULL);
3395 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3396
3397 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3398 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3399 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3400 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3401 "dot11RSNAConfigPMKLifetime");
3402 return -1;
3403 }
3404
3405 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3406 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3407 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3408 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3409 "dot11RSNAConfigPMKReauthThreshold");
3410 return -1;
3411 }
3412
3413 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3414 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3415 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3416 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3417 "dot11RSNAConfigSATimeout");
3418 return -1;
3419 }
3420
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003421 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3422 &wpa_s->hw.num_modes,
3423 &wpa_s->hw.flags);
3424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003426 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003427 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003428 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003429 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003430 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003431 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3432 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3433 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003434 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3435 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003436 wpa_s->extended_capa = capa.extended_capa;
3437 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3438 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003439 wpa_s->num_multichan_concurrent =
3440 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003441 }
3442 if (wpa_s->max_remain_on_chan == 0)
3443 wpa_s->max_remain_on_chan = 1000;
3444
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003445 /*
3446 * Only take p2p_mgmt parameters when P2P Device is supported.
3447 * Doing it here as it determines whether l2_packet_init() will be done
3448 * during wpa_supplicant_driver_init().
3449 */
3450 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3451 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3452 else
3453 iface->p2p_mgmt = 1;
3454
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003455 if (wpa_s->num_multichan_concurrent == 0)
3456 wpa_s->num_multichan_concurrent = 1;
3457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003458 if (wpa_supplicant_driver_init(wpa_s) < 0)
3459 return -1;
3460
3461#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003462 if ((!iface->p2p_mgmt ||
3463 !(wpa_s->drv_flags &
3464 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3465 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 return -1;
3467#endif /* CONFIG_TDLS */
3468
3469 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3470 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3471 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3472 return -1;
3473 }
3474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 if (wpas_wps_init(wpa_s))
3476 return -1;
3477
3478 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3479 return -1;
3480 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3481
3482 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3483 if (wpa_s->ctrl_iface == NULL) {
3484 wpa_printf(MSG_ERROR,
3485 "Failed to initialize control interface '%s'.\n"
3486 "You may have another wpa_supplicant process "
3487 "already running or the file was\n"
3488 "left by an unclean termination of wpa_supplicant "
3489 "in which case you will need\n"
3490 "to manually remove this file before starting "
3491 "wpa_supplicant again.\n",
3492 wpa_s->conf->ctrl_interface);
3493 return -1;
3494 }
3495
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003496 wpa_s->gas = gas_query_init(wpa_s);
3497 if (wpa_s->gas == NULL) {
3498 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3499 return -1;
3500 }
3501
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003502#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003503 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3505 return -1;
3506 }
3507#endif /* CONFIG_P2P */
3508
3509 if (wpa_bss_init(wpa_s) < 0)
3510 return -1;
3511
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003512#ifdef CONFIG_EAP_PROXY
3513{
3514 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003515 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3516 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003517 if (wpa_s->mnc_len > 0) {
3518 wpa_s->imsi[len] = '\0';
3519 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3520 wpa_s->imsi, wpa_s->mnc_len);
3521 } else {
3522 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3523 }
3524}
3525#endif /* CONFIG_EAP_PROXY */
3526
Dmitry Shmidt04949592012-07-19 12:16:46 -07003527 if (pcsc_reader_init(wpa_s) < 0)
3528 return -1;
3529
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003530 if (wpas_init_ext_pw(wpa_s) < 0)
3531 return -1;
3532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 return 0;
3534}
3535
3536
3537static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003538 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003540 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003541 if (wpa_s->drv_priv) {
3542 wpa_supplicant_deauthenticate(wpa_s,
3543 WLAN_REASON_DEAUTH_LEAVING);
3544
3545 wpa_drv_set_countermeasures(wpa_s, 0);
3546 wpa_clear_keys(wpa_s, NULL);
3547 }
3548
3549 wpa_supplicant_cleanup(wpa_s);
3550
Dmitry Shmidt04949592012-07-19 12:16:46 -07003551#ifdef CONFIG_P2P
3552 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3553 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3554 "the management interface is being removed");
3555 wpas_p2p_deinit_global(wpa_s->global);
3556 }
3557#endif /* CONFIG_P2P */
3558
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003559 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003560 radio_remove_interface(wpa_s);
3561
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 if (wpa_s->drv_priv)
3563 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003564
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003565 if (notify)
3566 wpas_notify_iface_removed(wpa_s);
3567
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003568 if (terminate)
3569 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003570
3571 if (wpa_s->ctrl_iface) {
3572 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3573 wpa_s->ctrl_iface = NULL;
3574 }
3575
3576 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003577 wpa_config_free(wpa_s->conf);
3578 wpa_s->conf = NULL;
3579 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003580
3581 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003582}
3583
3584
3585/**
3586 * wpa_supplicant_add_iface - Add a new network interface
3587 * @global: Pointer to global data from wpa_supplicant_init()
3588 * @iface: Interface configuration options
3589 * Returns: Pointer to the created interface or %NULL on failure
3590 *
3591 * This function is used to add new network interfaces for %wpa_supplicant.
3592 * This can be called before wpa_supplicant_run() to add interfaces before the
3593 * main event loop has been started. In addition, new interfaces can be added
3594 * dynamically while %wpa_supplicant is already running. This could happen,
3595 * e.g., when a hotplug network adapter is inserted.
3596 */
3597struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3598 struct wpa_interface *iface)
3599{
3600 struct wpa_supplicant *wpa_s;
3601 struct wpa_interface t_iface;
3602 struct wpa_ssid *ssid;
3603
3604 if (global == NULL || iface == NULL)
3605 return NULL;
3606
3607 wpa_s = wpa_supplicant_alloc();
3608 if (wpa_s == NULL)
3609 return NULL;
3610
3611 wpa_s->global = global;
3612
3613 t_iface = *iface;
3614 if (global->params.override_driver) {
3615 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3616 "('%s' -> '%s')",
3617 iface->driver, global->params.override_driver);
3618 t_iface.driver = global->params.override_driver;
3619 }
3620 if (global->params.override_ctrl_interface) {
3621 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3622 "ctrl_interface ('%s' -> '%s')",
3623 iface->ctrl_interface,
3624 global->params.override_ctrl_interface);
3625 t_iface.ctrl_interface =
3626 global->params.override_ctrl_interface;
3627 }
3628 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3629 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3630 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003631 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632 return NULL;
3633 }
3634
3635 /* Notify the control interfaces about new iface */
3636 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003637 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003638 return NULL;
3639 }
3640
3641 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3642 wpas_notify_network_added(wpa_s, ssid);
3643
3644 wpa_s->next = global->ifaces;
3645 global->ifaces = wpa_s;
3646
3647 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003648 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649
3650 return wpa_s;
3651}
3652
3653
3654/**
3655 * wpa_supplicant_remove_iface - Remove a network interface
3656 * @global: Pointer to global data from wpa_supplicant_init()
3657 * @wpa_s: Pointer to the network interface to be removed
3658 * Returns: 0 if interface was removed, -1 if interface was not found
3659 *
3660 * This function can be used to dynamically remove network interfaces from
3661 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3662 * addition, this function is used to remove all remaining interfaces when
3663 * %wpa_supplicant is terminated.
3664 */
3665int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003666 struct wpa_supplicant *wpa_s,
3667 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668{
3669 struct wpa_supplicant *prev;
3670
3671 /* Remove interface from the global list of interfaces */
3672 prev = global->ifaces;
3673 if (prev == wpa_s) {
3674 global->ifaces = wpa_s->next;
3675 } else {
3676 while (prev && prev->next != wpa_s)
3677 prev = prev->next;
3678 if (prev == NULL)
3679 return -1;
3680 prev->next = wpa_s->next;
3681 }
3682
3683 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3684
3685 if (global->p2p_group_formation == wpa_s)
3686 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003687 if (global->p2p_invite_group == wpa_s)
3688 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003689 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690
3691 return 0;
3692}
3693
3694
3695/**
3696 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3697 * @wpa_s: Pointer to the network interface
3698 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3699 */
3700const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3701{
3702 const char *eapol_method;
3703
3704 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3705 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3706 return "NO-EAP";
3707 }
3708
3709 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3710 if (eapol_method == NULL)
3711 return "UNKNOWN-EAP";
3712
3713 return eapol_method;
3714}
3715
3716
3717/**
3718 * wpa_supplicant_get_iface - Get a new network interface
3719 * @global: Pointer to global data from wpa_supplicant_init()
3720 * @ifname: Interface name
3721 * Returns: Pointer to the interface or %NULL if not found
3722 */
3723struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3724 const char *ifname)
3725{
3726 struct wpa_supplicant *wpa_s;
3727
3728 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3729 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3730 return wpa_s;
3731 }
3732 return NULL;
3733}
3734
3735
3736#ifndef CONFIG_NO_WPA_MSG
3737static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3738{
3739 struct wpa_supplicant *wpa_s = ctx;
3740 if (wpa_s == NULL)
3741 return NULL;
3742 return wpa_s->ifname;
3743}
3744#endif /* CONFIG_NO_WPA_MSG */
3745
3746
3747/**
3748 * wpa_supplicant_init - Initialize %wpa_supplicant
3749 * @params: Parameters for %wpa_supplicant
3750 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3751 *
3752 * This function is used to initialize %wpa_supplicant. After successful
3753 * initialization, the returned data pointer can be used to add and remove
3754 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3755 */
3756struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3757{
3758 struct wpa_global *global;
3759 int ret, i;
3760
3761 if (params == NULL)
3762 return NULL;
3763
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003764#ifdef CONFIG_DRIVER_NDIS
3765 {
3766 void driver_ndis_init_ops(void);
3767 driver_ndis_init_ops();
3768 }
3769#endif /* CONFIG_DRIVER_NDIS */
3770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003771#ifndef CONFIG_NO_WPA_MSG
3772 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3773#endif /* CONFIG_NO_WPA_MSG */
3774
3775 wpa_debug_open_file(params->wpa_debug_file_path);
3776 if (params->wpa_debug_syslog)
3777 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003778 if (params->wpa_debug_tracing) {
3779 ret = wpa_debug_open_linux_tracing();
3780 if (ret) {
3781 wpa_printf(MSG_ERROR,
3782 "Failed to enable trace logging");
3783 return NULL;
3784 }
3785 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786
3787 ret = eap_register_methods();
3788 if (ret) {
3789 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3790 if (ret == -2)
3791 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3792 "the same EAP type.");
3793 return NULL;
3794 }
3795
3796 global = os_zalloc(sizeof(*global));
3797 if (global == NULL)
3798 return NULL;
3799 dl_list_init(&global->p2p_srv_bonjour);
3800 dl_list_init(&global->p2p_srv_upnp);
3801 global->params.daemonize = params->daemonize;
3802 global->params.wait_for_monitor = params->wait_for_monitor;
3803 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3804 if (params->pid_file)
3805 global->params.pid_file = os_strdup(params->pid_file);
3806 if (params->ctrl_interface)
3807 global->params.ctrl_interface =
3808 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003809 if (params->ctrl_interface_group)
3810 global->params.ctrl_interface_group =
3811 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003812 if (params->override_driver)
3813 global->params.override_driver =
3814 os_strdup(params->override_driver);
3815 if (params->override_ctrl_interface)
3816 global->params.override_ctrl_interface =
3817 os_strdup(params->override_ctrl_interface);
3818 wpa_debug_level = global->params.wpa_debug_level =
3819 params->wpa_debug_level;
3820 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3821 params->wpa_debug_show_keys;
3822 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3823 params->wpa_debug_timestamp;
3824
3825 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3826
3827 if (eloop_init()) {
3828 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3829 wpa_supplicant_deinit(global);
3830 return NULL;
3831 }
3832
Jouni Malinen75ecf522011-06-27 15:19:46 -07003833 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003834
3835 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3836 if (global->ctrl_iface == NULL) {
3837 wpa_supplicant_deinit(global);
3838 return NULL;
3839 }
3840
3841 if (wpas_notify_supplicant_initialized(global)) {
3842 wpa_supplicant_deinit(global);
3843 return NULL;
3844 }
3845
3846 for (i = 0; wpa_drivers[i]; i++)
3847 global->drv_count++;
3848 if (global->drv_count == 0) {
3849 wpa_printf(MSG_ERROR, "No drivers enabled");
3850 wpa_supplicant_deinit(global);
3851 return NULL;
3852 }
3853 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3854 if (global->drv_priv == NULL) {
3855 wpa_supplicant_deinit(global);
3856 return NULL;
3857 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003858
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003859#ifdef CONFIG_WIFI_DISPLAY
3860 if (wifi_display_init(global) < 0) {
3861 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3862 wpa_supplicant_deinit(global);
3863 return NULL;
3864 }
3865#endif /* CONFIG_WIFI_DISPLAY */
3866
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867 return global;
3868}
3869
3870
3871/**
3872 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3873 * @global: Pointer to global data from wpa_supplicant_init()
3874 * Returns: 0 after successful event loop run, -1 on failure
3875 *
3876 * This function starts the main event loop and continues running as long as
3877 * there are any remaining events. In most cases, this function is running as
3878 * long as the %wpa_supplicant process in still in use.
3879 */
3880int wpa_supplicant_run(struct wpa_global *global)
3881{
3882 struct wpa_supplicant *wpa_s;
3883
3884 if (global->params.daemonize &&
3885 wpa_supplicant_daemon(global->params.pid_file))
3886 return -1;
3887
3888 if (global->params.wait_for_monitor) {
3889 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3890 if (wpa_s->ctrl_iface)
3891 wpa_supplicant_ctrl_iface_wait(
3892 wpa_s->ctrl_iface);
3893 }
3894
3895 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3896 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3897
3898 eloop_run();
3899
3900 return 0;
3901}
3902
3903
3904/**
3905 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3906 * @global: Pointer to global data from wpa_supplicant_init()
3907 *
3908 * This function is called to deinitialize %wpa_supplicant and to free all
3909 * allocated resources. Remaining network interfaces will also be removed.
3910 */
3911void wpa_supplicant_deinit(struct wpa_global *global)
3912{
3913 int i;
3914
3915 if (global == NULL)
3916 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003917
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003918#ifdef CONFIG_WIFI_DISPLAY
3919 wifi_display_deinit(global);
3920#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003921
3922 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003923 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003924
3925 if (global->ctrl_iface)
3926 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3927
3928 wpas_notify_supplicant_deinitialized(global);
3929
3930 eap_peer_unregister_methods();
3931#ifdef CONFIG_AP
3932 eap_server_unregister_methods();
3933#endif /* CONFIG_AP */
3934
3935 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3936 if (!global->drv_priv[i])
3937 continue;
3938 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3939 }
3940 os_free(global->drv_priv);
3941
3942 random_deinit();
3943
3944 eloop_destroy();
3945
3946 if (global->params.pid_file) {
3947 os_daemonize_terminate(global->params.pid_file);
3948 os_free(global->params.pid_file);
3949 }
3950 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003951 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003952 os_free(global->params.override_driver);
3953 os_free(global->params.override_ctrl_interface);
3954
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003955 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003956 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003957 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959 os_free(global);
3960 wpa_debug_close_syslog();
3961 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003962 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003963}
3964
3965
3966void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3967{
3968 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3969 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3970 char country[3];
3971 country[0] = wpa_s->conf->country[0];
3972 country[1] = wpa_s->conf->country[1];
3973 country[2] = '\0';
3974 if (wpa_drv_set_country(wpa_s, country) < 0) {
3975 wpa_printf(MSG_ERROR, "Failed to set country code "
3976 "'%s'", country);
3977 }
3978 }
3979
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003980 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3981 wpas_init_ext_pw(wpa_s);
3982
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003983#ifdef CONFIG_WPS
3984 wpas_wps_update_config(wpa_s);
3985#endif /* CONFIG_WPS */
3986
3987#ifdef CONFIG_P2P
3988 wpas_p2p_update_config(wpa_s);
3989#endif /* CONFIG_P2P */
3990
3991 wpa_s->conf->changed_parameters = 0;
3992}
3993
3994
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995static void add_freq(int *freqs, int *num_freqs, int freq)
3996{
3997 int i;
3998
3999 for (i = 0; i < *num_freqs; i++) {
4000 if (freqs[i] == freq)
4001 return;
4002 }
4003
4004 freqs[*num_freqs] = freq;
4005 (*num_freqs)++;
4006}
4007
4008
4009static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4010{
4011 struct wpa_bss *bss, *cbss;
4012 const int max_freqs = 10;
4013 int *freqs;
4014 int num_freqs = 0;
4015
4016 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4017 if (freqs == NULL)
4018 return NULL;
4019
4020 cbss = wpa_s->current_bss;
4021
4022 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4023 if (bss == cbss)
4024 continue;
4025 if (bss->ssid_len == cbss->ssid_len &&
4026 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4027 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4028 add_freq(freqs, &num_freqs, bss->freq);
4029 if (num_freqs == max_freqs)
4030 break;
4031 }
4032 }
4033
4034 if (num_freqs == 0) {
4035 os_free(freqs);
4036 freqs = NULL;
4037 }
4038
4039 return freqs;
4040}
4041
4042
4043void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4044{
4045 int timeout;
4046 int count;
4047 int *freqs = NULL;
4048
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004049 wpas_connect_work_done(wpa_s);
4050
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004051 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004052 * Remove possible authentication timeout since the connection failed.
4053 */
4054 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4055
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004056 if (wpa_s->disconnected) {
4057 /*
4058 * There is no point in blacklisting the AP if this event is
4059 * generated based on local request to disconnect.
4060 */
4061 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4062 "indication since interface has been put into "
4063 "disconnected state");
4064 return;
4065 }
4066
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004067 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004068 * Add the failed BSSID into the blacklist and speed up next scan
4069 * attempt if there could be other APs that could accept association.
4070 * The current blacklist count indicates how many times we have tried
4071 * connecting to this AP and multiple attempts mean that other APs are
4072 * either not available or has already been tried, so that we can start
4073 * increasing the delay here to avoid constant scanning.
4074 */
4075 count = wpa_blacklist_add(wpa_s, bssid);
4076 if (count == 1 && wpa_s->current_bss) {
4077 /*
4078 * This BSS was not in the blacklist before. If there is
4079 * another BSS available for the same ESS, we should try that
4080 * next. Otherwise, we may as well try this one once more
4081 * before allowing other, likely worse, ESSes to be considered.
4082 */
4083 freqs = get_bss_freqs_in_ess(wpa_s);
4084 if (freqs) {
4085 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4086 "has been seen; try it next");
4087 wpa_blacklist_add(wpa_s, bssid);
4088 /*
4089 * On the next scan, go through only the known channels
4090 * used in this ESS based on previous scans to speed up
4091 * common load balancing use case.
4092 */
4093 os_free(wpa_s->next_scan_freqs);
4094 wpa_s->next_scan_freqs = freqs;
4095 }
4096 }
4097
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004098 /*
4099 * Add previous failure count in case the temporary blacklist was
4100 * cleared due to no other BSSes being available.
4101 */
4102 count += wpa_s->extra_blacklist_count;
4103
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004104 if (count > 3 && wpa_s->current_ssid) {
4105 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4106 "consider temporary network disabling");
4107 wpas_auth_failed(wpa_s);
4108 }
4109
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004110 switch (count) {
4111 case 1:
4112 timeout = 100;
4113 break;
4114 case 2:
4115 timeout = 500;
4116 break;
4117 case 3:
4118 timeout = 1000;
4119 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004120 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004121 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004122 break;
4123 default:
4124 timeout = 10000;
4125 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 }
4127
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004128 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4129 "ms", count, timeout);
4130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004131 /*
4132 * TODO: if more than one possible AP is available in scan results,
4133 * could try the other ones before requesting a new scan.
4134 */
4135 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4136 1000 * (timeout % 1000));
4137}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004138
4139
4140int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4141{
4142 return wpa_s->conf->ap_scan == 2 ||
4143 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4144}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004145
Dmitry Shmidt04949592012-07-19 12:16:46 -07004146
4147#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4148int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4149 struct wpa_ssid *ssid,
4150 const char *field,
4151 const char *value)
4152{
4153#ifdef IEEE8021X_EAPOL
4154 struct eap_peer_config *eap = &ssid->eap;
4155
4156 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4157 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4158 (const u8 *) value, os_strlen(value));
4159
4160 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4161 case WPA_CTRL_REQ_EAP_IDENTITY:
4162 os_free(eap->identity);
4163 eap->identity = (u8 *) os_strdup(value);
4164 eap->identity_len = os_strlen(value);
4165 eap->pending_req_identity = 0;
4166 if (ssid == wpa_s->current_ssid)
4167 wpa_s->reassociate = 1;
4168 break;
4169 case WPA_CTRL_REQ_EAP_PASSWORD:
4170 os_free(eap->password);
4171 eap->password = (u8 *) os_strdup(value);
4172 eap->password_len = os_strlen(value);
4173 eap->pending_req_password = 0;
4174 if (ssid == wpa_s->current_ssid)
4175 wpa_s->reassociate = 1;
4176 break;
4177 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4178 os_free(eap->new_password);
4179 eap->new_password = (u8 *) os_strdup(value);
4180 eap->new_password_len = os_strlen(value);
4181 eap->pending_req_new_password = 0;
4182 if (ssid == wpa_s->current_ssid)
4183 wpa_s->reassociate = 1;
4184 break;
4185 case WPA_CTRL_REQ_EAP_PIN:
4186 os_free(eap->pin);
4187 eap->pin = os_strdup(value);
4188 eap->pending_req_pin = 0;
4189 if (ssid == wpa_s->current_ssid)
4190 wpa_s->reassociate = 1;
4191 break;
4192 case WPA_CTRL_REQ_EAP_OTP:
4193 os_free(eap->otp);
4194 eap->otp = (u8 *) os_strdup(value);
4195 eap->otp_len = os_strlen(value);
4196 os_free(eap->pending_req_otp);
4197 eap->pending_req_otp = NULL;
4198 eap->pending_req_otp_len = 0;
4199 break;
4200 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4201 os_free(eap->private_key_passwd);
4202 eap->private_key_passwd = (u8 *) os_strdup(value);
4203 eap->pending_req_passphrase = 0;
4204 if (ssid == wpa_s->current_ssid)
4205 wpa_s->reassociate = 1;
4206 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004207 case WPA_CTRL_REQ_SIM:
4208 os_free(eap->external_sim_resp);
4209 eap->external_sim_resp = os_strdup(value);
4210 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004211 default:
4212 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4213 return -1;
4214 }
4215
4216 return 0;
4217#else /* IEEE8021X_EAPOL */
4218 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4219 return -1;
4220#endif /* IEEE8021X_EAPOL */
4221}
4222#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4223
4224
4225int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4226{
4227 int i;
4228 unsigned int drv_enc;
4229
4230 if (ssid == NULL)
4231 return 1;
4232
4233 if (ssid->disabled)
4234 return 1;
4235
4236 if (wpa_s && wpa_s->drv_capa_known)
4237 drv_enc = wpa_s->drv_enc;
4238 else
4239 drv_enc = (unsigned int) -1;
4240
4241 for (i = 0; i < NUM_WEP_KEYS; i++) {
4242 size_t len = ssid->wep_key_len[i];
4243 if (len == 0)
4244 continue;
4245 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4246 continue;
4247 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4248 continue;
4249 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4250 continue;
4251 return 1; /* invalid WEP key */
4252 }
4253
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004254 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4255 !ssid->ext_psk)
4256 return 1;
4257
Dmitry Shmidt04949592012-07-19 12:16:46 -07004258 return 0;
4259}
4260
4261
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004262int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004263{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004264 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004265 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004266 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004267 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004268 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004269}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004270
4271
4272void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4273{
4274 struct wpa_ssid *ssid = wpa_s->current_ssid;
4275 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004276 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004277
4278 if (ssid == NULL) {
4279 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4280 "SSID block");
4281 return;
4282 }
4283
4284 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4285 return;
4286
4287 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004288
4289#ifdef CONFIG_P2P
4290 if (ssid->p2p_group &&
4291 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4292 /*
4293 * Skip the wait time since there is a short timeout on the
4294 * connection to a P2P group.
4295 */
4296 return;
4297 }
4298#endif /* CONFIG_P2P */
4299
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004300 if (ssid->auth_failures > 50)
4301 dur = 300;
4302 else if (ssid->auth_failures > 20)
4303 dur = 120;
4304 else if (ssid->auth_failures > 10)
4305 dur = 60;
4306 else if (ssid->auth_failures > 5)
4307 dur = 30;
4308 else if (ssid->auth_failures > 1)
4309 dur = 20;
4310 else
4311 dur = 10;
4312
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004313 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004314 if (now.sec + dur <= ssid->disabled_until.sec)
4315 return;
4316
4317 ssid->disabled_until.sec = now.sec + dur;
4318
4319 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4320 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4321 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4322 ssid->auth_failures, dur);
4323}
4324
4325
4326void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4327 struct wpa_ssid *ssid, int clear_failures)
4328{
4329 if (ssid == NULL)
4330 return;
4331
4332 if (ssid->disabled_until.sec) {
4333 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4334 "id=%d ssid=\"%s\"",
4335 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4336 }
4337 ssid->disabled_until.sec = 0;
4338 ssid->disabled_until.usec = 0;
4339 if (clear_failures)
4340 ssid->auth_failures = 0;
4341}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004342
4343
4344int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4345{
4346 size_t i;
4347
4348 if (wpa_s->disallow_aps_bssid == NULL)
4349 return 0;
4350
4351 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4352 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4353 bssid, ETH_ALEN) == 0)
4354 return 1;
4355 }
4356
4357 return 0;
4358}
4359
4360
4361int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4362 size_t ssid_len)
4363{
4364 size_t i;
4365
4366 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4367 return 0;
4368
4369 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4370 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4371 if (ssid_len == s->ssid_len &&
4372 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4373 return 1;
4374 }
4375
4376 return 0;
4377}
4378
4379
4380/**
4381 * wpas_request_connection - Request a new connection
4382 * @wpa_s: Pointer to the network interface
4383 *
4384 * This function is used to request a new connection to be found. It will mark
4385 * the interface to allow reassociation and request a new scan to find a
4386 * suitable network to connect to.
4387 */
4388void wpas_request_connection(struct wpa_supplicant *wpa_s)
4389{
4390 wpa_s->normal_scans = 0;
4391 wpa_supplicant_reinit_autoscan(wpa_s);
4392 wpa_s->extra_blacklist_count = 0;
4393 wpa_s->disconnected = 0;
4394 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004395
4396 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4397 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004398}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004399
4400
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004401void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4402 int *freq_array, unsigned int len)
4403{
4404 unsigned int i;
4405
4406 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4407 len, title);
4408 for (i = 0; i < len; i++)
4409 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4410}
4411
4412
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004413/*
4414 * Find the operating frequencies of any of the virtual interfaces that
4415 * are using the same radio as the current interface.
4416 */
4417int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4418 int *freq_array, unsigned int len)
4419{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004420 struct wpa_supplicant *ifs;
4421 u8 bssid[ETH_ALEN];
4422 int freq;
4423 unsigned int idx = 0, i;
4424
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004425 wpa_dbg(wpa_s, MSG_DEBUG,
4426 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004427 os_memset(freq_array, 0, sizeof(int) * len);
4428
4429 /* First add the frequency of the local interface */
4430 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4431 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4432 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4433 freq_array[idx++] = wpa_s->current_ssid->frequency;
4434 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4435 freq_array[idx++] = wpa_s->assoc_freq;
4436 }
4437
4438 /* If get_radio_name is not supported, use only the local freq */
4439 if (!wpa_s->driver->get_radio_name) {
4440 freq = wpa_drv_shared_freq(wpa_s);
4441 if (freq > 0 && idx < len &&
4442 (idx == 0 || freq_array[0] != freq))
4443 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004444 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004445 return idx;
4446 }
4447
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004448 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4449 radio_list) {
4450 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004451 continue;
4452
4453 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4454 continue;
4455
4456 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4457 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4458 freq = ifs->current_ssid->frequency;
4459 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4460 freq = ifs->assoc_freq;
4461 else
4462 continue;
4463
4464 /* Hold only distinct freqs */
4465 for (i = 0; i < idx; i++)
4466 if (freq_array[i] == freq)
4467 break;
4468
4469 if (i == idx)
4470 freq_array[idx++] = freq;
4471 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004472
4473 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004474 return idx;
4475}