blob: 187e5d9bce4ec6553053a4b6ac28acb46ac80bec [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 Shmidtfb79edc2014-01-10 10:45:54 -0800655 if (state == WPA_COMPLETED)
656 wpas_connect_work_done(wpa_s);
657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 if (state != WPA_SCANNING)
659 wpa_supplicant_notify_scanning(wpa_s, 0);
660
661 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700663#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800665 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800666 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667 ssid ? ssid->id : -1,
668 ssid && ssid->id_str ? ssid->id_str : "");
669#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800671 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673 wpa_drv_set_operstate(wpa_s, 1);
674#ifndef IEEE8021X_EAPOL
675 wpa_drv_set_supp_port(wpa_s, 1);
676#endif /* IEEE8021X_EAPOL */
677 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700678 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700679#ifdef CONFIG_P2P
680 wpas_p2p_completed(wpa_s);
681#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700682
683 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
685 state == WPA_ASSOCIATED) {
686 wpa_s->new_connection = 1;
687 wpa_drv_set_operstate(wpa_s, 0);
688#ifndef IEEE8021X_EAPOL
689 wpa_drv_set_supp_port(wpa_s, 0);
690#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700691 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 }
693 wpa_s->wpa_state = state;
694
695#ifdef CONFIG_BGSCAN
696 if (state == WPA_COMPLETED)
697 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800698 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 wpa_supplicant_stop_bgscan(wpa_s);
700#endif /* CONFIG_BGSCAN */
701
Dmitry Shmidt04949592012-07-19 12:16:46 -0700702 if (state == WPA_AUTHENTICATING)
703 wpa_supplicant_stop_autoscan(wpa_s);
704
705 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
706 wpa_supplicant_start_autoscan(wpa_s);
707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708 if (wpa_s->wpa_state != old_state) {
709 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
710
711 if (wpa_s->wpa_state == WPA_COMPLETED ||
712 old_state == WPA_COMPLETED)
713 wpas_notify_auth_changed(wpa_s);
714 }
715}
716
717
718void wpa_supplicant_terminate_proc(struct wpa_global *global)
719{
720 int pending = 0;
721#ifdef CONFIG_WPS
722 struct wpa_supplicant *wpa_s = global->ifaces;
723 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800724 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700725#ifdef CONFIG_P2P
726 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
727 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
728 wpas_p2p_disconnect(wpa_s);
729#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730 if (wpas_wps_terminate_pending(wpa_s) == 1)
731 pending = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800732 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700733 }
734#endif /* CONFIG_WPS */
735 if (pending)
736 return;
737 eloop_terminate();
738}
739
740
741static void wpa_supplicant_terminate(int sig, void *signal_ctx)
742{
743 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744 wpa_supplicant_terminate_proc(global);
745}
746
747
748void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
749{
750 enum wpa_states old_state = wpa_s->wpa_state;
751
752 wpa_s->pairwise_cipher = 0;
753 wpa_s->group_cipher = 0;
754 wpa_s->mgmt_group_cipher = 0;
755 wpa_s->key_mgmt = 0;
756 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700757 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700758
759 if (wpa_s->wpa_state != old_state)
760 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
761}
762
763
764/**
765 * wpa_supplicant_reload_configuration - Reload configuration data
766 * @wpa_s: Pointer to wpa_supplicant data
767 * Returns: 0 on success or -1 if configuration parsing failed
768 *
769 * This function can be used to request that the configuration data is reloaded
770 * (e.g., after configuration file change). This function is reloading
771 * configuration only for one interface, so this may need to be called multiple
772 * times if %wpa_supplicant is controlling multiple interfaces and all
773 * interfaces need reconfiguration.
774 */
775int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
776{
777 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778 int reconf_ctrl;
779 int old_ap_scan;
780
781 if (wpa_s->confname == NULL)
782 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700783 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 if (conf == NULL) {
785 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
786 "file '%s' - exiting", wpa_s->confname);
787 return -1;
788 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700789 wpa_config_read(wpa_s->confanother, conf);
790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791 conf->changed_parameters = (unsigned int) -1;
792
793 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
794 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
795 os_strcmp(conf->ctrl_interface,
796 wpa_s->conf->ctrl_interface) != 0);
797
798 if (reconf_ctrl && wpa_s->ctrl_iface) {
799 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
800 wpa_s->ctrl_iface = NULL;
801 }
802
803 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800804 if (wpa_s->current_ssid) {
805 wpa_supplicant_deauthenticate(wpa_s,
806 WLAN_REASON_DEAUTH_LEAVING);
807 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808
809 /*
810 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
811 * pkcs11_engine_path, pkcs11_module_path.
812 */
813 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
814 /*
815 * Clear forced success to clear EAP state for next
816 * authentication.
817 */
818 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
819 }
820 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
821 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800822 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
824 rsn_preauth_deinit(wpa_s->wpa);
825
826 old_ap_scan = wpa_s->conf->ap_scan;
827 wpa_config_free(wpa_s->conf);
828 wpa_s->conf = conf;
829 if (old_ap_scan != wpa_s->conf->ap_scan)
830 wpas_notify_ap_scan_changed(wpa_s);
831
832 if (reconf_ctrl)
833 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
834
835 wpa_supplicant_update_config(wpa_s);
836
837 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700838 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839 wpa_s->reassociate = 1;
840 wpa_supplicant_req_scan(wpa_s, 0, 0);
841 }
842 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
843 return 0;
844}
845
846
847static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
848{
849 struct wpa_global *global = signal_ctx;
850 struct wpa_supplicant *wpa_s;
851 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
852 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
853 sig);
854 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
855 wpa_supplicant_terminate_proc(global);
856 }
857 }
858}
859
860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
862 struct wpa_ssid *ssid,
863 struct wpa_ie_data *ie)
864{
865 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
866 if (ret) {
867 if (ret == -2) {
868 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
869 "from association info");
870 }
871 return -1;
872 }
873
874 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
875 "cipher suites");
876 if (!(ie->group_cipher & ssid->group_cipher)) {
877 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
878 "cipher 0x%x (mask 0x%x) - reject",
879 ie->group_cipher, ssid->group_cipher);
880 return -1;
881 }
882 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
883 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
884 "cipher 0x%x (mask 0x%x) - reject",
885 ie->pairwise_cipher, ssid->pairwise_cipher);
886 return -1;
887 }
888 if (!(ie->key_mgmt & ssid->key_mgmt)) {
889 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
890 "management 0x%x (mask 0x%x) - reject",
891 ie->key_mgmt, ssid->key_mgmt);
892 return -1;
893 }
894
895#ifdef CONFIG_IEEE80211W
896 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800897 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
898 wpa_s->conf->pmf : ssid->ieee80211w) ==
899 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700900 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
901 "that does not support management frame protection - "
902 "reject");
903 return -1;
904 }
905#endif /* CONFIG_IEEE80211W */
906
907 return 0;
908}
909
910
911/**
912 * wpa_supplicant_set_suites - Set authentication and encryption parameters
913 * @wpa_s: Pointer to wpa_supplicant data
914 * @bss: Scan results for the selected BSS, or %NULL if not available
915 * @ssid: Configuration data for the selected network
916 * @wpa_ie: Buffer for the WPA/RSN IE
917 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
918 * used buffer length in case the functions returns success.
919 * Returns: 0 on success or -1 on failure
920 *
921 * This function is used to configure authentication and encryption parameters
922 * based on the network configuration and scan result for the selected BSS (if
923 * available).
924 */
925int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
926 struct wpa_bss *bss, struct wpa_ssid *ssid,
927 u8 *wpa_ie, size_t *wpa_ie_len)
928{
929 struct wpa_ie_data ie;
930 int sel, proto;
931 const u8 *bss_wpa, *bss_rsn;
932
933 if (bss) {
934 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
935 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
936 } else
937 bss_wpa = bss_rsn = NULL;
938
939 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
940 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
941 (ie.group_cipher & ssid->group_cipher) &&
942 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
943 (ie.key_mgmt & ssid->key_mgmt)) {
944 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
945 proto = WPA_PROTO_RSN;
946 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
947 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
948 (ie.group_cipher & ssid->group_cipher) &&
949 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
950 (ie.key_mgmt & ssid->key_mgmt)) {
951 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
952 proto = WPA_PROTO_WPA;
953 } else if (bss) {
954 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
955 return -1;
956 } else {
957 if (ssid->proto & WPA_PROTO_RSN)
958 proto = WPA_PROTO_RSN;
959 else
960 proto = WPA_PROTO_WPA;
961 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
962 os_memset(&ie, 0, sizeof(ie));
963 ie.group_cipher = ssid->group_cipher;
964 ie.pairwise_cipher = ssid->pairwise_cipher;
965 ie.key_mgmt = ssid->key_mgmt;
966#ifdef CONFIG_IEEE80211W
967 ie.mgmt_group_cipher =
968 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
969 WPA_CIPHER_AES_128_CMAC : 0;
970#endif /* CONFIG_IEEE80211W */
971 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
972 "based on configuration");
973 } else
974 proto = ie.proto;
975 }
976
977 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
978 "pairwise %d key_mgmt %d proto %d",
979 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
980#ifdef CONFIG_IEEE80211W
981 if (ssid->ieee80211w) {
982 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
983 ie.mgmt_group_cipher);
984 }
985#endif /* CONFIG_IEEE80211W */
986
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800987 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700988 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
989 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
990 !!(ssid->proto & WPA_PROTO_RSN));
991
992 if (bss || !wpa_s->ap_ies_from_associnfo) {
993 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
994 bss_wpa ? 2 + bss_wpa[1] : 0) ||
995 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
996 bss_rsn ? 2 + bss_rsn[1] : 0))
997 return -1;
998 }
999
1000 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001001 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1002 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1004 "cipher");
1005 return -1;
1006 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001007 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1008 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001009
1010 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001011 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1012 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1014 "cipher");
1015 return -1;
1016 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001017 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1018 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001019
1020 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001021#ifdef CONFIG_SAE
1022 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1023 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1024#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 if (0) {
1026#ifdef CONFIG_IEEE80211R
1027 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1028 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1029 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1030 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1031 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1032 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1033#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001034#ifdef CONFIG_SAE
1035 } else if (sel & WPA_KEY_MGMT_SAE) {
1036 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1037 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1038 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1039 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1040 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1041#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042#ifdef CONFIG_IEEE80211W
1043 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1044 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1045 wpa_dbg(wpa_s, MSG_DEBUG,
1046 "WPA: using KEY_MGMT 802.1X with SHA256");
1047 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1048 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1049 wpa_dbg(wpa_s, MSG_DEBUG,
1050 "WPA: using KEY_MGMT PSK with SHA256");
1051#endif /* CONFIG_IEEE80211W */
1052 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1053 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1054 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1055 } else if (sel & WPA_KEY_MGMT_PSK) {
1056 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1057 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1058 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1059 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1060 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1061 } else {
1062 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1063 "authenticated key management type");
1064 return -1;
1065 }
1066
1067 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1068 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1069 wpa_s->pairwise_cipher);
1070 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1071
1072#ifdef CONFIG_IEEE80211W
1073 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001074 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1075 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1077 sel = 0;
1078 if (sel & WPA_CIPHER_AES_128_CMAC) {
1079 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1080 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1081 "AES-128-CMAC");
1082 } else {
1083 wpa_s->mgmt_group_cipher = 0;
1084 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1085 }
1086 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1087 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001088 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1089 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1090 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091#endif /* CONFIG_IEEE80211W */
1092
1093 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1094 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1095 return -1;
1096 }
1097
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001098 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001100#ifndef CONFIG_NO_PBKDF2
1101 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1102 ssid->passphrase) {
1103 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001104 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1105 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001106 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1107 psk, PMK_LEN);
1108 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1109 }
1110#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001111#ifdef CONFIG_EXT_PASSWORD
1112 if (ssid->ext_psk) {
1113 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1114 ssid->ext_psk);
1115 char pw_str[64 + 1];
1116 u8 psk[PMK_LEN];
1117
1118 if (pw == NULL) {
1119 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1120 "found from external storage");
1121 return -1;
1122 }
1123
1124 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1125 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1126 "PSK length %d in external storage",
1127 (int) wpabuf_len(pw));
1128 ext_password_free(pw);
1129 return -1;
1130 }
1131
1132 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1133 pw_str[wpabuf_len(pw)] = '\0';
1134
1135#ifndef CONFIG_NO_PBKDF2
1136 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1137 {
1138 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1139 4096, psk, PMK_LEN);
1140 os_memset(pw_str, 0, sizeof(pw_str));
1141 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1142 "external passphrase)",
1143 psk, PMK_LEN);
1144 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1145 } else
1146#endif /* CONFIG_NO_PBKDF2 */
1147 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1148 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1149 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1150 "Invalid PSK hex string");
1151 os_memset(pw_str, 0, sizeof(pw_str));
1152 ext_password_free(pw);
1153 return -1;
1154 }
1155 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1156 } else {
1157 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1158 "PSK available");
1159 os_memset(pw_str, 0, sizeof(pw_str));
1160 ext_password_free(pw);
1161 return -1;
1162 }
1163
1164 os_memset(pw_str, 0, sizeof(pw_str));
1165 ext_password_free(pw);
1166 }
1167#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001168 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001169 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1170
1171 return 0;
1172}
1173
1174
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001175static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1176{
1177 *pos = 0x00;
1178
1179 switch (idx) {
1180 case 0: /* Bits 0-7 */
1181 break;
1182 case 1: /* Bits 8-15 */
1183 break;
1184 case 2: /* Bits 16-23 */
1185#ifdef CONFIG_WNM
1186 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1187 *pos |= 0x08; /* Bit 19 - BSS Transition */
1188#endif /* CONFIG_WNM */
1189 break;
1190 case 3: /* Bits 24-31 */
1191#ifdef CONFIG_WNM
1192 *pos |= 0x02; /* Bit 25 - SSID List */
1193#endif /* CONFIG_WNM */
1194#ifdef CONFIG_INTERWORKING
1195 if (wpa_s->conf->interworking)
1196 *pos |= 0x80; /* Bit 31 - Interworking */
1197#endif /* CONFIG_INTERWORKING */
1198 break;
1199 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001200#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001201 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1202 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001203#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001204 break;
1205 case 5: /* Bits 40-47 */
1206 break;
1207 case 6: /* Bits 48-55 */
1208 break;
1209 }
1210}
1211
1212
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001213int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1214{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001215 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001216 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001217
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001218 if (len < wpa_s->extended_capa_len)
1219 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001220
1221 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001222 *pos++ = len;
1223 for (i = 0; i < len; i++, pos++) {
1224 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001225
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001226 if (i < wpa_s->extended_capa_len) {
1227 *pos &= ~wpa_s->extended_capa_mask[i];
1228 *pos |= wpa_s->extended_capa[i];
1229 }
1230 }
1231
1232 while (len > 0 && buf[1 + len] == 0) {
1233 len--;
1234 buf[1] = len;
1235 }
1236 if (len == 0)
1237 return 0;
1238
1239 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001240}
1241
1242
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001243static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1244 struct wpa_bss *test_bss)
1245{
1246 struct wpa_bss *bss;
1247
1248 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1249 if (bss == test_bss)
1250 return 1;
1251 }
1252
1253 return 0;
1254}
1255
1256
1257static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1258 struct wpa_ssid *test_ssid)
1259{
1260 struct wpa_ssid *ssid;
1261
1262 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1263 if (ssid == test_ssid)
1264 return 1;
1265 }
1266
1267 return 0;
1268}
1269
1270
1271int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1272 struct wpa_ssid *test_ssid)
1273{
1274 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1275 return 0;
1276
1277 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1278}
1279
1280
1281void wpas_connect_work_free(struct wpa_connect_work *cwork)
1282{
1283 if (cwork == NULL)
1284 return;
1285 os_free(cwork);
1286}
1287
1288
1289void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1290{
1291 struct wpa_connect_work *cwork;
1292 struct wpa_radio_work *work = wpa_s->connect_work;
1293
1294 if (!work)
1295 return;
1296
1297 wpa_s->connect_work = NULL;
1298 cwork = work->ctx;
1299 work->ctx = NULL;
1300 wpas_connect_work_free(cwork);
1301 radio_work_done(work);
1302}
1303
1304
1305static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307/**
1308 * wpa_supplicant_associate - Request association
1309 * @wpa_s: Pointer to wpa_supplicant data
1310 * @bss: Scan results for the selected BSS, or %NULL if not available
1311 * @ssid: Configuration data for the selected network
1312 *
1313 * This function is used to request %wpa_supplicant to associate with a BSS.
1314 */
1315void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1316 struct wpa_bss *bss, struct wpa_ssid *ssid)
1317{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001318 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001319
1320#ifdef CONFIG_IBSS_RSN
1321 ibss_rsn_deinit(wpa_s->ibss_rsn);
1322 wpa_s->ibss_rsn = NULL;
1323#endif /* CONFIG_IBSS_RSN */
1324
1325 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1326 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1327#ifdef CONFIG_AP
1328 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1329 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1330 "mode");
1331 return;
1332 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001333 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1334 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001335 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1336 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001337 return;
1338 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001339 wpa_s->current_bss = bss;
1340#else /* CONFIG_AP */
1341 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1342 "the build");
1343#endif /* CONFIG_AP */
1344 return;
1345 }
1346
1347#ifdef CONFIG_TDLS
1348 if (bss)
1349 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1350 bss->ie_len);
1351#endif /* CONFIG_TDLS */
1352
1353 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1354 ssid->mode == IEEE80211_MODE_INFRA) {
1355 sme_authenticate(wpa_s, bss, ssid);
1356 return;
1357 }
1358
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001359 if (wpa_s->connect_work) {
1360 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1361 return;
1362 }
1363
1364 cwork = os_zalloc(sizeof(*cwork));
1365 if (cwork == NULL)
1366 return;
1367
1368 cwork->bss = bss;
1369 cwork->ssid = ssid;
1370
1371 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1372 wpas_start_assoc_cb, cwork) < 0) {
1373 os_free(cwork);
1374 }
1375}
1376
1377
1378static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1379{
1380 struct wpa_connect_work *cwork = work->ctx;
1381 struct wpa_bss *bss = cwork->bss;
1382 struct wpa_ssid *ssid = cwork->ssid;
1383 struct wpa_supplicant *wpa_s = work->wpa_s;
1384 u8 wpa_ie[200];
1385 size_t wpa_ie_len;
1386 int use_crypt, ret, i, bssid_changed;
1387 int algs = WPA_AUTH_ALG_OPEN;
1388 unsigned int cipher_pairwise, cipher_group;
1389 struct wpa_driver_associate_params params;
1390 int wep_keys_set = 0;
1391 int assoc_failed = 0;
1392 struct wpa_ssid *old_ssid;
1393#ifdef CONFIG_HT_OVERRIDES
1394 struct ieee80211_ht_capabilities htcaps;
1395 struct ieee80211_ht_capabilities htcaps_mask;
1396#endif /* CONFIG_HT_OVERRIDES */
1397
1398 if (deinit) {
1399 wpas_connect_work_free(cwork);
1400 return;
1401 }
1402
1403 wpa_s->connect_work = work;
1404
1405 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1406 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1407 wpas_connect_work_done(wpa_s);
1408 return;
1409 }
1410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001411 os_memset(&params, 0, sizeof(params));
1412 wpa_s->reassociate = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001413 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414#ifdef CONFIG_IEEE80211R
1415 const u8 *ie, *md = NULL;
1416#endif /* CONFIG_IEEE80211R */
1417 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1418 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1419 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1420 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1421 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1422 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1423 if (bssid_changed)
1424 wpas_notify_bssid_changed(wpa_s);
1425#ifdef CONFIG_IEEE80211R
1426 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1427 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1428 md = ie + 2;
1429 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1430 if (md) {
1431 /* Prepare for the next transition */
1432 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1433 }
1434#endif /* CONFIG_IEEE80211R */
1435#ifdef CONFIG_WPS
1436 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1437 wpa_s->conf->ap_scan == 2 &&
1438 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1439 /* Use ap_scan==1 style network selection to find the network
1440 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001441 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001442 wpa_s->reassociate = 1;
1443 wpa_supplicant_req_scan(wpa_s, 0, 0);
1444 return;
1445#endif /* CONFIG_WPS */
1446 } else {
1447 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1448 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1449 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1450 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001451 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001452 wpa_supplicant_cancel_scan(wpa_s);
1453
1454 /* Starting new association, so clear the possibly used WPA IE from the
1455 * previous association. */
1456 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1457
1458#ifdef IEEE8021X_EAPOL
1459 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1460 if (ssid->leap) {
1461 if (ssid->non_leap == 0)
1462 algs = WPA_AUTH_ALG_LEAP;
1463 else
1464 algs |= WPA_AUTH_ALG_LEAP;
1465 }
1466 }
1467#endif /* IEEE8021X_EAPOL */
1468 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1469 if (ssid->auth_alg) {
1470 algs = ssid->auth_alg;
1471 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1472 "0x%x", algs);
1473 }
1474
1475 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1476 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001477 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001479 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1480 wpa_s->conf->okc :
1481 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 (ssid->proto & WPA_PROTO_RSN);
1483 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001484 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001485 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1486 wpa_ie_len = sizeof(wpa_ie);
1487 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1488 wpa_ie, &wpa_ie_len)) {
1489 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1490 "key management and encryption suites");
1491 return;
1492 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001493 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1494 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1495 /*
1496 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1497 * use non-WPA since the scan results did not indicate that the
1498 * AP is using WPA or WPA2.
1499 */
1500 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1501 wpa_ie_len = 0;
1502 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001503 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001504 wpa_ie_len = sizeof(wpa_ie);
1505 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1506 wpa_ie, &wpa_ie_len)) {
1507 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1508 "key management and encryption suites (no "
1509 "scan results)");
1510 return;
1511 }
1512#ifdef CONFIG_WPS
1513 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1514 struct wpabuf *wps_ie;
1515 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1516 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1517 wpa_ie_len = wpabuf_len(wps_ie);
1518 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1519 } else
1520 wpa_ie_len = 0;
1521 wpabuf_free(wps_ie);
1522 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1523 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1524 params.wps = WPS_MODE_PRIVACY;
1525 else
1526 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001527 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001528#endif /* CONFIG_WPS */
1529 } else {
1530 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1531 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001532 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533 }
1534
1535#ifdef CONFIG_P2P
1536 if (wpa_s->global->p2p) {
1537 u8 *pos;
1538 size_t len;
1539 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001540 pos = wpa_ie + wpa_ie_len;
1541 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001542 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1543 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001544 if (res >= 0)
1545 wpa_ie_len += res;
1546 }
1547
1548 wpa_s->cross_connect_disallowed = 0;
1549 if (bss) {
1550 struct wpabuf *p2p;
1551 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1552 if (p2p) {
1553 wpa_s->cross_connect_disallowed =
1554 p2p_get_cross_connect_disallowed(p2p);
1555 wpabuf_free(p2p);
1556 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1557 "connection",
1558 wpa_s->cross_connect_disallowed ?
1559 "disallows" : "allows");
1560 }
1561 }
1562#endif /* CONFIG_P2P */
1563
Dmitry Shmidt04949592012-07-19 12:16:46 -07001564#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001565 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001566 struct wpabuf *hs20;
1567 hs20 = wpabuf_alloc(20);
1568 if (hs20) {
1569 wpas_hs20_add_indication(hs20);
1570 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1571 wpabuf_len(hs20));
1572 wpa_ie_len += wpabuf_len(hs20);
1573 wpabuf_free(hs20);
1574 }
1575 }
1576#endif /* CONFIG_HS20 */
1577
Dmitry Shmidt56052862013-10-04 10:23:25 -07001578 /*
1579 * Workaround: Add Extended Capabilities element only if the AP
1580 * included this element in Beacon/Probe Response frames. Some older
1581 * APs seem to have interoperability issues if this element is
1582 * included, so while the standard may require us to include the
1583 * element in all cases, it is justifiable to skip it to avoid
1584 * interoperability issues.
1585 */
1586 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1587 u8 ext_capab[10];
1588 int ext_capab_len;
1589 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1590 if (ext_capab_len > 0) {
1591 u8 *pos = wpa_ie;
1592 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1593 pos += 2 + pos[1];
1594 os_memmove(pos + ext_capab_len, pos,
1595 wpa_ie_len - (pos - wpa_ie));
1596 wpa_ie_len += ext_capab_len;
1597 os_memcpy(pos, ext_capab, ext_capab_len);
1598 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001599 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001601 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1602 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001603 cipher_pairwise = wpa_s->pairwise_cipher;
1604 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1606 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1607 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1608 use_crypt = 0;
1609 if (wpa_set_wep_keys(wpa_s, ssid)) {
1610 use_crypt = 1;
1611 wep_keys_set = 1;
1612 }
1613 }
1614 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1615 use_crypt = 0;
1616
1617#ifdef IEEE8021X_EAPOL
1618 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1619 if ((ssid->eapol_flags &
1620 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1621 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1622 !wep_keys_set) {
1623 use_crypt = 0;
1624 } else {
1625 /* Assume that dynamic WEP-104 keys will be used and
1626 * set cipher suites in order for drivers to expect
1627 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001628 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 }
1630 }
1631#endif /* IEEE8021X_EAPOL */
1632
1633 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1634 /* Set the key before (and later after) association */
1635 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1636 }
1637
1638 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1639 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001640 params.ssid = bss->ssid;
1641 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001642 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1643 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1644 MACSTR " freq=%u MHz based on scan results "
1645 "(bssid_set=%d)",
1646 MAC2STR(bss->bssid), bss->freq,
1647 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001648 params.bssid = bss->bssid;
1649 params.freq = bss->freq;
1650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001651 } else {
1652 params.ssid = ssid->ssid;
1653 params.ssid_len = ssid->ssid_len;
1654 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001655
1656 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1657 wpa_s->conf->ap_scan == 2) {
1658 params.bssid = ssid->bssid;
1659 params.fixed_bssid = 1;
1660 }
1661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001662 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1663 params.freq == 0)
1664 params.freq = ssid->frequency; /* Initial channel for IBSS */
1665 params.wpa_ie = wpa_ie;
1666 params.wpa_ie_len = wpa_ie_len;
1667 params.pairwise_suite = cipher_pairwise;
1668 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001669 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001670 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671 params.auth_alg = algs;
1672 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001673 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001674 for (i = 0; i < NUM_WEP_KEYS; i++) {
1675 if (ssid->wep_key_len[i])
1676 params.wep_key[i] = ssid->wep_key[i];
1677 params.wep_key_len[i] = ssid->wep_key_len[i];
1678 }
1679 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1680
1681 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001682 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1683 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001684 params.passphrase = ssid->passphrase;
1685 if (ssid->psk_set)
1686 params.psk = ssid->psk;
1687 }
1688
1689 params.drop_unencrypted = use_crypt;
1690
1691#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001692 params.mgmt_frame_protection =
1693 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1694 wpa_s->conf->pmf : ssid->ieee80211w;
1695 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001696 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1697 struct wpa_ie_data ie;
1698 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1699 ie.capabilities &
1700 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1701 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1702 "MFP: require MFP");
1703 params.mgmt_frame_protection =
1704 MGMT_FRAME_PROTECTION_REQUIRED;
1705 }
1706 }
1707#endif /* CONFIG_IEEE80211W */
1708
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001709 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001710
1711 if (wpa_s->parent->set_sta_uapsd)
1712 params.uapsd = wpa_s->parent->sta_uapsd;
1713 else
1714 params.uapsd = -1;
1715
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001716#ifdef CONFIG_HT_OVERRIDES
1717 os_memset(&htcaps, 0, sizeof(htcaps));
1718 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1719 params.htcaps = (u8 *) &htcaps;
1720 params.htcaps_mask = (u8 *) &htcaps_mask;
1721 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1722#endif /* CONFIG_HT_OVERRIDES */
1723
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001724#ifdef CONFIG_P2P
1725 /*
1726 * If multi-channel concurrency is not supported, check for any
1727 * frequency conflict. In case of any frequency conflict, remove the
1728 * least prioritized connection.
1729 */
1730 if (wpa_s->num_multichan_concurrent < 2) {
1731 int freq = wpa_drv_shared_freq(wpa_s);
1732 if (freq > 0 && freq != params.freq) {
1733 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1734 freq, params.freq);
1735 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1736 params.freq,
1737 ssid) < 0)
1738 return;
1739 }
1740 }
1741#endif /* CONFIG_P2P */
1742
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001743 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 if (ret < 0) {
1745 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1746 "failed");
1747 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1748 /*
1749 * The driver is known to mean what is saying, so we
1750 * can stop right here; the association will not
1751 * succeed.
1752 */
1753 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001754 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001755 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1756 return;
1757 }
1758 /* try to continue anyway; new association will be tried again
1759 * after timeout */
1760 assoc_failed = 1;
1761 }
1762
1763 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1764 /* Set the key after the association just in case association
1765 * cleared the previously configured key. */
1766 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1767 /* No need to timeout authentication since there is no key
1768 * management. */
1769 wpa_supplicant_cancel_auth_timeout(wpa_s);
1770 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1771#ifdef CONFIG_IBSS_RSN
1772 } else if (ssid->mode == WPAS_MODE_IBSS &&
1773 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1774 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1775 /*
1776 * RSN IBSS authentication is per-STA and we can disable the
1777 * per-BSSID authentication.
1778 */
1779 wpa_supplicant_cancel_auth_timeout(wpa_s);
1780#endif /* CONFIG_IBSS_RSN */
1781 } else {
1782 /* Timeout for IEEE 802.11 authentication and association */
1783 int timeout = 60;
1784
1785 if (assoc_failed) {
1786 /* give IBSS a bit more time */
1787 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1788 } else if (wpa_s->conf->ap_scan == 1) {
1789 /* give IBSS a bit more time */
1790 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1791 }
1792 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1793 }
1794
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001795 if (wep_keys_set &&
1796 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 /* Set static WEP keys again */
1798 wpa_set_wep_keys(wpa_s, ssid);
1799 }
1800
1801 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1802 /*
1803 * Do not allow EAP session resumption between different
1804 * network configurations.
1805 */
1806 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1807 }
1808 old_ssid = wpa_s->current_ssid;
1809 wpa_s->current_ssid = ssid;
1810 wpa_s->current_bss = bss;
1811 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1812 wpa_supplicant_initiate_eapol(wpa_s);
1813 if (old_ssid != wpa_s->current_ssid)
1814 wpas_notify_network_changed(wpa_s);
1815}
1816
1817
1818static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1819 const u8 *addr)
1820{
1821 struct wpa_ssid *old_ssid;
1822
1823 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001825 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 wpa_sm_set_config(wpa_s->wpa, NULL);
1827 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1828 if (old_ssid != wpa_s->current_ssid)
1829 wpas_notify_network_changed(wpa_s);
1830 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1831}
1832
1833
1834/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1836 * @wpa_s: Pointer to wpa_supplicant data
1837 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1838 *
1839 * This function is used to request %wpa_supplicant to deauthenticate from the
1840 * current AP.
1841 */
1842void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1843 int reason_code)
1844{
1845 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001846 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001847 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001849 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1850 " pending_bssid=" MACSTR " reason=%d state=%s",
1851 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1852 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1853
1854 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001855 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001856 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1857 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1858 wpa_s->wpa_state == WPA_ASSOCIATING))
1859 addr = wpa_s->pending_bssid;
1860 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1861 /*
1862 * When using driver-based BSS selection, we may not know the
1863 * BSSID with which we are currently trying to associate. We
1864 * need to notify the driver of this disconnection even in such
1865 * a case, so use the all zeros address here.
1866 */
1867 addr = wpa_s->bssid;
1868 zero_addr = 1;
1869 }
1870
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001871#ifdef CONFIG_TDLS
1872 wpa_tdls_teardown_peers(wpa_s->wpa);
1873#endif /* CONFIG_TDLS */
1874
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001875 if (addr) {
1876 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001877 os_memset(&event, 0, sizeof(event));
1878 event.deauth_info.reason_code = (u16) reason_code;
1879 event.deauth_info.locally_generated = 1;
1880 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001881 if (zero_addr)
1882 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001883 }
1884
1885 wpa_supplicant_clear_connection(wpa_s, addr);
1886}
1887
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001888static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1889 struct wpa_ssid *ssid)
1890{
1891 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1892 return;
1893
1894 ssid->disabled = 0;
1895 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1896 wpas_notify_network_enabled_changed(wpa_s, ssid);
1897
1898 /*
1899 * Try to reassociate since there is no current configuration and a new
1900 * network was made available.
1901 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001902 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001903 wpa_s->reassociate = 1;
1904}
1905
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906
1907/**
1908 * wpa_supplicant_enable_network - Mark a configured network as enabled
1909 * @wpa_s: wpa_supplicant structure for a network interface
1910 * @ssid: wpa_ssid structure for a configured network or %NULL
1911 *
1912 * Enables the specified network or all networks if no network specified.
1913 */
1914void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1915 struct wpa_ssid *ssid)
1916{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001917 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001918 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1919 wpa_supplicant_enable_one_network(wpa_s, ssid);
1920 } else
1921 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001923 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001924 if (wpa_s->sched_scanning) {
1925 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1926 "new network to scan filters");
1927 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928 }
1929
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001930 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1931 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932 }
1933}
1934
1935
1936/**
1937 * wpa_supplicant_disable_network - Mark a configured network as disabled
1938 * @wpa_s: wpa_supplicant structure for a network interface
1939 * @ssid: wpa_ssid structure for a configured network or %NULL
1940 *
1941 * Disables the specified network or all networks if no network specified.
1942 */
1943void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1944 struct wpa_ssid *ssid)
1945{
1946 struct wpa_ssid *other_ssid;
1947 int was_disabled;
1948
1949 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001950 if (wpa_s->sched_scanning)
1951 wpa_supplicant_cancel_sched_scan(wpa_s);
1952
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001953 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1954 other_ssid = other_ssid->next) {
1955 was_disabled = other_ssid->disabled;
1956 if (was_disabled == 2)
1957 continue; /* do not change persistent P2P group
1958 * data */
1959
1960 other_ssid->disabled = 1;
1961
1962 if (was_disabled != other_ssid->disabled)
1963 wpas_notify_network_enabled_changed(
1964 wpa_s, other_ssid);
1965 }
1966 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001967 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1969 } else if (ssid->disabled != 2) {
1970 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001971 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001972 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1973
1974 was_disabled = ssid->disabled;
1975
1976 ssid->disabled = 1;
1977
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001978 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001979 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001980 if (wpa_s->sched_scanning) {
1981 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1982 "to remove network from filters");
1983 wpa_supplicant_cancel_sched_scan(wpa_s);
1984 wpa_supplicant_req_scan(wpa_s, 0, 0);
1985 }
1986 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001987 }
1988}
1989
1990
1991/**
1992 * wpa_supplicant_select_network - Attempt association with a network
1993 * @wpa_s: wpa_supplicant structure for a network interface
1994 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1995 */
1996void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1997 struct wpa_ssid *ssid)
1998{
1999
2000 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002001 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002003 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002004 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002006 disconnected = 1;
2007 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002009 if (ssid)
2010 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2011
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012 /*
2013 * Mark all other networks disabled or mark all networks enabled if no
2014 * network specified.
2015 */
2016 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2017 other_ssid = other_ssid->next) {
2018 int was_disabled = other_ssid->disabled;
2019 if (was_disabled == 2)
2020 continue; /* do not change persistent P2P group data */
2021
2022 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002023 if (was_disabled && !other_ssid->disabled)
2024 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025
2026 if (was_disabled != other_ssid->disabled)
2027 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2028 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002029
2030 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2031 /* We are already associated with the selected network */
2032 wpa_printf(MSG_DEBUG, "Already associated with the "
2033 "selected network - do nothing");
2034 return;
2035 }
2036
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002037 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002038 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002039 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2040 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002041 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 wpa_s->disconnected = 0;
2043 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002044
2045 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2046 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047
2048 if (ssid)
2049 wpas_notify_network_selected(wpa_s, ssid);
2050}
2051
2052
2053/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002054 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2055 * @wpa_s: wpa_supplicant structure for a network interface
2056 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2057 * @pkcs11_module_path: PKCS #11 module path or NULL
2058 * Returns: 0 on success; -1 on failure
2059 *
2060 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2061 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2062 * module path fails the paths will be reset to the default value (NULL).
2063 */
2064int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2065 const char *pkcs11_engine_path,
2066 const char *pkcs11_module_path)
2067{
2068 char *pkcs11_engine_path_copy = NULL;
2069 char *pkcs11_module_path_copy = NULL;
2070
2071 if (pkcs11_engine_path != NULL) {
2072 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2073 if (pkcs11_engine_path_copy == NULL)
2074 return -1;
2075 }
2076 if (pkcs11_module_path != NULL) {
2077 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
2078 if (pkcs11_engine_path_copy == NULL) {
2079 os_free(pkcs11_engine_path_copy);
2080 return -1;
2081 }
2082 }
2083
2084 os_free(wpa_s->conf->pkcs11_engine_path);
2085 os_free(wpa_s->conf->pkcs11_module_path);
2086 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2087 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2088
2089 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2090 eapol_sm_deinit(wpa_s->eapol);
2091 wpa_s->eapol = NULL;
2092 if (wpa_supplicant_init_eapol(wpa_s)) {
2093 /* Error -> Reset paths to the default value (NULL) once. */
2094 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2095 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2096 NULL);
2097
2098 return -1;
2099 }
2100 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2101
2102 return 0;
2103}
2104
2105
2106/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2108 * @wpa_s: wpa_supplicant structure for a network interface
2109 * @ap_scan: AP scan mode
2110 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2111 *
2112 */
2113int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2114{
2115
2116 int old_ap_scan;
2117
2118 if (ap_scan < 0 || ap_scan > 2)
2119 return -1;
2120
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002121#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002122 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2123 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2124 wpa_s->wpa_state < WPA_COMPLETED) {
2125 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2126 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002127 return 0;
2128 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002129#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131 old_ap_scan = wpa_s->conf->ap_scan;
2132 wpa_s->conf->ap_scan = ap_scan;
2133
2134 if (old_ap_scan != wpa_s->conf->ap_scan)
2135 wpas_notify_ap_scan_changed(wpa_s);
2136
2137 return 0;
2138}
2139
2140
2141/**
2142 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2143 * @wpa_s: wpa_supplicant structure for a network interface
2144 * @expire_age: Expiration age in seconds
2145 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2146 *
2147 */
2148int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2149 unsigned int bss_expire_age)
2150{
2151 if (bss_expire_age < 10) {
2152 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2153 bss_expire_age);
2154 return -1;
2155 }
2156 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2157 bss_expire_age);
2158 wpa_s->conf->bss_expiration_age = bss_expire_age;
2159
2160 return 0;
2161}
2162
2163
2164/**
2165 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2166 * @wpa_s: wpa_supplicant structure for a network interface
2167 * @expire_count: number of scans after which an unseen BSS is reclaimed
2168 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2169 *
2170 */
2171int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2172 unsigned int bss_expire_count)
2173{
2174 if (bss_expire_count < 1) {
2175 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2176 bss_expire_count);
2177 return -1;
2178 }
2179 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2180 bss_expire_count);
2181 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2182
2183 return 0;
2184}
2185
2186
2187/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002188 * wpa_supplicant_set_scan_interval - Set scan interval
2189 * @wpa_s: wpa_supplicant structure for a network interface
2190 * @scan_interval: scan interval in seconds
2191 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2192 *
2193 */
2194int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2195 int scan_interval)
2196{
2197 if (scan_interval < 0) {
2198 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2199 scan_interval);
2200 return -1;
2201 }
2202 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2203 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002204 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002205
2206 return 0;
2207}
2208
2209
2210/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 * wpa_supplicant_set_debug_params - Set global debug params
2212 * @global: wpa_global structure
2213 * @debug_level: debug level
2214 * @debug_timestamp: determines if show timestamp in debug data
2215 * @debug_show_keys: determines if show keys in debug data
2216 * Returns: 0 if succeed or -1 if debug_level has wrong value
2217 */
2218int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2219 int debug_timestamp, int debug_show_keys)
2220{
2221
2222 int old_level, old_timestamp, old_show_keys;
2223
2224 /* check for allowed debuglevels */
2225 if (debug_level != MSG_EXCESSIVE &&
2226 debug_level != MSG_MSGDUMP &&
2227 debug_level != MSG_DEBUG &&
2228 debug_level != MSG_INFO &&
2229 debug_level != MSG_WARNING &&
2230 debug_level != MSG_ERROR)
2231 return -1;
2232
2233 old_level = wpa_debug_level;
2234 old_timestamp = wpa_debug_timestamp;
2235 old_show_keys = wpa_debug_show_keys;
2236
2237 wpa_debug_level = debug_level;
2238 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2239 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2240
2241 if (wpa_debug_level != old_level)
2242 wpas_notify_debug_level_changed(global);
2243 if (wpa_debug_timestamp != old_timestamp)
2244 wpas_notify_debug_timestamp_changed(global);
2245 if (wpa_debug_show_keys != old_show_keys)
2246 wpas_notify_debug_show_keys_changed(global);
2247
2248 return 0;
2249}
2250
2251
2252/**
2253 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2254 * @wpa_s: Pointer to wpa_supplicant data
2255 * Returns: A pointer to the current network structure or %NULL on failure
2256 */
2257struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2258{
2259 struct wpa_ssid *entry;
2260 u8 ssid[MAX_SSID_LEN];
2261 int res;
2262 size_t ssid_len;
2263 u8 bssid[ETH_ALEN];
2264 int wired;
2265
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002266 res = wpa_drv_get_ssid(wpa_s, ssid);
2267 if (res < 0) {
2268 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2269 "driver");
2270 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002272 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002273
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002274 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002275 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2276 "driver");
2277 return NULL;
2278 }
2279
2280 wired = wpa_s->conf->ap_scan == 0 &&
2281 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2282
2283 entry = wpa_s->conf->ssid;
2284 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002285 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286 ((ssid_len == entry->ssid_len &&
2287 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2288 (!entry->bssid_set ||
2289 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2290 return entry;
2291#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002292 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2294 (entry->ssid == NULL || entry->ssid_len == 0) &&
2295 (!entry->bssid_set ||
2296 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2297 return entry;
2298#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002299
Dmitry Shmidt04949592012-07-19 12:16:46 -07002300 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002301 entry->ssid_len == 0 &&
2302 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2303 return entry;
2304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002305 entry = entry->next;
2306 }
2307
2308 return NULL;
2309}
2310
2311
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002312static int select_driver(struct wpa_supplicant *wpa_s, int i)
2313{
2314 struct wpa_global *global = wpa_s->global;
2315
2316 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2317 global->drv_priv[i] = wpa_drivers[i]->global_init();
2318 if (global->drv_priv[i] == NULL) {
2319 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2320 "'%s'", wpa_drivers[i]->name);
2321 return -1;
2322 }
2323 }
2324
2325 wpa_s->driver = wpa_drivers[i];
2326 wpa_s->global_drv_priv = global->drv_priv[i];
2327
2328 return 0;
2329}
2330
2331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002332static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2333 const char *name)
2334{
2335 int i;
2336 size_t len;
2337 const char *pos, *driver = name;
2338
2339 if (wpa_s == NULL)
2340 return -1;
2341
2342 if (wpa_drivers[0] == NULL) {
2343 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2344 "wpa_supplicant");
2345 return -1;
2346 }
2347
2348 if (name == NULL) {
2349 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002350 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351 }
2352
2353 do {
2354 pos = os_strchr(driver, ',');
2355 if (pos)
2356 len = pos - driver;
2357 else
2358 len = os_strlen(driver);
2359
2360 for (i = 0; wpa_drivers[i]; i++) {
2361 if (os_strlen(wpa_drivers[i]->name) == len &&
2362 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002363 0) {
2364 /* First driver that succeeds wins */
2365 if (select_driver(wpa_s, i) == 0)
2366 return 0;
2367 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 }
2369
2370 driver = pos + 1;
2371 } while (pos);
2372
2373 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2374 return -1;
2375}
2376
2377
2378/**
2379 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2380 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2381 * with struct wpa_driver_ops::init()
2382 * @src_addr: Source address of the EAPOL frame
2383 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2384 * @len: Length of the EAPOL data
2385 *
2386 * This function is called for each received EAPOL frame. Most driver
2387 * interfaces rely on more generic OS mechanism for receiving frames through
2388 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2389 * take care of received EAPOL frames and deliver them to the core supplicant
2390 * code by calling this function.
2391 */
2392void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2393 const u8 *buf, size_t len)
2394{
2395 struct wpa_supplicant *wpa_s = ctx;
2396
2397 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2398 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2399
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002400#ifdef CONFIG_PEERKEY
2401 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2402 wpa_s->current_ssid->peerkey &&
2403 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2404 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2405 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2406 return;
2407 }
2408#endif /* CONFIG_PEERKEY */
2409
Jouni Malinena05074c2012-12-21 21:35:35 +02002410 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2411 (wpa_s->last_eapol_matches_bssid &&
2412#ifdef CONFIG_AP
2413 !wpa_s->ap_iface &&
2414#endif /* CONFIG_AP */
2415 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 /*
2417 * There is possible race condition between receiving the
2418 * association event and the EAPOL frame since they are coming
2419 * through different paths from the driver. In order to avoid
2420 * issues in trying to process the EAPOL frame before receiving
2421 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002422 * the association event is received. This may also be needed in
2423 * driver-based roaming case, so also use src_addr != BSSID as a
2424 * trigger if we have previously confirmed that the
2425 * Authenticator uses BSSID as the src_addr (which is not the
2426 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 */
2428 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002429 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2430 wpa_supplicant_state_txt(wpa_s->wpa_state),
2431 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 wpabuf_free(wpa_s->pending_eapol_rx);
2433 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2434 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002435 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2437 ETH_ALEN);
2438 }
2439 return;
2440 }
2441
Jouni Malinena05074c2012-12-21 21:35:35 +02002442 wpa_s->last_eapol_matches_bssid =
2443 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445#ifdef CONFIG_AP
2446 if (wpa_s->ap_iface) {
2447 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2448 return;
2449 }
2450#endif /* CONFIG_AP */
2451
2452 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2453 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2454 "no key management is configured");
2455 return;
2456 }
2457
2458 if (wpa_s->eapol_received == 0 &&
2459 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2460 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2461 wpa_s->wpa_state != WPA_COMPLETED) &&
2462 (wpa_s->current_ssid == NULL ||
2463 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2464 /* Timeout for completing IEEE 802.1X and WPA authentication */
2465 wpa_supplicant_req_auth_timeout(
2466 wpa_s,
2467 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2468 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2469 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2470 70 : 10, 0);
2471 }
2472 wpa_s->eapol_received++;
2473
2474 if (wpa_s->countermeasures) {
2475 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2476 "EAPOL packet");
2477 return;
2478 }
2479
2480#ifdef CONFIG_IBSS_RSN
2481 if (wpa_s->current_ssid &&
2482 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2483 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2484 return;
2485 }
2486#endif /* CONFIG_IBSS_RSN */
2487
2488 /* Source address of the incoming EAPOL frame could be compared to the
2489 * current BSSID. However, it is possible that a centralized
2490 * Authenticator could be using another MAC address than the BSSID of
2491 * an AP, so just allow any address to be used for now. The replies are
2492 * still sent to the current BSSID (if available), though. */
2493
2494 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2495 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2496 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2497 return;
2498 wpa_drv_poll(wpa_s);
2499 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2500 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2501 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2502 /*
2503 * Set portValid = TRUE here since we are going to skip 4-way
2504 * handshake processing which would normally set portValid. We
2505 * need this to allow the EAPOL state machines to be completed
2506 * without going through EAPOL-Key handshake.
2507 */
2508 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2509 }
2510}
2511
2512
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002513int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 if (wpa_s->driver->send_eapol) {
2516 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2517 if (addr)
2518 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002519 } else if ((!wpa_s->p2p_mgmt ||
2520 !(wpa_s->drv_flags &
2521 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2522 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002524 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2526 wpa_drv_get_mac_addr(wpa_s),
2527 ETH_P_EAPOL,
2528 wpa_supplicant_rx_eapol, wpa_s, 0);
2529 if (wpa_s->l2 == NULL)
2530 return -1;
2531 } else {
2532 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2533 if (addr)
2534 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2535 }
2536
2537 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2538 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2539 return -1;
2540 }
2541
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002542 return 0;
2543}
2544
2545
Dmitry Shmidt04949592012-07-19 12:16:46 -07002546static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2547 const u8 *buf, size_t len)
2548{
2549 struct wpa_supplicant *wpa_s = ctx;
2550 const struct l2_ethhdr *eth;
2551
2552 if (len < sizeof(*eth))
2553 return;
2554 eth = (const struct l2_ethhdr *) buf;
2555
2556 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2557 !(eth->h_dest[0] & 0x01)) {
2558 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2559 " (bridge - not for this interface - ignore)",
2560 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2561 return;
2562 }
2563
2564 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2565 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2566 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2567 len - sizeof(*eth));
2568}
2569
2570
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002571/**
2572 * wpa_supplicant_driver_init - Initialize driver interface parameters
2573 * @wpa_s: Pointer to wpa_supplicant data
2574 * Returns: 0 on success, -1 on failure
2575 *
2576 * This function is called to initialize driver interface parameters.
2577 * wpa_drv_init() must have been called before this function to initialize the
2578 * driver interface.
2579 */
2580int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2581{
2582 static int interface_count = 0;
2583
2584 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2585 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002587 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2588 MAC2STR(wpa_s->own_addr));
2589 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2590
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 if (wpa_s->bridge_ifname[0]) {
2592 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2593 "interface '%s'", wpa_s->bridge_ifname);
2594 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2595 wpa_s->own_addr,
2596 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002597 wpa_supplicant_rx_eapol_bridge,
2598 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 if (wpa_s->l2_br == NULL) {
2600 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2601 "connection for the bridge interface '%s'",
2602 wpa_s->bridge_ifname);
2603 return -1;
2604 }
2605 }
2606
2607 wpa_clear_keys(wpa_s, NULL);
2608
2609 /* Make sure that TKIP countermeasures are not left enabled (could
2610 * happen if wpa_supplicant is killed during countermeasures. */
2611 wpa_drv_set_countermeasures(wpa_s, 0);
2612
2613 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2614 wpa_drv_flush_pmkid(wpa_s);
2615
2616 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002617 wpa_s->prev_scan_wildcard = 0;
2618
Dmitry Shmidt04949592012-07-19 12:16:46 -07002619 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002620 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2621 100000))
2622 wpa_supplicant_req_scan(wpa_s, interface_count,
2623 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 interface_count++;
2625 } else
2626 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2627
2628 return 0;
2629}
2630
2631
2632static int wpa_supplicant_daemon(const char *pid_file)
2633{
2634 wpa_printf(MSG_DEBUG, "Daemonize..");
2635 return os_daemonize(pid_file);
2636}
2637
2638
2639static struct wpa_supplicant * wpa_supplicant_alloc(void)
2640{
2641 struct wpa_supplicant *wpa_s;
2642
2643 wpa_s = os_zalloc(sizeof(*wpa_s));
2644 if (wpa_s == NULL)
2645 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002646 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 wpa_s->scan_interval = 5;
2648 wpa_s->new_connection = 1;
2649 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002650 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651
2652 return wpa_s;
2653}
2654
2655
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002656#ifdef CONFIG_HT_OVERRIDES
2657
2658static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2659 struct ieee80211_ht_capabilities *htcaps,
2660 struct ieee80211_ht_capabilities *htcaps_mask,
2661 const char *ht_mcs)
2662{
2663 /* parse ht_mcs into hex array */
2664 int i;
2665 const char *tmp = ht_mcs;
2666 char *end = NULL;
2667
2668 /* If ht_mcs is null, do not set anything */
2669 if (!ht_mcs)
2670 return 0;
2671
2672 /* This is what we are setting in the kernel */
2673 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2674
2675 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2676
2677 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2678 errno = 0;
2679 long v = strtol(tmp, &end, 16);
2680 if (errno == 0) {
2681 wpa_msg(wpa_s, MSG_DEBUG,
2682 "htcap value[%i]: %ld end: %p tmp: %p",
2683 i, v, end, tmp);
2684 if (end == tmp)
2685 break;
2686
2687 htcaps->supported_mcs_set[i] = v;
2688 tmp = end;
2689 } else {
2690 wpa_msg(wpa_s, MSG_ERROR,
2691 "Failed to parse ht-mcs: %s, error: %s\n",
2692 ht_mcs, strerror(errno));
2693 return -1;
2694 }
2695 }
2696
2697 /*
2698 * If we were able to parse any values, then set mask for the MCS set.
2699 */
2700 if (i) {
2701 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2702 IEEE80211_HT_MCS_MASK_LEN - 1);
2703 /* skip the 3 reserved bits */
2704 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2705 0x1f;
2706 }
2707
2708 return 0;
2709}
2710
2711
2712static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2713 struct ieee80211_ht_capabilities *htcaps,
2714 struct ieee80211_ht_capabilities *htcaps_mask,
2715 int disabled)
2716{
2717 u16 msk;
2718
2719 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2720
2721 if (disabled == -1)
2722 return 0;
2723
2724 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2725 htcaps_mask->ht_capabilities_info |= msk;
2726 if (disabled)
2727 htcaps->ht_capabilities_info &= msk;
2728 else
2729 htcaps->ht_capabilities_info |= msk;
2730
2731 return 0;
2732}
2733
2734
2735static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2736 struct ieee80211_ht_capabilities *htcaps,
2737 struct ieee80211_ht_capabilities *htcaps_mask,
2738 int factor)
2739{
2740 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2741
2742 if (factor == -1)
2743 return 0;
2744
2745 if (factor < 0 || factor > 3) {
2746 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2747 "Must be 0-3 or -1", factor);
2748 return -EINVAL;
2749 }
2750
2751 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2752 htcaps->a_mpdu_params &= ~0x3;
2753 htcaps->a_mpdu_params |= factor & 0x3;
2754
2755 return 0;
2756}
2757
2758
2759static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2760 struct ieee80211_ht_capabilities *htcaps,
2761 struct ieee80211_ht_capabilities *htcaps_mask,
2762 int density)
2763{
2764 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2765
2766 if (density == -1)
2767 return 0;
2768
2769 if (density < 0 || density > 7) {
2770 wpa_msg(wpa_s, MSG_ERROR,
2771 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2772 density);
2773 return -EINVAL;
2774 }
2775
2776 htcaps_mask->a_mpdu_params |= 0x1C;
2777 htcaps->a_mpdu_params &= ~(0x1C);
2778 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2779
2780 return 0;
2781}
2782
2783
2784static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2785 struct ieee80211_ht_capabilities *htcaps,
2786 struct ieee80211_ht_capabilities *htcaps_mask,
2787 int disabled)
2788{
2789 /* Masking these out disables HT40 */
2790 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2791 HT_CAP_INFO_SHORT_GI40MHZ);
2792
2793 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2794
2795 if (disabled)
2796 htcaps->ht_capabilities_info &= ~msk;
2797 else
2798 htcaps->ht_capabilities_info |= msk;
2799
2800 htcaps_mask->ht_capabilities_info |= msk;
2801
2802 return 0;
2803}
2804
2805
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002806static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2807 struct ieee80211_ht_capabilities *htcaps,
2808 struct ieee80211_ht_capabilities *htcaps_mask,
2809 int disabled)
2810{
2811 /* Masking these out disables SGI */
2812 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2813 HT_CAP_INFO_SHORT_GI40MHZ);
2814
2815 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2816
2817 if (disabled)
2818 htcaps->ht_capabilities_info &= ~msk;
2819 else
2820 htcaps->ht_capabilities_info |= msk;
2821
2822 htcaps_mask->ht_capabilities_info |= msk;
2823
2824 return 0;
2825}
2826
2827
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002828void wpa_supplicant_apply_ht_overrides(
2829 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2830 struct wpa_driver_associate_params *params)
2831{
2832 struct ieee80211_ht_capabilities *htcaps;
2833 struct ieee80211_ht_capabilities *htcaps_mask;
2834
2835 if (!ssid)
2836 return;
2837
2838 params->disable_ht = ssid->disable_ht;
2839 if (!params->htcaps || !params->htcaps_mask)
2840 return;
2841
2842 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2843 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2844 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2845 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2846 ssid->disable_max_amsdu);
2847 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2848 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2849 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002850 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002851}
2852
2853#endif /* CONFIG_HT_OVERRIDES */
2854
2855
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002856#ifdef CONFIG_VHT_OVERRIDES
2857void wpa_supplicant_apply_vht_overrides(
2858 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2859 struct wpa_driver_associate_params *params)
2860{
2861 struct ieee80211_vht_capabilities *vhtcaps;
2862 struct ieee80211_vht_capabilities *vhtcaps_mask;
2863
2864 if (!ssid)
2865 return;
2866
2867 params->disable_vht = ssid->disable_vht;
2868
2869 vhtcaps = (void *) params->vhtcaps;
2870 vhtcaps_mask = (void *) params->vhtcaps_mask;
2871
2872 if (!vhtcaps || !vhtcaps_mask)
2873 return;
2874
2875 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2876 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2877
2878#define OVERRIDE_MCS(i) \
2879 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2880 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2881 3 << 2 * (i - 1); \
2882 vhtcaps->vht_supported_mcs_set.tx_map |= \
2883 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2884 } \
2885 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2886 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2887 3 << 2 * (i - 1); \
2888 vhtcaps->vht_supported_mcs_set.rx_map |= \
2889 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2890 }
2891
2892 OVERRIDE_MCS(1);
2893 OVERRIDE_MCS(2);
2894 OVERRIDE_MCS(3);
2895 OVERRIDE_MCS(4);
2896 OVERRIDE_MCS(5);
2897 OVERRIDE_MCS(6);
2898 OVERRIDE_MCS(7);
2899 OVERRIDE_MCS(8);
2900}
2901#endif /* CONFIG_VHT_OVERRIDES */
2902
2903
Dmitry Shmidt04949592012-07-19 12:16:46 -07002904static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2905{
2906#ifdef PCSC_FUNCS
2907 size_t len;
2908
2909 if (!wpa_s->conf->pcsc_reader)
2910 return 0;
2911
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002912 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002913 if (!wpa_s->scard)
2914 return 1;
2915
2916 if (wpa_s->conf->pcsc_pin &&
2917 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2918 scard_deinit(wpa_s->scard);
2919 wpa_s->scard = NULL;
2920 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2921 return -1;
2922 }
2923
2924 len = sizeof(wpa_s->imsi) - 1;
2925 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2926 scard_deinit(wpa_s->scard);
2927 wpa_s->scard = NULL;
2928 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2929 return -1;
2930 }
2931 wpa_s->imsi[len] = '\0';
2932
2933 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2934
2935 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2936 wpa_s->imsi, wpa_s->mnc_len);
2937
2938 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2939 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2940#endif /* PCSC_FUNCS */
2941
2942 return 0;
2943}
2944
2945
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002946int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2947{
2948 char *val, *pos;
2949
2950 ext_password_deinit(wpa_s->ext_pw);
2951 wpa_s->ext_pw = NULL;
2952 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2953
2954 if (!wpa_s->conf->ext_password_backend)
2955 return 0;
2956
2957 val = os_strdup(wpa_s->conf->ext_password_backend);
2958 if (val == NULL)
2959 return -1;
2960 pos = os_strchr(val, ':');
2961 if (pos)
2962 *pos++ = '\0';
2963
2964 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2965
2966 wpa_s->ext_pw = ext_password_init(val, pos);
2967 os_free(val);
2968 if (wpa_s->ext_pw == NULL) {
2969 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2970 return -1;
2971 }
2972 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2973
2974 return 0;
2975}
2976
2977
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002978static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2979 const char *rn)
2980{
2981 struct wpa_supplicant *iface = wpa_s->global->ifaces;
2982 struct wpa_radio *radio;
2983
2984 while (rn && iface) {
2985 radio = iface->radio;
2986 if (radio && os_strcmp(rn, radio->name) == 0) {
2987 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
2988 wpa_s->ifname, rn);
2989 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
2990 return radio;
2991 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08002992
2993 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002994 }
2995
2996 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
2997 wpa_s->ifname, rn ? rn : "N/A");
2998 radio = os_zalloc(sizeof(*radio));
2999 if (radio == NULL)
3000 return NULL;
3001
3002 if (rn)
3003 os_strlcpy(radio->name, rn, sizeof(radio->name));
3004 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003005 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003006 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3007
3008 return radio;
3009}
3010
3011
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003012static void radio_work_free(struct wpa_radio_work *work)
3013{
3014 if (work->wpa_s->scan_work == work) {
3015 /* This should not really happen. */
3016 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3017 work->type, work, work->started);
3018 work->wpa_s->scan_work = NULL;
3019 }
3020
3021#ifdef CONFIG_P2P
3022 if (work->wpa_s->p2p_scan_work == work) {
3023 /* This should not really happen. */
3024 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3025 work->type, work, work->started);
3026 work->wpa_s->p2p_scan_work = NULL;
3027 }
3028#endif /* CONFIG_P2P */
3029
3030 dl_list_del(&work->list);
3031 os_free(work);
3032}
3033
3034
3035static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3036{
3037 struct wpa_radio *radio = eloop_ctx;
3038 struct wpa_radio_work *work;
3039 struct os_reltime now, diff;
3040 struct wpa_supplicant *wpa_s;
3041
3042 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3043 if (work == NULL)
3044 return;
3045
3046 if (work->started)
3047 return; /* already started and still in progress */
3048
3049 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3050 radio_list);
3051 if (wpa_s && wpa_s->external_scan_running) {
3052 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3053 return;
3054 }
3055
3056 os_get_reltime(&now);
3057 os_reltime_sub(&now, &work->time, &diff);
3058 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3059 work->type, work, diff.sec, diff.usec);
3060 work->started = 1;
3061 work->time = now;
3062 work->cb(work, 0);
3063}
3064
3065
3066void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
3067{
3068 struct wpa_radio_work *work, *tmp;
3069 struct wpa_radio *radio = wpa_s->radio;
3070
3071 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3072 list) {
3073 if (type && (work->started || os_strcmp(type, work->type) != 0))
3074 continue;
3075 if (work->started) {
3076 wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
3077 work->type, work);
3078 continue;
3079 }
3080 wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
3081 work->type, work);
3082 work->cb(work, 1);
3083 radio_work_free(work);
3084 }
3085}
3086
3087
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003088static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3089{
3090 struct wpa_radio *radio = wpa_s->radio;
3091
3092 if (!radio)
3093 return;
3094
3095 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3096 wpa_s->ifname, radio->name);
3097 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003098 if (!dl_list_empty(&radio->ifaces)) {
3099 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003100 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003101 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003102
3103 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003104 radio_remove_unstarted_work(wpa_s, NULL);
3105 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3106 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003107 os_free(radio);
3108}
3109
3110
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003111void radio_work_check_next(struct wpa_supplicant *wpa_s)
3112{
3113 struct wpa_radio *radio = wpa_s->radio;
3114
3115 if (dl_list_empty(&radio->work))
3116 return;
3117 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3118 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3119}
3120
3121
3122/**
3123 * radio_add_work - Add a radio work item
3124 * @wpa_s: Pointer to wpa_supplicant data
3125 * @freq: Frequency of the offchannel operation in MHz or 0
3126 * @type: Unique identifier for each type of work
3127 * @next: Force as the next work to be executed
3128 * @cb: Callback function for indicating when radio is available
3129 * @ctx: Context pointer for the work (work->ctx in cb())
3130 * Returns: 0 on success, -1 on failure
3131 *
3132 * This function is used to request time for an operation that requires
3133 * exclusive radio control. Once the radio is available, the registered callback
3134 * function will be called. radio_work_done() must be called once the exclusive
3135 * radio operation has been completed, so that the radio is freed for other
3136 * operations. The special case of deinit=1 is used to free the context data
3137 * during interface removal. That does not allow the callback function to start
3138 * the radio operation, i.e., it must free any resources allocated for the radio
3139 * work and return.
3140 *
3141 * The @freq parameter can be used to indicate a single channel on which the
3142 * offchannel operation will occur. This may allow multiple radio work
3143 * operations to be performed in parallel if they apply for the same channel.
3144 * Setting this to 0 indicates that the work item may use multiple channels or
3145 * requires exclusive control of the radio.
3146 */
3147int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3148 const char *type, int next,
3149 void (*cb)(struct wpa_radio_work *work, int deinit),
3150 void *ctx)
3151{
3152 struct wpa_radio_work *work;
3153 int was_empty;
3154
3155 work = os_zalloc(sizeof(*work));
3156 if (work == NULL)
3157 return -1;
3158 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3159 os_get_reltime(&work->time);
3160 work->freq = freq;
3161 work->type = type;
3162 work->wpa_s = wpa_s;
3163 work->cb = cb;
3164 work->ctx = ctx;
3165
3166 was_empty = dl_list_empty(&wpa_s->radio->work);
3167 if (next)
3168 dl_list_add(&wpa_s->radio->work, &work->list);
3169 else
3170 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3171 if (was_empty) {
3172 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3173 radio_work_check_next(wpa_s);
3174 }
3175
3176 return 0;
3177}
3178
3179
3180/**
3181 * radio_work_done - Indicate that a radio work item has been completed
3182 * @work: Completed work
3183 *
3184 * This function is called once the callback function registered with
3185 * radio_add_work() has completed its work.
3186 */
3187void radio_work_done(struct wpa_radio_work *work)
3188{
3189 struct wpa_supplicant *wpa_s = work->wpa_s;
3190 struct os_reltime now, diff;
3191 unsigned int started = work->started;
3192
3193 os_get_reltime(&now);
3194 os_reltime_sub(&now, &work->time, &diff);
3195 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3196 work->type, work, started ? "done" : "canceled",
3197 diff.sec, diff.usec);
3198 radio_work_free(work);
3199 if (started)
3200 radio_work_check_next(wpa_s);
3201}
3202
3203
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003204static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3205 struct wpa_interface *iface)
3206{
3207 const char *ifname, *driver, *rn;
3208
3209 driver = iface->driver;
3210next_driver:
3211 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3212 return -1;
3213
3214 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3215 if (wpa_s->drv_priv == NULL) {
3216 const char *pos;
3217 pos = driver ? os_strchr(driver, ',') : NULL;
3218 if (pos) {
3219 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3220 "driver interface - try next driver wrapper");
3221 driver = pos + 1;
3222 goto next_driver;
3223 }
3224 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3225 "interface");
3226 return -1;
3227 }
3228 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3229 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3230 "driver_param '%s'", wpa_s->conf->driver_param);
3231 return -1;
3232 }
3233
3234 ifname = wpa_drv_get_ifname(wpa_s);
3235 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3236 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3237 "interface name with '%s'", ifname);
3238 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3239 }
3240
3241 if (wpa_s->driver->get_radio_name)
3242 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3243 else
3244 rn = NULL;
3245 if (rn && rn[0] == '\0')
3246 rn = NULL;
3247
3248 wpa_s->radio = radio_add_interface(wpa_s, rn);
3249 if (wpa_s->radio == NULL)
3250 return -1;
3251
3252 return 0;
3253}
3254
3255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003256static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3257 struct wpa_interface *iface)
3258{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003259 struct wpa_driver_capa capa;
3260
3261 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3262 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3263 iface->confname ? iface->confname : "N/A",
3264 iface->driver ? iface->driver : "default",
3265 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3266 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3267
3268 if (iface->confname) {
3269#ifdef CONFIG_BACKEND_FILE
3270 wpa_s->confname = os_rel2abs_path(iface->confname);
3271 if (wpa_s->confname == NULL) {
3272 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3273 "for configuration file '%s'.",
3274 iface->confname);
3275 return -1;
3276 }
3277 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3278 iface->confname, wpa_s->confname);
3279#else /* CONFIG_BACKEND_FILE */
3280 wpa_s->confname = os_strdup(iface->confname);
3281#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003282 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003283 if (wpa_s->conf == NULL) {
3284 wpa_printf(MSG_ERROR, "Failed to read or parse "
3285 "configuration '%s'.", wpa_s->confname);
3286 return -1;
3287 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003288 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3289 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290
3291 /*
3292 * Override ctrl_interface and driver_param if set on command
3293 * line.
3294 */
3295 if (iface->ctrl_interface) {
3296 os_free(wpa_s->conf->ctrl_interface);
3297 wpa_s->conf->ctrl_interface =
3298 os_strdup(iface->ctrl_interface);
3299 }
3300
3301 if (iface->driver_param) {
3302 os_free(wpa_s->conf->driver_param);
3303 wpa_s->conf->driver_param =
3304 os_strdup(iface->driver_param);
3305 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003306
3307 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3308 os_free(wpa_s->conf->ctrl_interface);
3309 wpa_s->conf->ctrl_interface = NULL;
3310 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 } else
3312 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3313 iface->driver_param);
3314
3315 if (wpa_s->conf == NULL) {
3316 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3317 return -1;
3318 }
3319
3320 if (iface->ifname == NULL) {
3321 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3322 return -1;
3323 }
3324 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3325 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3326 iface->ifname);
3327 return -1;
3328 }
3329 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3330
3331 if (iface->bridge_ifname) {
3332 if (os_strlen(iface->bridge_ifname) >=
3333 sizeof(wpa_s->bridge_ifname)) {
3334 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3335 "name '%s'.", iface->bridge_ifname);
3336 return -1;
3337 }
3338 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3339 sizeof(wpa_s->bridge_ifname));
3340 }
3341
3342 /* RSNA Supplicant Key Management - INITIALIZE */
3343 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3344 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3345
3346 /* Initialize driver interface and register driver event handler before
3347 * L2 receive handler so that association events are processed before
3348 * EAPOL-Key packets if both become available for the same select()
3349 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003350 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003351 return -1;
3352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003353 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3354 return -1;
3355
3356 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3357 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3358 NULL);
3359 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3360
3361 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3362 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3363 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3364 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3365 "dot11RSNAConfigPMKLifetime");
3366 return -1;
3367 }
3368
3369 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3370 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3371 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3372 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3373 "dot11RSNAConfigPMKReauthThreshold");
3374 return -1;
3375 }
3376
3377 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3378 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3379 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3380 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3381 "dot11RSNAConfigSATimeout");
3382 return -1;
3383 }
3384
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003385 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3386 &wpa_s->hw.num_modes,
3387 &wpa_s->hw.flags);
3388
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003389 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003390 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003391 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003392 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003393 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003394 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003395 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3396 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3397 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003398 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3399 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003400 wpa_s->extended_capa = capa.extended_capa;
3401 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3402 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003403 wpa_s->num_multichan_concurrent =
3404 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405 }
3406 if (wpa_s->max_remain_on_chan == 0)
3407 wpa_s->max_remain_on_chan = 1000;
3408
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003409 /*
3410 * Only take p2p_mgmt parameters when P2P Device is supported.
3411 * Doing it here as it determines whether l2_packet_init() will be done
3412 * during wpa_supplicant_driver_init().
3413 */
3414 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3415 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3416 else
3417 iface->p2p_mgmt = 1;
3418
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003419 if (wpa_s->num_multichan_concurrent == 0)
3420 wpa_s->num_multichan_concurrent = 1;
3421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422 if (wpa_supplicant_driver_init(wpa_s) < 0)
3423 return -1;
3424
3425#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003426 if ((!iface->p2p_mgmt ||
3427 !(wpa_s->drv_flags &
3428 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3429 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003430 return -1;
3431#endif /* CONFIG_TDLS */
3432
3433 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3434 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3435 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3436 return -1;
3437 }
3438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439 if (wpas_wps_init(wpa_s))
3440 return -1;
3441
3442 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3443 return -1;
3444 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3445
3446 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3447 if (wpa_s->ctrl_iface == NULL) {
3448 wpa_printf(MSG_ERROR,
3449 "Failed to initialize control interface '%s'.\n"
3450 "You may have another wpa_supplicant process "
3451 "already running or the file was\n"
3452 "left by an unclean termination of wpa_supplicant "
3453 "in which case you will need\n"
3454 "to manually remove this file before starting "
3455 "wpa_supplicant again.\n",
3456 wpa_s->conf->ctrl_interface);
3457 return -1;
3458 }
3459
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003460 wpa_s->gas = gas_query_init(wpa_s);
3461 if (wpa_s->gas == NULL) {
3462 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3463 return -1;
3464 }
3465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003467 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3469 return -1;
3470 }
3471#endif /* CONFIG_P2P */
3472
3473 if (wpa_bss_init(wpa_s) < 0)
3474 return -1;
3475
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003476#ifdef CONFIG_EAP_PROXY
3477{
3478 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003479 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3480 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003481 if (wpa_s->mnc_len > 0) {
3482 wpa_s->imsi[len] = '\0';
3483 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3484 wpa_s->imsi, wpa_s->mnc_len);
3485 } else {
3486 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3487 }
3488}
3489#endif /* CONFIG_EAP_PROXY */
3490
Dmitry Shmidt04949592012-07-19 12:16:46 -07003491 if (pcsc_reader_init(wpa_s) < 0)
3492 return -1;
3493
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003494 if (wpas_init_ext_pw(wpa_s) < 0)
3495 return -1;
3496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003497 return 0;
3498}
3499
3500
3501static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003502 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003503{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003504 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003505 if (wpa_s->drv_priv) {
3506 wpa_supplicant_deauthenticate(wpa_s,
3507 WLAN_REASON_DEAUTH_LEAVING);
3508
3509 wpa_drv_set_countermeasures(wpa_s, 0);
3510 wpa_clear_keys(wpa_s, NULL);
3511 }
3512
3513 wpa_supplicant_cleanup(wpa_s);
3514
Dmitry Shmidt04949592012-07-19 12:16:46 -07003515#ifdef CONFIG_P2P
3516 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3517 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3518 "the management interface is being removed");
3519 wpas_p2p_deinit_global(wpa_s->global);
3520 }
3521#endif /* CONFIG_P2P */
3522
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003523 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003524 radio_remove_interface(wpa_s);
3525
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003526 if (wpa_s->drv_priv)
3527 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003528
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003529 if (notify)
3530 wpas_notify_iface_removed(wpa_s);
3531
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003532 if (terminate)
3533 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003534
3535 if (wpa_s->ctrl_iface) {
3536 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3537 wpa_s->ctrl_iface = NULL;
3538 }
3539
3540 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003541 wpa_config_free(wpa_s->conf);
3542 wpa_s->conf = NULL;
3543 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003544
3545 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546}
3547
3548
3549/**
3550 * wpa_supplicant_add_iface - Add a new network interface
3551 * @global: Pointer to global data from wpa_supplicant_init()
3552 * @iface: Interface configuration options
3553 * Returns: Pointer to the created interface or %NULL on failure
3554 *
3555 * This function is used to add new network interfaces for %wpa_supplicant.
3556 * This can be called before wpa_supplicant_run() to add interfaces before the
3557 * main event loop has been started. In addition, new interfaces can be added
3558 * dynamically while %wpa_supplicant is already running. This could happen,
3559 * e.g., when a hotplug network adapter is inserted.
3560 */
3561struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3562 struct wpa_interface *iface)
3563{
3564 struct wpa_supplicant *wpa_s;
3565 struct wpa_interface t_iface;
3566 struct wpa_ssid *ssid;
3567
3568 if (global == NULL || iface == NULL)
3569 return NULL;
3570
3571 wpa_s = wpa_supplicant_alloc();
3572 if (wpa_s == NULL)
3573 return NULL;
3574
3575 wpa_s->global = global;
3576
3577 t_iface = *iface;
3578 if (global->params.override_driver) {
3579 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3580 "('%s' -> '%s')",
3581 iface->driver, global->params.override_driver);
3582 t_iface.driver = global->params.override_driver;
3583 }
3584 if (global->params.override_ctrl_interface) {
3585 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3586 "ctrl_interface ('%s' -> '%s')",
3587 iface->ctrl_interface,
3588 global->params.override_ctrl_interface);
3589 t_iface.ctrl_interface =
3590 global->params.override_ctrl_interface;
3591 }
3592 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3593 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3594 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003595 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596 return NULL;
3597 }
3598
3599 /* Notify the control interfaces about new iface */
3600 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003601 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003602 return NULL;
3603 }
3604
3605 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3606 wpas_notify_network_added(wpa_s, ssid);
3607
3608 wpa_s->next = global->ifaces;
3609 global->ifaces = wpa_s;
3610
3611 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003612 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613
3614 return wpa_s;
3615}
3616
3617
3618/**
3619 * wpa_supplicant_remove_iface - Remove a network interface
3620 * @global: Pointer to global data from wpa_supplicant_init()
3621 * @wpa_s: Pointer to the network interface to be removed
3622 * Returns: 0 if interface was removed, -1 if interface was not found
3623 *
3624 * This function can be used to dynamically remove network interfaces from
3625 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3626 * addition, this function is used to remove all remaining interfaces when
3627 * %wpa_supplicant is terminated.
3628 */
3629int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003630 struct wpa_supplicant *wpa_s,
3631 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632{
3633 struct wpa_supplicant *prev;
3634
3635 /* Remove interface from the global list of interfaces */
3636 prev = global->ifaces;
3637 if (prev == wpa_s) {
3638 global->ifaces = wpa_s->next;
3639 } else {
3640 while (prev && prev->next != wpa_s)
3641 prev = prev->next;
3642 if (prev == NULL)
3643 return -1;
3644 prev->next = wpa_s->next;
3645 }
3646
3647 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3648
3649 if (global->p2p_group_formation == wpa_s)
3650 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003651 if (global->p2p_invite_group == wpa_s)
3652 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003653 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654
3655 return 0;
3656}
3657
3658
3659/**
3660 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3661 * @wpa_s: Pointer to the network interface
3662 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3663 */
3664const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3665{
3666 const char *eapol_method;
3667
3668 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3669 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3670 return "NO-EAP";
3671 }
3672
3673 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3674 if (eapol_method == NULL)
3675 return "UNKNOWN-EAP";
3676
3677 return eapol_method;
3678}
3679
3680
3681/**
3682 * wpa_supplicant_get_iface - Get a new network interface
3683 * @global: Pointer to global data from wpa_supplicant_init()
3684 * @ifname: Interface name
3685 * Returns: Pointer to the interface or %NULL if not found
3686 */
3687struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3688 const char *ifname)
3689{
3690 struct wpa_supplicant *wpa_s;
3691
3692 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3693 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3694 return wpa_s;
3695 }
3696 return NULL;
3697}
3698
3699
3700#ifndef CONFIG_NO_WPA_MSG
3701static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3702{
3703 struct wpa_supplicant *wpa_s = ctx;
3704 if (wpa_s == NULL)
3705 return NULL;
3706 return wpa_s->ifname;
3707}
3708#endif /* CONFIG_NO_WPA_MSG */
3709
3710
3711/**
3712 * wpa_supplicant_init - Initialize %wpa_supplicant
3713 * @params: Parameters for %wpa_supplicant
3714 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3715 *
3716 * This function is used to initialize %wpa_supplicant. After successful
3717 * initialization, the returned data pointer can be used to add and remove
3718 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3719 */
3720struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3721{
3722 struct wpa_global *global;
3723 int ret, i;
3724
3725 if (params == NULL)
3726 return NULL;
3727
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003728#ifdef CONFIG_DRIVER_NDIS
3729 {
3730 void driver_ndis_init_ops(void);
3731 driver_ndis_init_ops();
3732 }
3733#endif /* CONFIG_DRIVER_NDIS */
3734
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003735#ifndef CONFIG_NO_WPA_MSG
3736 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3737#endif /* CONFIG_NO_WPA_MSG */
3738
3739 wpa_debug_open_file(params->wpa_debug_file_path);
3740 if (params->wpa_debug_syslog)
3741 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003742 if (params->wpa_debug_tracing) {
3743 ret = wpa_debug_open_linux_tracing();
3744 if (ret) {
3745 wpa_printf(MSG_ERROR,
3746 "Failed to enable trace logging");
3747 return NULL;
3748 }
3749 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750
3751 ret = eap_register_methods();
3752 if (ret) {
3753 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3754 if (ret == -2)
3755 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3756 "the same EAP type.");
3757 return NULL;
3758 }
3759
3760 global = os_zalloc(sizeof(*global));
3761 if (global == NULL)
3762 return NULL;
3763 dl_list_init(&global->p2p_srv_bonjour);
3764 dl_list_init(&global->p2p_srv_upnp);
3765 global->params.daemonize = params->daemonize;
3766 global->params.wait_for_monitor = params->wait_for_monitor;
3767 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3768 if (params->pid_file)
3769 global->params.pid_file = os_strdup(params->pid_file);
3770 if (params->ctrl_interface)
3771 global->params.ctrl_interface =
3772 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003773 if (params->ctrl_interface_group)
3774 global->params.ctrl_interface_group =
3775 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 if (params->override_driver)
3777 global->params.override_driver =
3778 os_strdup(params->override_driver);
3779 if (params->override_ctrl_interface)
3780 global->params.override_ctrl_interface =
3781 os_strdup(params->override_ctrl_interface);
3782 wpa_debug_level = global->params.wpa_debug_level =
3783 params->wpa_debug_level;
3784 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3785 params->wpa_debug_show_keys;
3786 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3787 params->wpa_debug_timestamp;
3788
3789 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3790
3791 if (eloop_init()) {
3792 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3793 wpa_supplicant_deinit(global);
3794 return NULL;
3795 }
3796
Jouni Malinen75ecf522011-06-27 15:19:46 -07003797 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798
3799 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3800 if (global->ctrl_iface == NULL) {
3801 wpa_supplicant_deinit(global);
3802 return NULL;
3803 }
3804
3805 if (wpas_notify_supplicant_initialized(global)) {
3806 wpa_supplicant_deinit(global);
3807 return NULL;
3808 }
3809
3810 for (i = 0; wpa_drivers[i]; i++)
3811 global->drv_count++;
3812 if (global->drv_count == 0) {
3813 wpa_printf(MSG_ERROR, "No drivers enabled");
3814 wpa_supplicant_deinit(global);
3815 return NULL;
3816 }
3817 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3818 if (global->drv_priv == NULL) {
3819 wpa_supplicant_deinit(global);
3820 return NULL;
3821 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003822
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003823#ifdef CONFIG_WIFI_DISPLAY
3824 if (wifi_display_init(global) < 0) {
3825 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3826 wpa_supplicant_deinit(global);
3827 return NULL;
3828 }
3829#endif /* CONFIG_WIFI_DISPLAY */
3830
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003831 return global;
3832}
3833
3834
3835/**
3836 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3837 * @global: Pointer to global data from wpa_supplicant_init()
3838 * Returns: 0 after successful event loop run, -1 on failure
3839 *
3840 * This function starts the main event loop and continues running as long as
3841 * there are any remaining events. In most cases, this function is running as
3842 * long as the %wpa_supplicant process in still in use.
3843 */
3844int wpa_supplicant_run(struct wpa_global *global)
3845{
3846 struct wpa_supplicant *wpa_s;
3847
3848 if (global->params.daemonize &&
3849 wpa_supplicant_daemon(global->params.pid_file))
3850 return -1;
3851
3852 if (global->params.wait_for_monitor) {
3853 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3854 if (wpa_s->ctrl_iface)
3855 wpa_supplicant_ctrl_iface_wait(
3856 wpa_s->ctrl_iface);
3857 }
3858
3859 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3860 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3861
3862 eloop_run();
3863
3864 return 0;
3865}
3866
3867
3868/**
3869 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3870 * @global: Pointer to global data from wpa_supplicant_init()
3871 *
3872 * This function is called to deinitialize %wpa_supplicant and to free all
3873 * allocated resources. Remaining network interfaces will also be removed.
3874 */
3875void wpa_supplicant_deinit(struct wpa_global *global)
3876{
3877 int i;
3878
3879 if (global == NULL)
3880 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003881
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003882#ifdef CONFIG_WIFI_DISPLAY
3883 wifi_display_deinit(global);
3884#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003885
3886 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003887 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003888
3889 if (global->ctrl_iface)
3890 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3891
3892 wpas_notify_supplicant_deinitialized(global);
3893
3894 eap_peer_unregister_methods();
3895#ifdef CONFIG_AP
3896 eap_server_unregister_methods();
3897#endif /* CONFIG_AP */
3898
3899 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3900 if (!global->drv_priv[i])
3901 continue;
3902 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3903 }
3904 os_free(global->drv_priv);
3905
3906 random_deinit();
3907
3908 eloop_destroy();
3909
3910 if (global->params.pid_file) {
3911 os_daemonize_terminate(global->params.pid_file);
3912 os_free(global->params.pid_file);
3913 }
3914 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003915 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 os_free(global->params.override_driver);
3917 os_free(global->params.override_ctrl_interface);
3918
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003919 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003920 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003921
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003922 os_free(global);
3923 wpa_debug_close_syslog();
3924 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003925 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003926}
3927
3928
3929void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3930{
3931 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3932 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3933 char country[3];
3934 country[0] = wpa_s->conf->country[0];
3935 country[1] = wpa_s->conf->country[1];
3936 country[2] = '\0';
3937 if (wpa_drv_set_country(wpa_s, country) < 0) {
3938 wpa_printf(MSG_ERROR, "Failed to set country code "
3939 "'%s'", country);
3940 }
3941 }
3942
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003943 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3944 wpas_init_ext_pw(wpa_s);
3945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946#ifdef CONFIG_WPS
3947 wpas_wps_update_config(wpa_s);
3948#endif /* CONFIG_WPS */
3949
3950#ifdef CONFIG_P2P
3951 wpas_p2p_update_config(wpa_s);
3952#endif /* CONFIG_P2P */
3953
3954 wpa_s->conf->changed_parameters = 0;
3955}
3956
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958static void add_freq(int *freqs, int *num_freqs, int freq)
3959{
3960 int i;
3961
3962 for (i = 0; i < *num_freqs; i++) {
3963 if (freqs[i] == freq)
3964 return;
3965 }
3966
3967 freqs[*num_freqs] = freq;
3968 (*num_freqs)++;
3969}
3970
3971
3972static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3973{
3974 struct wpa_bss *bss, *cbss;
3975 const int max_freqs = 10;
3976 int *freqs;
3977 int num_freqs = 0;
3978
3979 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3980 if (freqs == NULL)
3981 return NULL;
3982
3983 cbss = wpa_s->current_bss;
3984
3985 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3986 if (bss == cbss)
3987 continue;
3988 if (bss->ssid_len == cbss->ssid_len &&
3989 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3990 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3991 add_freq(freqs, &num_freqs, bss->freq);
3992 if (num_freqs == max_freqs)
3993 break;
3994 }
3995 }
3996
3997 if (num_freqs == 0) {
3998 os_free(freqs);
3999 freqs = NULL;
4000 }
4001
4002 return freqs;
4003}
4004
4005
4006void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4007{
4008 int timeout;
4009 int count;
4010 int *freqs = NULL;
4011
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004012 wpas_connect_work_done(wpa_s);
4013
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004014 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004015 * Remove possible authentication timeout since the connection failed.
4016 */
4017 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4018
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004019 if (wpa_s->disconnected) {
4020 /*
4021 * There is no point in blacklisting the AP if this event is
4022 * generated based on local request to disconnect.
4023 */
4024 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4025 "indication since interface has been put into "
4026 "disconnected state");
4027 return;
4028 }
4029
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004030 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031 * Add the failed BSSID into the blacklist and speed up next scan
4032 * attempt if there could be other APs that could accept association.
4033 * The current blacklist count indicates how many times we have tried
4034 * connecting to this AP and multiple attempts mean that other APs are
4035 * either not available or has already been tried, so that we can start
4036 * increasing the delay here to avoid constant scanning.
4037 */
4038 count = wpa_blacklist_add(wpa_s, bssid);
4039 if (count == 1 && wpa_s->current_bss) {
4040 /*
4041 * This BSS was not in the blacklist before. If there is
4042 * another BSS available for the same ESS, we should try that
4043 * next. Otherwise, we may as well try this one once more
4044 * before allowing other, likely worse, ESSes to be considered.
4045 */
4046 freqs = get_bss_freqs_in_ess(wpa_s);
4047 if (freqs) {
4048 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4049 "has been seen; try it next");
4050 wpa_blacklist_add(wpa_s, bssid);
4051 /*
4052 * On the next scan, go through only the known channels
4053 * used in this ESS based on previous scans to speed up
4054 * common load balancing use case.
4055 */
4056 os_free(wpa_s->next_scan_freqs);
4057 wpa_s->next_scan_freqs = freqs;
4058 }
4059 }
4060
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004061 /*
4062 * Add previous failure count in case the temporary blacklist was
4063 * cleared due to no other BSSes being available.
4064 */
4065 count += wpa_s->extra_blacklist_count;
4066
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004067 if (count > 3 && wpa_s->current_ssid) {
4068 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4069 "consider temporary network disabling");
4070 wpas_auth_failed(wpa_s);
4071 }
4072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 switch (count) {
4074 case 1:
4075 timeout = 100;
4076 break;
4077 case 2:
4078 timeout = 500;
4079 break;
4080 case 3:
4081 timeout = 1000;
4082 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004083 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004084 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004085 break;
4086 default:
4087 timeout = 10000;
4088 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004089 }
4090
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004091 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4092 "ms", count, timeout);
4093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094 /*
4095 * TODO: if more than one possible AP is available in scan results,
4096 * could try the other ones before requesting a new scan.
4097 */
4098 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4099 1000 * (timeout % 1000));
4100}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004101
4102
4103int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4104{
4105 return wpa_s->conf->ap_scan == 2 ||
4106 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4107}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004108
Dmitry Shmidt04949592012-07-19 12:16:46 -07004109
4110#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4111int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4112 struct wpa_ssid *ssid,
4113 const char *field,
4114 const char *value)
4115{
4116#ifdef IEEE8021X_EAPOL
4117 struct eap_peer_config *eap = &ssid->eap;
4118
4119 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4120 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4121 (const u8 *) value, os_strlen(value));
4122
4123 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4124 case WPA_CTRL_REQ_EAP_IDENTITY:
4125 os_free(eap->identity);
4126 eap->identity = (u8 *) os_strdup(value);
4127 eap->identity_len = os_strlen(value);
4128 eap->pending_req_identity = 0;
4129 if (ssid == wpa_s->current_ssid)
4130 wpa_s->reassociate = 1;
4131 break;
4132 case WPA_CTRL_REQ_EAP_PASSWORD:
4133 os_free(eap->password);
4134 eap->password = (u8 *) os_strdup(value);
4135 eap->password_len = os_strlen(value);
4136 eap->pending_req_password = 0;
4137 if (ssid == wpa_s->current_ssid)
4138 wpa_s->reassociate = 1;
4139 break;
4140 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4141 os_free(eap->new_password);
4142 eap->new_password = (u8 *) os_strdup(value);
4143 eap->new_password_len = os_strlen(value);
4144 eap->pending_req_new_password = 0;
4145 if (ssid == wpa_s->current_ssid)
4146 wpa_s->reassociate = 1;
4147 break;
4148 case WPA_CTRL_REQ_EAP_PIN:
4149 os_free(eap->pin);
4150 eap->pin = os_strdup(value);
4151 eap->pending_req_pin = 0;
4152 if (ssid == wpa_s->current_ssid)
4153 wpa_s->reassociate = 1;
4154 break;
4155 case WPA_CTRL_REQ_EAP_OTP:
4156 os_free(eap->otp);
4157 eap->otp = (u8 *) os_strdup(value);
4158 eap->otp_len = os_strlen(value);
4159 os_free(eap->pending_req_otp);
4160 eap->pending_req_otp = NULL;
4161 eap->pending_req_otp_len = 0;
4162 break;
4163 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4164 os_free(eap->private_key_passwd);
4165 eap->private_key_passwd = (u8 *) os_strdup(value);
4166 eap->pending_req_passphrase = 0;
4167 if (ssid == wpa_s->current_ssid)
4168 wpa_s->reassociate = 1;
4169 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004170 case WPA_CTRL_REQ_SIM:
4171 os_free(eap->external_sim_resp);
4172 eap->external_sim_resp = os_strdup(value);
4173 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004174 default:
4175 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4176 return -1;
4177 }
4178
4179 return 0;
4180#else /* IEEE8021X_EAPOL */
4181 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4182 return -1;
4183#endif /* IEEE8021X_EAPOL */
4184}
4185#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4186
4187
4188int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4189{
4190 int i;
4191 unsigned int drv_enc;
4192
4193 if (ssid == NULL)
4194 return 1;
4195
4196 if (ssid->disabled)
4197 return 1;
4198
4199 if (wpa_s && wpa_s->drv_capa_known)
4200 drv_enc = wpa_s->drv_enc;
4201 else
4202 drv_enc = (unsigned int) -1;
4203
4204 for (i = 0; i < NUM_WEP_KEYS; i++) {
4205 size_t len = ssid->wep_key_len[i];
4206 if (len == 0)
4207 continue;
4208 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4209 continue;
4210 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4211 continue;
4212 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4213 continue;
4214 return 1; /* invalid WEP key */
4215 }
4216
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004217 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4218 !ssid->ext_psk)
4219 return 1;
4220
Dmitry Shmidt04949592012-07-19 12:16:46 -07004221 return 0;
4222}
4223
4224
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004225int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004226{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004227 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004228 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004229 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004230 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004231 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004232}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004233
4234
4235void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4236{
4237 struct wpa_ssid *ssid = wpa_s->current_ssid;
4238 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004239 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004240
4241 if (ssid == NULL) {
4242 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4243 "SSID block");
4244 return;
4245 }
4246
4247 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4248 return;
4249
4250 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004251
4252#ifdef CONFIG_P2P
4253 if (ssid->p2p_group &&
4254 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4255 /*
4256 * Skip the wait time since there is a short timeout on the
4257 * connection to a P2P group.
4258 */
4259 return;
4260 }
4261#endif /* CONFIG_P2P */
4262
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004263 if (ssid->auth_failures > 50)
4264 dur = 300;
4265 else if (ssid->auth_failures > 20)
4266 dur = 120;
4267 else if (ssid->auth_failures > 10)
4268 dur = 60;
4269 else if (ssid->auth_failures > 5)
4270 dur = 30;
4271 else if (ssid->auth_failures > 1)
4272 dur = 20;
4273 else
4274 dur = 10;
4275
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004276 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004277 if (now.sec + dur <= ssid->disabled_until.sec)
4278 return;
4279
4280 ssid->disabled_until.sec = now.sec + dur;
4281
4282 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4283 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4284 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4285 ssid->auth_failures, dur);
4286}
4287
4288
4289void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4290 struct wpa_ssid *ssid, int clear_failures)
4291{
4292 if (ssid == NULL)
4293 return;
4294
4295 if (ssid->disabled_until.sec) {
4296 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4297 "id=%d ssid=\"%s\"",
4298 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4299 }
4300 ssid->disabled_until.sec = 0;
4301 ssid->disabled_until.usec = 0;
4302 if (clear_failures)
4303 ssid->auth_failures = 0;
4304}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004305
4306
4307int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4308{
4309 size_t i;
4310
4311 if (wpa_s->disallow_aps_bssid == NULL)
4312 return 0;
4313
4314 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4315 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4316 bssid, ETH_ALEN) == 0)
4317 return 1;
4318 }
4319
4320 return 0;
4321}
4322
4323
4324int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4325 size_t ssid_len)
4326{
4327 size_t i;
4328
4329 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4330 return 0;
4331
4332 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4333 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4334 if (ssid_len == s->ssid_len &&
4335 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4336 return 1;
4337 }
4338
4339 return 0;
4340}
4341
4342
4343/**
4344 * wpas_request_connection - Request a new connection
4345 * @wpa_s: Pointer to the network interface
4346 *
4347 * This function is used to request a new connection to be found. It will mark
4348 * the interface to allow reassociation and request a new scan to find a
4349 * suitable network to connect to.
4350 */
4351void wpas_request_connection(struct wpa_supplicant *wpa_s)
4352{
4353 wpa_s->normal_scans = 0;
4354 wpa_supplicant_reinit_autoscan(wpa_s);
4355 wpa_s->extra_blacklist_count = 0;
4356 wpa_s->disconnected = 0;
4357 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004358
4359 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4360 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004361}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004362
4363
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004364void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4365 int *freq_array, unsigned int len)
4366{
4367 unsigned int i;
4368
4369 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4370 len, title);
4371 for (i = 0; i < len; i++)
4372 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4373}
4374
4375
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004376/*
4377 * Find the operating frequencies of any of the virtual interfaces that
4378 * are using the same radio as the current interface.
4379 */
4380int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4381 int *freq_array, unsigned int len)
4382{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004383 struct wpa_supplicant *ifs;
4384 u8 bssid[ETH_ALEN];
4385 int freq;
4386 unsigned int idx = 0, i;
4387
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004388 wpa_dbg(wpa_s, MSG_DEBUG,
4389 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004390 os_memset(freq_array, 0, sizeof(int) * len);
4391
4392 /* First add the frequency of the local interface */
4393 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4394 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4395 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4396 freq_array[idx++] = wpa_s->current_ssid->frequency;
4397 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4398 freq_array[idx++] = wpa_s->assoc_freq;
4399 }
4400
4401 /* If get_radio_name is not supported, use only the local freq */
4402 if (!wpa_s->driver->get_radio_name) {
4403 freq = wpa_drv_shared_freq(wpa_s);
4404 if (freq > 0 && idx < len &&
4405 (idx == 0 || freq_array[0] != freq))
4406 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004407 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004408 return idx;
4409 }
4410
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004411 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4412 radio_list) {
4413 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004414 continue;
4415
4416 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4417 continue;
4418
4419 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4420 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4421 freq = ifs->current_ssid->frequency;
4422 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4423 freq = ifs->assoc_freq;
4424 else
4425 continue;
4426
4427 /* Hold only distinct freqs */
4428 for (i = 0; i < idx; i++)
4429 if (freq_array[i] == freq)
4430 break;
4431
4432 if (i == idx)
4433 freq_array[idx++] = freq;
4434 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004435
4436 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004437 return idx;
4438}