blob: 78e274979df2a452abcf4a26f20ac12663591c71 [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 Shmidt344abd32014-01-14 13:17:00 -08001413 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001414 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415#ifdef CONFIG_IEEE80211R
1416 const u8 *ie, *md = NULL;
1417#endif /* CONFIG_IEEE80211R */
1418 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1419 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1420 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1421 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1422 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1423 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1424 if (bssid_changed)
1425 wpas_notify_bssid_changed(wpa_s);
1426#ifdef CONFIG_IEEE80211R
1427 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1428 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1429 md = ie + 2;
1430 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1431 if (md) {
1432 /* Prepare for the next transition */
1433 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1434 }
1435#endif /* CONFIG_IEEE80211R */
1436#ifdef CONFIG_WPS
1437 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1438 wpa_s->conf->ap_scan == 2 &&
1439 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1440 /* Use ap_scan==1 style network selection to find the network
1441 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001442 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001443 wpa_s->reassociate = 1;
1444 wpa_supplicant_req_scan(wpa_s, 0, 0);
1445 return;
1446#endif /* CONFIG_WPS */
1447 } else {
1448 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1449 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1450 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1451 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001452 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001453 wpa_supplicant_cancel_scan(wpa_s);
1454
1455 /* Starting new association, so clear the possibly used WPA IE from the
1456 * previous association. */
1457 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1458
1459#ifdef IEEE8021X_EAPOL
1460 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1461 if (ssid->leap) {
1462 if (ssid->non_leap == 0)
1463 algs = WPA_AUTH_ALG_LEAP;
1464 else
1465 algs |= WPA_AUTH_ALG_LEAP;
1466 }
1467 }
1468#endif /* IEEE8021X_EAPOL */
1469 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1470 if (ssid->auth_alg) {
1471 algs = ssid->auth_alg;
1472 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1473 "0x%x", algs);
1474 }
1475
1476 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1477 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001478 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001479 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001480 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1481 wpa_s->conf->okc :
1482 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001483 (ssid->proto & WPA_PROTO_RSN);
1484 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001485 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1487 wpa_ie_len = sizeof(wpa_ie);
1488 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1489 wpa_ie, &wpa_ie_len)) {
1490 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1491 "key management and encryption suites");
1492 return;
1493 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001494 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1495 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1496 /*
1497 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1498 * use non-WPA since the scan results did not indicate that the
1499 * AP is using WPA or WPA2.
1500 */
1501 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1502 wpa_ie_len = 0;
1503 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001504 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001505 wpa_ie_len = sizeof(wpa_ie);
1506 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1507 wpa_ie, &wpa_ie_len)) {
1508 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1509 "key management and encryption suites (no "
1510 "scan results)");
1511 return;
1512 }
1513#ifdef CONFIG_WPS
1514 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1515 struct wpabuf *wps_ie;
1516 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1517 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1518 wpa_ie_len = wpabuf_len(wps_ie);
1519 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1520 } else
1521 wpa_ie_len = 0;
1522 wpabuf_free(wps_ie);
1523 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1524 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1525 params.wps = WPS_MODE_PRIVACY;
1526 else
1527 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001528 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529#endif /* CONFIG_WPS */
1530 } else {
1531 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1532 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001533 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534 }
1535
1536#ifdef CONFIG_P2P
1537 if (wpa_s->global->p2p) {
1538 u8 *pos;
1539 size_t len;
1540 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001541 pos = wpa_ie + wpa_ie_len;
1542 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001543 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1544 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545 if (res >= 0)
1546 wpa_ie_len += res;
1547 }
1548
1549 wpa_s->cross_connect_disallowed = 0;
1550 if (bss) {
1551 struct wpabuf *p2p;
1552 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1553 if (p2p) {
1554 wpa_s->cross_connect_disallowed =
1555 p2p_get_cross_connect_disallowed(p2p);
1556 wpabuf_free(p2p);
1557 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1558 "connection",
1559 wpa_s->cross_connect_disallowed ?
1560 "disallows" : "allows");
1561 }
1562 }
1563#endif /* CONFIG_P2P */
1564
Dmitry Shmidt04949592012-07-19 12:16:46 -07001565#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001566 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001567 struct wpabuf *hs20;
1568 hs20 = wpabuf_alloc(20);
1569 if (hs20) {
1570 wpas_hs20_add_indication(hs20);
1571 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1572 wpabuf_len(hs20));
1573 wpa_ie_len += wpabuf_len(hs20);
1574 wpabuf_free(hs20);
1575 }
1576 }
1577#endif /* CONFIG_HS20 */
1578
Dmitry Shmidt56052862013-10-04 10:23:25 -07001579 /*
1580 * Workaround: Add Extended Capabilities element only if the AP
1581 * included this element in Beacon/Probe Response frames. Some older
1582 * APs seem to have interoperability issues if this element is
1583 * included, so while the standard may require us to include the
1584 * element in all cases, it is justifiable to skip it to avoid
1585 * interoperability issues.
1586 */
1587 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1588 u8 ext_capab[10];
1589 int ext_capab_len;
1590 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1591 if (ext_capab_len > 0) {
1592 u8 *pos = wpa_ie;
1593 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1594 pos += 2 + pos[1];
1595 os_memmove(pos + ext_capab_len, pos,
1596 wpa_ie_len - (pos - wpa_ie));
1597 wpa_ie_len += ext_capab_len;
1598 os_memcpy(pos, ext_capab, ext_capab_len);
1599 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001600 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001601
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001602 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1603 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001604 cipher_pairwise = wpa_s->pairwise_cipher;
1605 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001606 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1607 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1608 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1609 use_crypt = 0;
1610 if (wpa_set_wep_keys(wpa_s, ssid)) {
1611 use_crypt = 1;
1612 wep_keys_set = 1;
1613 }
1614 }
1615 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1616 use_crypt = 0;
1617
1618#ifdef IEEE8021X_EAPOL
1619 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1620 if ((ssid->eapol_flags &
1621 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1622 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1623 !wep_keys_set) {
1624 use_crypt = 0;
1625 } else {
1626 /* Assume that dynamic WEP-104 keys will be used and
1627 * set cipher suites in order for drivers to expect
1628 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001629 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 }
1631 }
1632#endif /* IEEE8021X_EAPOL */
1633
1634 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1635 /* Set the key before (and later after) association */
1636 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1637 }
1638
1639 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1640 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 params.ssid = bss->ssid;
1642 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001643 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1644 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1645 MACSTR " freq=%u MHz based on scan results "
1646 "(bssid_set=%d)",
1647 MAC2STR(bss->bssid), bss->freq,
1648 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001649 params.bssid = bss->bssid;
1650 params.freq = bss->freq;
1651 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 } else {
1653 params.ssid = ssid->ssid;
1654 params.ssid_len = ssid->ssid_len;
1655 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001656
1657 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1658 wpa_s->conf->ap_scan == 2) {
1659 params.bssid = ssid->bssid;
1660 params.fixed_bssid = 1;
1661 }
1662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001663 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1664 params.freq == 0)
1665 params.freq = ssid->frequency; /* Initial channel for IBSS */
1666 params.wpa_ie = wpa_ie;
1667 params.wpa_ie_len = wpa_ie_len;
1668 params.pairwise_suite = cipher_pairwise;
1669 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001670 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001671 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 params.auth_alg = algs;
1673 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001674 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001675 for (i = 0; i < NUM_WEP_KEYS; i++) {
1676 if (ssid->wep_key_len[i])
1677 params.wep_key[i] = ssid->wep_key[i];
1678 params.wep_key_len[i] = ssid->wep_key_len[i];
1679 }
1680 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1681
1682 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001683 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1684 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001685 params.passphrase = ssid->passphrase;
1686 if (ssid->psk_set)
1687 params.psk = ssid->psk;
1688 }
1689
1690 params.drop_unencrypted = use_crypt;
1691
1692#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001693 params.mgmt_frame_protection =
1694 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1695 wpa_s->conf->pmf : ssid->ieee80211w;
1696 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001697 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1698 struct wpa_ie_data ie;
1699 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1700 ie.capabilities &
1701 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1702 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1703 "MFP: require MFP");
1704 params.mgmt_frame_protection =
1705 MGMT_FRAME_PROTECTION_REQUIRED;
1706 }
1707 }
1708#endif /* CONFIG_IEEE80211W */
1709
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001710 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001711
1712 if (wpa_s->parent->set_sta_uapsd)
1713 params.uapsd = wpa_s->parent->sta_uapsd;
1714 else
1715 params.uapsd = -1;
1716
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001717#ifdef CONFIG_HT_OVERRIDES
1718 os_memset(&htcaps, 0, sizeof(htcaps));
1719 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1720 params.htcaps = (u8 *) &htcaps;
1721 params.htcaps_mask = (u8 *) &htcaps_mask;
1722 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1723#endif /* CONFIG_HT_OVERRIDES */
1724
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001725#ifdef CONFIG_P2P
1726 /*
1727 * If multi-channel concurrency is not supported, check for any
1728 * frequency conflict. In case of any frequency conflict, remove the
1729 * least prioritized connection.
1730 */
1731 if (wpa_s->num_multichan_concurrent < 2) {
1732 int freq = wpa_drv_shared_freq(wpa_s);
1733 if (freq > 0 && freq != params.freq) {
1734 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1735 freq, params.freq);
1736 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1737 params.freq,
1738 ssid) < 0)
1739 return;
1740 }
1741 }
1742#endif /* CONFIG_P2P */
1743
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001744 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745 if (ret < 0) {
1746 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1747 "failed");
1748 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1749 /*
1750 * The driver is known to mean what is saying, so we
1751 * can stop right here; the association will not
1752 * succeed.
1753 */
1754 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001755 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001756 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1757 return;
1758 }
1759 /* try to continue anyway; new association will be tried again
1760 * after timeout */
1761 assoc_failed = 1;
1762 }
1763
1764 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1765 /* Set the key after the association just in case association
1766 * cleared the previously configured key. */
1767 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1768 /* No need to timeout authentication since there is no key
1769 * management. */
1770 wpa_supplicant_cancel_auth_timeout(wpa_s);
1771 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1772#ifdef CONFIG_IBSS_RSN
1773 } else if (ssid->mode == WPAS_MODE_IBSS &&
1774 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1775 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1776 /*
1777 * RSN IBSS authentication is per-STA and we can disable the
1778 * per-BSSID authentication.
1779 */
1780 wpa_supplicant_cancel_auth_timeout(wpa_s);
1781#endif /* CONFIG_IBSS_RSN */
1782 } else {
1783 /* Timeout for IEEE 802.11 authentication and association */
1784 int timeout = 60;
1785
1786 if (assoc_failed) {
1787 /* give IBSS a bit more time */
1788 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1789 } else if (wpa_s->conf->ap_scan == 1) {
1790 /* give IBSS a bit more time */
1791 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1792 }
1793 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1794 }
1795
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001796 if (wep_keys_set &&
1797 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001798 /* Set static WEP keys again */
1799 wpa_set_wep_keys(wpa_s, ssid);
1800 }
1801
1802 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1803 /*
1804 * Do not allow EAP session resumption between different
1805 * network configurations.
1806 */
1807 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1808 }
1809 old_ssid = wpa_s->current_ssid;
1810 wpa_s->current_ssid = ssid;
1811 wpa_s->current_bss = bss;
1812 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1813 wpa_supplicant_initiate_eapol(wpa_s);
1814 if (old_ssid != wpa_s->current_ssid)
1815 wpas_notify_network_changed(wpa_s);
1816}
1817
1818
1819static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1820 const u8 *addr)
1821{
1822 struct wpa_ssid *old_ssid;
1823
1824 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001825 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001826 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 wpa_sm_set_config(wpa_s->wpa, NULL);
1828 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1829 if (old_ssid != wpa_s->current_ssid)
1830 wpas_notify_network_changed(wpa_s);
1831 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1832}
1833
1834
1835/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1837 * @wpa_s: Pointer to wpa_supplicant data
1838 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1839 *
1840 * This function is used to request %wpa_supplicant to deauthenticate from the
1841 * current AP.
1842 */
1843void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1844 int reason_code)
1845{
1846 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001847 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001848 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001850 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1851 " pending_bssid=" MACSTR " reason=%d state=%s",
1852 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1853 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1854
1855 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001857 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1858 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1859 wpa_s->wpa_state == WPA_ASSOCIATING))
1860 addr = wpa_s->pending_bssid;
1861 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1862 /*
1863 * When using driver-based BSS selection, we may not know the
1864 * BSSID with which we are currently trying to associate. We
1865 * need to notify the driver of this disconnection even in such
1866 * a case, so use the all zeros address here.
1867 */
1868 addr = wpa_s->bssid;
1869 zero_addr = 1;
1870 }
1871
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001872#ifdef CONFIG_TDLS
1873 wpa_tdls_teardown_peers(wpa_s->wpa);
1874#endif /* CONFIG_TDLS */
1875
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001876 if (addr) {
1877 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001878 os_memset(&event, 0, sizeof(event));
1879 event.deauth_info.reason_code = (u16) reason_code;
1880 event.deauth_info.locally_generated = 1;
1881 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001882 if (zero_addr)
1883 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 }
1885
1886 wpa_supplicant_clear_connection(wpa_s, addr);
1887}
1888
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001889static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1890 struct wpa_ssid *ssid)
1891{
1892 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1893 return;
1894
1895 ssid->disabled = 0;
1896 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1897 wpas_notify_network_enabled_changed(wpa_s, ssid);
1898
1899 /*
1900 * Try to reassociate since there is no current configuration and a new
1901 * network was made available.
1902 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001903 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001904 wpa_s->reassociate = 1;
1905}
1906
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907
1908/**
1909 * wpa_supplicant_enable_network - Mark a configured network as enabled
1910 * @wpa_s: wpa_supplicant structure for a network interface
1911 * @ssid: wpa_ssid structure for a configured network or %NULL
1912 *
1913 * Enables the specified network or all networks if no network specified.
1914 */
1915void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1916 struct wpa_ssid *ssid)
1917{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001918 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001919 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1920 wpa_supplicant_enable_one_network(wpa_s, ssid);
1921 } else
1922 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001924 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001925 if (wpa_s->sched_scanning) {
1926 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1927 "new network to scan filters");
1928 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001929 }
1930
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001931 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1932 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 }
1934}
1935
1936
1937/**
1938 * wpa_supplicant_disable_network - Mark a configured network as disabled
1939 * @wpa_s: wpa_supplicant structure for a network interface
1940 * @ssid: wpa_ssid structure for a configured network or %NULL
1941 *
1942 * Disables the specified network or all networks if no network specified.
1943 */
1944void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1945 struct wpa_ssid *ssid)
1946{
1947 struct wpa_ssid *other_ssid;
1948 int was_disabled;
1949
1950 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001951 if (wpa_s->sched_scanning)
1952 wpa_supplicant_cancel_sched_scan(wpa_s);
1953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001954 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1955 other_ssid = other_ssid->next) {
1956 was_disabled = other_ssid->disabled;
1957 if (was_disabled == 2)
1958 continue; /* do not change persistent P2P group
1959 * data */
1960
1961 other_ssid->disabled = 1;
1962
1963 if (was_disabled != other_ssid->disabled)
1964 wpas_notify_network_enabled_changed(
1965 wpa_s, other_ssid);
1966 }
1967 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001968 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1970 } else if (ssid->disabled != 2) {
1971 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001972 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1974
1975 was_disabled = ssid->disabled;
1976
1977 ssid->disabled = 1;
1978
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001979 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001981 if (wpa_s->sched_scanning) {
1982 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1983 "to remove network from filters");
1984 wpa_supplicant_cancel_sched_scan(wpa_s);
1985 wpa_supplicant_req_scan(wpa_s, 0, 0);
1986 }
1987 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988 }
1989}
1990
1991
1992/**
1993 * wpa_supplicant_select_network - Attempt association with a network
1994 * @wpa_s: wpa_supplicant structure for a network interface
1995 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
1996 */
1997void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
1998 struct wpa_ssid *ssid)
1999{
2000
2001 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002002 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002003
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002004 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002005 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002006 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002007 disconnected = 1;
2008 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002010 if (ssid)
2011 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2012
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 /*
2014 * Mark all other networks disabled or mark all networks enabled if no
2015 * network specified.
2016 */
2017 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2018 other_ssid = other_ssid->next) {
2019 int was_disabled = other_ssid->disabled;
2020 if (was_disabled == 2)
2021 continue; /* do not change persistent P2P group data */
2022
2023 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002024 if (was_disabled && !other_ssid->disabled)
2025 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002026
2027 if (was_disabled != other_ssid->disabled)
2028 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2029 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002030
2031 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2032 /* We are already associated with the selected network */
2033 wpa_printf(MSG_DEBUG, "Already associated with the "
2034 "selected network - do nothing");
2035 return;
2036 }
2037
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002038 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002039 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002040 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2041 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002042 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 wpa_s->disconnected = 0;
2044 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002045
2046 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2047 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048
2049 if (ssid)
2050 wpas_notify_network_selected(wpa_s, ssid);
2051}
2052
2053
2054/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002055 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2056 * @wpa_s: wpa_supplicant structure for a network interface
2057 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2058 * @pkcs11_module_path: PKCS #11 module path or NULL
2059 * Returns: 0 on success; -1 on failure
2060 *
2061 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2062 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2063 * module path fails the paths will be reset to the default value (NULL).
2064 */
2065int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2066 const char *pkcs11_engine_path,
2067 const char *pkcs11_module_path)
2068{
2069 char *pkcs11_engine_path_copy = NULL;
2070 char *pkcs11_module_path_copy = NULL;
2071
2072 if (pkcs11_engine_path != NULL) {
2073 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2074 if (pkcs11_engine_path_copy == NULL)
2075 return -1;
2076 }
2077 if (pkcs11_module_path != NULL) {
2078 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
2079 if (pkcs11_engine_path_copy == NULL) {
2080 os_free(pkcs11_engine_path_copy);
2081 return -1;
2082 }
2083 }
2084
2085 os_free(wpa_s->conf->pkcs11_engine_path);
2086 os_free(wpa_s->conf->pkcs11_module_path);
2087 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2088 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2089
2090 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2091 eapol_sm_deinit(wpa_s->eapol);
2092 wpa_s->eapol = NULL;
2093 if (wpa_supplicant_init_eapol(wpa_s)) {
2094 /* Error -> Reset paths to the default value (NULL) once. */
2095 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2096 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2097 NULL);
2098
2099 return -1;
2100 }
2101 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2102
2103 return 0;
2104}
2105
2106
2107/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2109 * @wpa_s: wpa_supplicant structure for a network interface
2110 * @ap_scan: AP scan mode
2111 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2112 *
2113 */
2114int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2115{
2116
2117 int old_ap_scan;
2118
2119 if (ap_scan < 0 || ap_scan > 2)
2120 return -1;
2121
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002122#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002123 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2124 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2125 wpa_s->wpa_state < WPA_COMPLETED) {
2126 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2127 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002128 return 0;
2129 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002130#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002131
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132 old_ap_scan = wpa_s->conf->ap_scan;
2133 wpa_s->conf->ap_scan = ap_scan;
2134
2135 if (old_ap_scan != wpa_s->conf->ap_scan)
2136 wpas_notify_ap_scan_changed(wpa_s);
2137
2138 return 0;
2139}
2140
2141
2142/**
2143 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2144 * @wpa_s: wpa_supplicant structure for a network interface
2145 * @expire_age: Expiration age in seconds
2146 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2147 *
2148 */
2149int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2150 unsigned int bss_expire_age)
2151{
2152 if (bss_expire_age < 10) {
2153 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2154 bss_expire_age);
2155 return -1;
2156 }
2157 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2158 bss_expire_age);
2159 wpa_s->conf->bss_expiration_age = bss_expire_age;
2160
2161 return 0;
2162}
2163
2164
2165/**
2166 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2167 * @wpa_s: wpa_supplicant structure for a network interface
2168 * @expire_count: number of scans after which an unseen BSS is reclaimed
2169 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2170 *
2171 */
2172int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2173 unsigned int bss_expire_count)
2174{
2175 if (bss_expire_count < 1) {
2176 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2177 bss_expire_count);
2178 return -1;
2179 }
2180 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2181 bss_expire_count);
2182 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2183
2184 return 0;
2185}
2186
2187
2188/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002189 * wpa_supplicant_set_scan_interval - Set scan interval
2190 * @wpa_s: wpa_supplicant structure for a network interface
2191 * @scan_interval: scan interval in seconds
2192 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2193 *
2194 */
2195int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2196 int scan_interval)
2197{
2198 if (scan_interval < 0) {
2199 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2200 scan_interval);
2201 return -1;
2202 }
2203 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2204 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002205 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002206
2207 return 0;
2208}
2209
2210
2211/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212 * wpa_supplicant_set_debug_params - Set global debug params
2213 * @global: wpa_global structure
2214 * @debug_level: debug level
2215 * @debug_timestamp: determines if show timestamp in debug data
2216 * @debug_show_keys: determines if show keys in debug data
2217 * Returns: 0 if succeed or -1 if debug_level has wrong value
2218 */
2219int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2220 int debug_timestamp, int debug_show_keys)
2221{
2222
2223 int old_level, old_timestamp, old_show_keys;
2224
2225 /* check for allowed debuglevels */
2226 if (debug_level != MSG_EXCESSIVE &&
2227 debug_level != MSG_MSGDUMP &&
2228 debug_level != MSG_DEBUG &&
2229 debug_level != MSG_INFO &&
2230 debug_level != MSG_WARNING &&
2231 debug_level != MSG_ERROR)
2232 return -1;
2233
2234 old_level = wpa_debug_level;
2235 old_timestamp = wpa_debug_timestamp;
2236 old_show_keys = wpa_debug_show_keys;
2237
2238 wpa_debug_level = debug_level;
2239 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2240 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2241
2242 if (wpa_debug_level != old_level)
2243 wpas_notify_debug_level_changed(global);
2244 if (wpa_debug_timestamp != old_timestamp)
2245 wpas_notify_debug_timestamp_changed(global);
2246 if (wpa_debug_show_keys != old_show_keys)
2247 wpas_notify_debug_show_keys_changed(global);
2248
2249 return 0;
2250}
2251
2252
2253/**
2254 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2255 * @wpa_s: Pointer to wpa_supplicant data
2256 * Returns: A pointer to the current network structure or %NULL on failure
2257 */
2258struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2259{
2260 struct wpa_ssid *entry;
2261 u8 ssid[MAX_SSID_LEN];
2262 int res;
2263 size_t ssid_len;
2264 u8 bssid[ETH_ALEN];
2265 int wired;
2266
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002267 res = wpa_drv_get_ssid(wpa_s, ssid);
2268 if (res < 0) {
2269 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2270 "driver");
2271 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002272 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002273 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002274
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002275 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2277 "driver");
2278 return NULL;
2279 }
2280
2281 wired = wpa_s->conf->ap_scan == 0 &&
2282 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2283
2284 entry = wpa_s->conf->ssid;
2285 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002286 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002287 ((ssid_len == entry->ssid_len &&
2288 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2289 (!entry->bssid_set ||
2290 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2291 return entry;
2292#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002293 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002294 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2295 (entry->ssid == NULL || entry->ssid_len == 0) &&
2296 (!entry->bssid_set ||
2297 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2298 return entry;
2299#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002300
Dmitry Shmidt04949592012-07-19 12:16:46 -07002301 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002302 entry->ssid_len == 0 &&
2303 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2304 return entry;
2305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 entry = entry->next;
2307 }
2308
2309 return NULL;
2310}
2311
2312
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002313static int select_driver(struct wpa_supplicant *wpa_s, int i)
2314{
2315 struct wpa_global *global = wpa_s->global;
2316
2317 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2318 global->drv_priv[i] = wpa_drivers[i]->global_init();
2319 if (global->drv_priv[i] == NULL) {
2320 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2321 "'%s'", wpa_drivers[i]->name);
2322 return -1;
2323 }
2324 }
2325
2326 wpa_s->driver = wpa_drivers[i];
2327 wpa_s->global_drv_priv = global->drv_priv[i];
2328
2329 return 0;
2330}
2331
2332
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2334 const char *name)
2335{
2336 int i;
2337 size_t len;
2338 const char *pos, *driver = name;
2339
2340 if (wpa_s == NULL)
2341 return -1;
2342
2343 if (wpa_drivers[0] == NULL) {
2344 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2345 "wpa_supplicant");
2346 return -1;
2347 }
2348
2349 if (name == NULL) {
2350 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002351 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 }
2353
2354 do {
2355 pos = os_strchr(driver, ',');
2356 if (pos)
2357 len = pos - driver;
2358 else
2359 len = os_strlen(driver);
2360
2361 for (i = 0; wpa_drivers[i]; i++) {
2362 if (os_strlen(wpa_drivers[i]->name) == len &&
2363 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002364 0) {
2365 /* First driver that succeeds wins */
2366 if (select_driver(wpa_s, i) == 0)
2367 return 0;
2368 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002369 }
2370
2371 driver = pos + 1;
2372 } while (pos);
2373
2374 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2375 return -1;
2376}
2377
2378
2379/**
2380 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2381 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2382 * with struct wpa_driver_ops::init()
2383 * @src_addr: Source address of the EAPOL frame
2384 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2385 * @len: Length of the EAPOL data
2386 *
2387 * This function is called for each received EAPOL frame. Most driver
2388 * interfaces rely on more generic OS mechanism for receiving frames through
2389 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2390 * take care of received EAPOL frames and deliver them to the core supplicant
2391 * code by calling this function.
2392 */
2393void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2394 const u8 *buf, size_t len)
2395{
2396 struct wpa_supplicant *wpa_s = ctx;
2397
2398 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2399 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2400
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002401#ifdef CONFIG_PEERKEY
2402 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2403 wpa_s->current_ssid->peerkey &&
2404 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2405 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2406 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2407 return;
2408 }
2409#endif /* CONFIG_PEERKEY */
2410
Jouni Malinena05074c2012-12-21 21:35:35 +02002411 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2412 (wpa_s->last_eapol_matches_bssid &&
2413#ifdef CONFIG_AP
2414 !wpa_s->ap_iface &&
2415#endif /* CONFIG_AP */
2416 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 /*
2418 * There is possible race condition between receiving the
2419 * association event and the EAPOL frame since they are coming
2420 * through different paths from the driver. In order to avoid
2421 * issues in trying to process the EAPOL frame before receiving
2422 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002423 * the association event is received. This may also be needed in
2424 * driver-based roaming case, so also use src_addr != BSSID as a
2425 * trigger if we have previously confirmed that the
2426 * Authenticator uses BSSID as the src_addr (which is not the
2427 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 */
2429 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002430 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2431 wpa_supplicant_state_txt(wpa_s->wpa_state),
2432 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 wpabuf_free(wpa_s->pending_eapol_rx);
2434 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2435 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002436 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2438 ETH_ALEN);
2439 }
2440 return;
2441 }
2442
Jouni Malinena05074c2012-12-21 21:35:35 +02002443 wpa_s->last_eapol_matches_bssid =
2444 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2445
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446#ifdef CONFIG_AP
2447 if (wpa_s->ap_iface) {
2448 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2449 return;
2450 }
2451#endif /* CONFIG_AP */
2452
2453 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2454 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2455 "no key management is configured");
2456 return;
2457 }
2458
2459 if (wpa_s->eapol_received == 0 &&
2460 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2461 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2462 wpa_s->wpa_state != WPA_COMPLETED) &&
2463 (wpa_s->current_ssid == NULL ||
2464 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2465 /* Timeout for completing IEEE 802.1X and WPA authentication */
2466 wpa_supplicant_req_auth_timeout(
2467 wpa_s,
2468 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2469 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2470 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2471 70 : 10, 0);
2472 }
2473 wpa_s->eapol_received++;
2474
2475 if (wpa_s->countermeasures) {
2476 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2477 "EAPOL packet");
2478 return;
2479 }
2480
2481#ifdef CONFIG_IBSS_RSN
2482 if (wpa_s->current_ssid &&
2483 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2484 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2485 return;
2486 }
2487#endif /* CONFIG_IBSS_RSN */
2488
2489 /* Source address of the incoming EAPOL frame could be compared to the
2490 * current BSSID. However, it is possible that a centralized
2491 * Authenticator could be using another MAC address than the BSSID of
2492 * an AP, so just allow any address to be used for now. The replies are
2493 * still sent to the current BSSID (if available), though. */
2494
2495 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2496 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2497 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2498 return;
2499 wpa_drv_poll(wpa_s);
2500 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2501 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2502 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2503 /*
2504 * Set portValid = TRUE here since we are going to skip 4-way
2505 * handshake processing which would normally set portValid. We
2506 * need this to allow the EAPOL state machines to be completed
2507 * without going through EAPOL-Key handshake.
2508 */
2509 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2510 }
2511}
2512
2513
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002514int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 if (wpa_s->driver->send_eapol) {
2517 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2518 if (addr)
2519 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002520 } else if ((!wpa_s->p2p_mgmt ||
2521 !(wpa_s->drv_flags &
2522 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2523 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002525 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2527 wpa_drv_get_mac_addr(wpa_s),
2528 ETH_P_EAPOL,
2529 wpa_supplicant_rx_eapol, wpa_s, 0);
2530 if (wpa_s->l2 == NULL)
2531 return -1;
2532 } else {
2533 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2534 if (addr)
2535 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2536 }
2537
2538 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2539 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2540 return -1;
2541 }
2542
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002543 return 0;
2544}
2545
2546
Dmitry Shmidt04949592012-07-19 12:16:46 -07002547static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2548 const u8 *buf, size_t len)
2549{
2550 struct wpa_supplicant *wpa_s = ctx;
2551 const struct l2_ethhdr *eth;
2552
2553 if (len < sizeof(*eth))
2554 return;
2555 eth = (const struct l2_ethhdr *) buf;
2556
2557 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2558 !(eth->h_dest[0] & 0x01)) {
2559 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2560 " (bridge - not for this interface - ignore)",
2561 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2562 return;
2563 }
2564
2565 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2566 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2567 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2568 len - sizeof(*eth));
2569}
2570
2571
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002572/**
2573 * wpa_supplicant_driver_init - Initialize driver interface parameters
2574 * @wpa_s: Pointer to wpa_supplicant data
2575 * Returns: 0 on success, -1 on failure
2576 *
2577 * This function is called to initialize driver interface parameters.
2578 * wpa_drv_init() must have been called before this function to initialize the
2579 * driver interface.
2580 */
2581int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2582{
2583 static int interface_count = 0;
2584
2585 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2586 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002588 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2589 MAC2STR(wpa_s->own_addr));
2590 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2591
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 if (wpa_s->bridge_ifname[0]) {
2593 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2594 "interface '%s'", wpa_s->bridge_ifname);
2595 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2596 wpa_s->own_addr,
2597 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002598 wpa_supplicant_rx_eapol_bridge,
2599 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 if (wpa_s->l2_br == NULL) {
2601 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2602 "connection for the bridge interface '%s'",
2603 wpa_s->bridge_ifname);
2604 return -1;
2605 }
2606 }
2607
2608 wpa_clear_keys(wpa_s, NULL);
2609
2610 /* Make sure that TKIP countermeasures are not left enabled (could
2611 * happen if wpa_supplicant is killed during countermeasures. */
2612 wpa_drv_set_countermeasures(wpa_s, 0);
2613
2614 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2615 wpa_drv_flush_pmkid(wpa_s);
2616
2617 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002618 wpa_s->prev_scan_wildcard = 0;
2619
Dmitry Shmidt04949592012-07-19 12:16:46 -07002620 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002621 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2622 100000))
2623 wpa_supplicant_req_scan(wpa_s, interface_count,
2624 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 interface_count++;
2626 } else
2627 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2628
2629 return 0;
2630}
2631
2632
2633static int wpa_supplicant_daemon(const char *pid_file)
2634{
2635 wpa_printf(MSG_DEBUG, "Daemonize..");
2636 return os_daemonize(pid_file);
2637}
2638
2639
2640static struct wpa_supplicant * wpa_supplicant_alloc(void)
2641{
2642 struct wpa_supplicant *wpa_s;
2643
2644 wpa_s = os_zalloc(sizeof(*wpa_s));
2645 if (wpa_s == NULL)
2646 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002647 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 wpa_s->scan_interval = 5;
2649 wpa_s->new_connection = 1;
2650 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002651 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652
2653 return wpa_s;
2654}
2655
2656
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002657#ifdef CONFIG_HT_OVERRIDES
2658
2659static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2660 struct ieee80211_ht_capabilities *htcaps,
2661 struct ieee80211_ht_capabilities *htcaps_mask,
2662 const char *ht_mcs)
2663{
2664 /* parse ht_mcs into hex array */
2665 int i;
2666 const char *tmp = ht_mcs;
2667 char *end = NULL;
2668
2669 /* If ht_mcs is null, do not set anything */
2670 if (!ht_mcs)
2671 return 0;
2672
2673 /* This is what we are setting in the kernel */
2674 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2675
2676 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2677
2678 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2679 errno = 0;
2680 long v = strtol(tmp, &end, 16);
2681 if (errno == 0) {
2682 wpa_msg(wpa_s, MSG_DEBUG,
2683 "htcap value[%i]: %ld end: %p tmp: %p",
2684 i, v, end, tmp);
2685 if (end == tmp)
2686 break;
2687
2688 htcaps->supported_mcs_set[i] = v;
2689 tmp = end;
2690 } else {
2691 wpa_msg(wpa_s, MSG_ERROR,
2692 "Failed to parse ht-mcs: %s, error: %s\n",
2693 ht_mcs, strerror(errno));
2694 return -1;
2695 }
2696 }
2697
2698 /*
2699 * If we were able to parse any values, then set mask for the MCS set.
2700 */
2701 if (i) {
2702 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2703 IEEE80211_HT_MCS_MASK_LEN - 1);
2704 /* skip the 3 reserved bits */
2705 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2706 0x1f;
2707 }
2708
2709 return 0;
2710}
2711
2712
2713static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2714 struct ieee80211_ht_capabilities *htcaps,
2715 struct ieee80211_ht_capabilities *htcaps_mask,
2716 int disabled)
2717{
2718 u16 msk;
2719
2720 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2721
2722 if (disabled == -1)
2723 return 0;
2724
2725 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2726 htcaps_mask->ht_capabilities_info |= msk;
2727 if (disabled)
2728 htcaps->ht_capabilities_info &= msk;
2729 else
2730 htcaps->ht_capabilities_info |= msk;
2731
2732 return 0;
2733}
2734
2735
2736static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2737 struct ieee80211_ht_capabilities *htcaps,
2738 struct ieee80211_ht_capabilities *htcaps_mask,
2739 int factor)
2740{
2741 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2742
2743 if (factor == -1)
2744 return 0;
2745
2746 if (factor < 0 || factor > 3) {
2747 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2748 "Must be 0-3 or -1", factor);
2749 return -EINVAL;
2750 }
2751
2752 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2753 htcaps->a_mpdu_params &= ~0x3;
2754 htcaps->a_mpdu_params |= factor & 0x3;
2755
2756 return 0;
2757}
2758
2759
2760static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2761 struct ieee80211_ht_capabilities *htcaps,
2762 struct ieee80211_ht_capabilities *htcaps_mask,
2763 int density)
2764{
2765 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2766
2767 if (density == -1)
2768 return 0;
2769
2770 if (density < 0 || density > 7) {
2771 wpa_msg(wpa_s, MSG_ERROR,
2772 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2773 density);
2774 return -EINVAL;
2775 }
2776
2777 htcaps_mask->a_mpdu_params |= 0x1C;
2778 htcaps->a_mpdu_params &= ~(0x1C);
2779 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2780
2781 return 0;
2782}
2783
2784
2785static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2786 struct ieee80211_ht_capabilities *htcaps,
2787 struct ieee80211_ht_capabilities *htcaps_mask,
2788 int disabled)
2789{
2790 /* Masking these out disables HT40 */
2791 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2792 HT_CAP_INFO_SHORT_GI40MHZ);
2793
2794 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2795
2796 if (disabled)
2797 htcaps->ht_capabilities_info &= ~msk;
2798 else
2799 htcaps->ht_capabilities_info |= msk;
2800
2801 htcaps_mask->ht_capabilities_info |= msk;
2802
2803 return 0;
2804}
2805
2806
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002807static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2808 struct ieee80211_ht_capabilities *htcaps,
2809 struct ieee80211_ht_capabilities *htcaps_mask,
2810 int disabled)
2811{
2812 /* Masking these out disables SGI */
2813 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2814 HT_CAP_INFO_SHORT_GI40MHZ);
2815
2816 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2817
2818 if (disabled)
2819 htcaps->ht_capabilities_info &= ~msk;
2820 else
2821 htcaps->ht_capabilities_info |= msk;
2822
2823 htcaps_mask->ht_capabilities_info |= msk;
2824
2825 return 0;
2826}
2827
2828
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002829void wpa_supplicant_apply_ht_overrides(
2830 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2831 struct wpa_driver_associate_params *params)
2832{
2833 struct ieee80211_ht_capabilities *htcaps;
2834 struct ieee80211_ht_capabilities *htcaps_mask;
2835
2836 if (!ssid)
2837 return;
2838
2839 params->disable_ht = ssid->disable_ht;
2840 if (!params->htcaps || !params->htcaps_mask)
2841 return;
2842
2843 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2844 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2845 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2846 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2847 ssid->disable_max_amsdu);
2848 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2849 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2850 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002851 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002852}
2853
2854#endif /* CONFIG_HT_OVERRIDES */
2855
2856
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002857#ifdef CONFIG_VHT_OVERRIDES
2858void wpa_supplicant_apply_vht_overrides(
2859 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2860 struct wpa_driver_associate_params *params)
2861{
2862 struct ieee80211_vht_capabilities *vhtcaps;
2863 struct ieee80211_vht_capabilities *vhtcaps_mask;
2864
2865 if (!ssid)
2866 return;
2867
2868 params->disable_vht = ssid->disable_vht;
2869
2870 vhtcaps = (void *) params->vhtcaps;
2871 vhtcaps_mask = (void *) params->vhtcaps_mask;
2872
2873 if (!vhtcaps || !vhtcaps_mask)
2874 return;
2875
2876 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2877 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2878
2879#define OVERRIDE_MCS(i) \
2880 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2881 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2882 3 << 2 * (i - 1); \
2883 vhtcaps->vht_supported_mcs_set.tx_map |= \
2884 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2885 } \
2886 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2887 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2888 3 << 2 * (i - 1); \
2889 vhtcaps->vht_supported_mcs_set.rx_map |= \
2890 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2891 }
2892
2893 OVERRIDE_MCS(1);
2894 OVERRIDE_MCS(2);
2895 OVERRIDE_MCS(3);
2896 OVERRIDE_MCS(4);
2897 OVERRIDE_MCS(5);
2898 OVERRIDE_MCS(6);
2899 OVERRIDE_MCS(7);
2900 OVERRIDE_MCS(8);
2901}
2902#endif /* CONFIG_VHT_OVERRIDES */
2903
2904
Dmitry Shmidt04949592012-07-19 12:16:46 -07002905static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2906{
2907#ifdef PCSC_FUNCS
2908 size_t len;
2909
2910 if (!wpa_s->conf->pcsc_reader)
2911 return 0;
2912
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002913 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002914 if (!wpa_s->scard)
2915 return 1;
2916
2917 if (wpa_s->conf->pcsc_pin &&
2918 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2919 scard_deinit(wpa_s->scard);
2920 wpa_s->scard = NULL;
2921 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2922 return -1;
2923 }
2924
2925 len = sizeof(wpa_s->imsi) - 1;
2926 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2927 scard_deinit(wpa_s->scard);
2928 wpa_s->scard = NULL;
2929 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2930 return -1;
2931 }
2932 wpa_s->imsi[len] = '\0';
2933
2934 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2935
2936 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2937 wpa_s->imsi, wpa_s->mnc_len);
2938
2939 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2940 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2941#endif /* PCSC_FUNCS */
2942
2943 return 0;
2944}
2945
2946
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002947int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2948{
2949 char *val, *pos;
2950
2951 ext_password_deinit(wpa_s->ext_pw);
2952 wpa_s->ext_pw = NULL;
2953 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2954
2955 if (!wpa_s->conf->ext_password_backend)
2956 return 0;
2957
2958 val = os_strdup(wpa_s->conf->ext_password_backend);
2959 if (val == NULL)
2960 return -1;
2961 pos = os_strchr(val, ':');
2962 if (pos)
2963 *pos++ = '\0';
2964
2965 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2966
2967 wpa_s->ext_pw = ext_password_init(val, pos);
2968 os_free(val);
2969 if (wpa_s->ext_pw == NULL) {
2970 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2971 return -1;
2972 }
2973 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2974
2975 return 0;
2976}
2977
2978
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002979static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2980 const char *rn)
2981{
2982 struct wpa_supplicant *iface = wpa_s->global->ifaces;
2983 struct wpa_radio *radio;
2984
2985 while (rn && iface) {
2986 radio = iface->radio;
2987 if (radio && os_strcmp(rn, radio->name) == 0) {
2988 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
2989 wpa_s->ifname, rn);
2990 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
2991 return radio;
2992 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08002993
2994 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002995 }
2996
2997 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
2998 wpa_s->ifname, rn ? rn : "N/A");
2999 radio = os_zalloc(sizeof(*radio));
3000 if (radio == NULL)
3001 return NULL;
3002
3003 if (rn)
3004 os_strlcpy(radio->name, rn, sizeof(radio->name));
3005 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003006 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003007 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3008
3009 return radio;
3010}
3011
3012
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003013static void radio_work_free(struct wpa_radio_work *work)
3014{
3015 if (work->wpa_s->scan_work == work) {
3016 /* This should not really happen. */
3017 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3018 work->type, work, work->started);
3019 work->wpa_s->scan_work = NULL;
3020 }
3021
3022#ifdef CONFIG_P2P
3023 if (work->wpa_s->p2p_scan_work == work) {
3024 /* This should not really happen. */
3025 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3026 work->type, work, work->started);
3027 work->wpa_s->p2p_scan_work = NULL;
3028 }
3029#endif /* CONFIG_P2P */
3030
3031 dl_list_del(&work->list);
3032 os_free(work);
3033}
3034
3035
3036static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3037{
3038 struct wpa_radio *radio = eloop_ctx;
3039 struct wpa_radio_work *work;
3040 struct os_reltime now, diff;
3041 struct wpa_supplicant *wpa_s;
3042
3043 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3044 if (work == NULL)
3045 return;
3046
3047 if (work->started)
3048 return; /* already started and still in progress */
3049
3050 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3051 radio_list);
3052 if (wpa_s && wpa_s->external_scan_running) {
3053 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3054 return;
3055 }
3056
3057 os_get_reltime(&now);
3058 os_reltime_sub(&now, &work->time, &diff);
3059 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3060 work->type, work, diff.sec, diff.usec);
3061 work->started = 1;
3062 work->time = now;
3063 work->cb(work, 0);
3064}
3065
3066
3067void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
3068{
3069 struct wpa_radio_work *work, *tmp;
3070 struct wpa_radio *radio = wpa_s->radio;
3071
3072 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3073 list) {
3074 if (type && (work->started || os_strcmp(type, work->type) != 0))
3075 continue;
3076 if (work->started) {
3077 wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
3078 work->type, work);
3079 continue;
3080 }
3081 wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
3082 work->type, work);
3083 work->cb(work, 1);
3084 radio_work_free(work);
3085 }
3086}
3087
3088
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003089static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3090{
3091 struct wpa_radio *radio = wpa_s->radio;
3092
3093 if (!radio)
3094 return;
3095
3096 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3097 wpa_s->ifname, radio->name);
3098 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003099 if (!dl_list_empty(&radio->ifaces)) {
3100 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003101 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003102 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003103
3104 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003105 radio_remove_unstarted_work(wpa_s, NULL);
3106 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3107 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003108 os_free(radio);
3109}
3110
3111
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003112void radio_work_check_next(struct wpa_supplicant *wpa_s)
3113{
3114 struct wpa_radio *radio = wpa_s->radio;
3115
3116 if (dl_list_empty(&radio->work))
3117 return;
3118 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3119 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3120}
3121
3122
3123/**
3124 * radio_add_work - Add a radio work item
3125 * @wpa_s: Pointer to wpa_supplicant data
3126 * @freq: Frequency of the offchannel operation in MHz or 0
3127 * @type: Unique identifier for each type of work
3128 * @next: Force as the next work to be executed
3129 * @cb: Callback function for indicating when radio is available
3130 * @ctx: Context pointer for the work (work->ctx in cb())
3131 * Returns: 0 on success, -1 on failure
3132 *
3133 * This function is used to request time for an operation that requires
3134 * exclusive radio control. Once the radio is available, the registered callback
3135 * function will be called. radio_work_done() must be called once the exclusive
3136 * radio operation has been completed, so that the radio is freed for other
3137 * operations. The special case of deinit=1 is used to free the context data
3138 * during interface removal. That does not allow the callback function to start
3139 * the radio operation, i.e., it must free any resources allocated for the radio
3140 * work and return.
3141 *
3142 * The @freq parameter can be used to indicate a single channel on which the
3143 * offchannel operation will occur. This may allow multiple radio work
3144 * operations to be performed in parallel if they apply for the same channel.
3145 * Setting this to 0 indicates that the work item may use multiple channels or
3146 * requires exclusive control of the radio.
3147 */
3148int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3149 const char *type, int next,
3150 void (*cb)(struct wpa_radio_work *work, int deinit),
3151 void *ctx)
3152{
3153 struct wpa_radio_work *work;
3154 int was_empty;
3155
3156 work = os_zalloc(sizeof(*work));
3157 if (work == NULL)
3158 return -1;
3159 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3160 os_get_reltime(&work->time);
3161 work->freq = freq;
3162 work->type = type;
3163 work->wpa_s = wpa_s;
3164 work->cb = cb;
3165 work->ctx = ctx;
3166
3167 was_empty = dl_list_empty(&wpa_s->radio->work);
3168 if (next)
3169 dl_list_add(&wpa_s->radio->work, &work->list);
3170 else
3171 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3172 if (was_empty) {
3173 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3174 radio_work_check_next(wpa_s);
3175 }
3176
3177 return 0;
3178}
3179
3180
3181/**
3182 * radio_work_done - Indicate that a radio work item has been completed
3183 * @work: Completed work
3184 *
3185 * This function is called once the callback function registered with
3186 * radio_add_work() has completed its work.
3187 */
3188void radio_work_done(struct wpa_radio_work *work)
3189{
3190 struct wpa_supplicant *wpa_s = work->wpa_s;
3191 struct os_reltime now, diff;
3192 unsigned int started = work->started;
3193
3194 os_get_reltime(&now);
3195 os_reltime_sub(&now, &work->time, &diff);
3196 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3197 work->type, work, started ? "done" : "canceled",
3198 diff.sec, diff.usec);
3199 radio_work_free(work);
3200 if (started)
3201 radio_work_check_next(wpa_s);
3202}
3203
3204
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003205static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3206 struct wpa_interface *iface)
3207{
3208 const char *ifname, *driver, *rn;
3209
3210 driver = iface->driver;
3211next_driver:
3212 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3213 return -1;
3214
3215 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3216 if (wpa_s->drv_priv == NULL) {
3217 const char *pos;
3218 pos = driver ? os_strchr(driver, ',') : NULL;
3219 if (pos) {
3220 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3221 "driver interface - try next driver wrapper");
3222 driver = pos + 1;
3223 goto next_driver;
3224 }
3225 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3226 "interface");
3227 return -1;
3228 }
3229 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3230 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3231 "driver_param '%s'", wpa_s->conf->driver_param);
3232 return -1;
3233 }
3234
3235 ifname = wpa_drv_get_ifname(wpa_s);
3236 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3237 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3238 "interface name with '%s'", ifname);
3239 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3240 }
3241
3242 if (wpa_s->driver->get_radio_name)
3243 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3244 else
3245 rn = NULL;
3246 if (rn && rn[0] == '\0')
3247 rn = NULL;
3248
3249 wpa_s->radio = radio_add_interface(wpa_s, rn);
3250 if (wpa_s->radio == NULL)
3251 return -1;
3252
3253 return 0;
3254}
3255
3256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003257static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3258 struct wpa_interface *iface)
3259{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 struct wpa_driver_capa capa;
3261
3262 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3263 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3264 iface->confname ? iface->confname : "N/A",
3265 iface->driver ? iface->driver : "default",
3266 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3267 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3268
3269 if (iface->confname) {
3270#ifdef CONFIG_BACKEND_FILE
3271 wpa_s->confname = os_rel2abs_path(iface->confname);
3272 if (wpa_s->confname == NULL) {
3273 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3274 "for configuration file '%s'.",
3275 iface->confname);
3276 return -1;
3277 }
3278 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3279 iface->confname, wpa_s->confname);
3280#else /* CONFIG_BACKEND_FILE */
3281 wpa_s->confname = os_strdup(iface->confname);
3282#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003283 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284 if (wpa_s->conf == NULL) {
3285 wpa_printf(MSG_ERROR, "Failed to read or parse "
3286 "configuration '%s'.", wpa_s->confname);
3287 return -1;
3288 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003289 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3290 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003291
3292 /*
3293 * Override ctrl_interface and driver_param if set on command
3294 * line.
3295 */
3296 if (iface->ctrl_interface) {
3297 os_free(wpa_s->conf->ctrl_interface);
3298 wpa_s->conf->ctrl_interface =
3299 os_strdup(iface->ctrl_interface);
3300 }
3301
3302 if (iface->driver_param) {
3303 os_free(wpa_s->conf->driver_param);
3304 wpa_s->conf->driver_param =
3305 os_strdup(iface->driver_param);
3306 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003307
3308 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3309 os_free(wpa_s->conf->ctrl_interface);
3310 wpa_s->conf->ctrl_interface = NULL;
3311 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003312 } else
3313 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3314 iface->driver_param);
3315
3316 if (wpa_s->conf == NULL) {
3317 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3318 return -1;
3319 }
3320
3321 if (iface->ifname == NULL) {
3322 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3323 return -1;
3324 }
3325 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3326 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3327 iface->ifname);
3328 return -1;
3329 }
3330 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3331
3332 if (iface->bridge_ifname) {
3333 if (os_strlen(iface->bridge_ifname) >=
3334 sizeof(wpa_s->bridge_ifname)) {
3335 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3336 "name '%s'.", iface->bridge_ifname);
3337 return -1;
3338 }
3339 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3340 sizeof(wpa_s->bridge_ifname));
3341 }
3342
3343 /* RSNA Supplicant Key Management - INITIALIZE */
3344 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3345 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3346
3347 /* Initialize driver interface and register driver event handler before
3348 * L2 receive handler so that association events are processed before
3349 * EAPOL-Key packets if both become available for the same select()
3350 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003351 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 return -1;
3353
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3355 return -1;
3356
3357 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3358 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3359 NULL);
3360 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3361
3362 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3363 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3364 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3365 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3366 "dot11RSNAConfigPMKLifetime");
3367 return -1;
3368 }
3369
3370 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3371 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3372 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3373 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3374 "dot11RSNAConfigPMKReauthThreshold");
3375 return -1;
3376 }
3377
3378 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3379 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3380 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3381 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3382 "dot11RSNAConfigSATimeout");
3383 return -1;
3384 }
3385
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003386 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3387 &wpa_s->hw.num_modes,
3388 &wpa_s->hw.flags);
3389
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003390 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003391 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003392 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003393 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003394 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003396 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3397 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3398 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003399 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3400 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003401 wpa_s->extended_capa = capa.extended_capa;
3402 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3403 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003404 wpa_s->num_multichan_concurrent =
3405 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003406 }
3407 if (wpa_s->max_remain_on_chan == 0)
3408 wpa_s->max_remain_on_chan = 1000;
3409
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003410 /*
3411 * Only take p2p_mgmt parameters when P2P Device is supported.
3412 * Doing it here as it determines whether l2_packet_init() will be done
3413 * during wpa_supplicant_driver_init().
3414 */
3415 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3416 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3417 else
3418 iface->p2p_mgmt = 1;
3419
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003420 if (wpa_s->num_multichan_concurrent == 0)
3421 wpa_s->num_multichan_concurrent = 1;
3422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423 if (wpa_supplicant_driver_init(wpa_s) < 0)
3424 return -1;
3425
3426#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003427 if ((!iface->p2p_mgmt ||
3428 !(wpa_s->drv_flags &
3429 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3430 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003431 return -1;
3432#endif /* CONFIG_TDLS */
3433
3434 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3435 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3436 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3437 return -1;
3438 }
3439
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003440 if (wpas_wps_init(wpa_s))
3441 return -1;
3442
3443 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3444 return -1;
3445 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3446
3447 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3448 if (wpa_s->ctrl_iface == NULL) {
3449 wpa_printf(MSG_ERROR,
3450 "Failed to initialize control interface '%s'.\n"
3451 "You may have another wpa_supplicant process "
3452 "already running or the file was\n"
3453 "left by an unclean termination of wpa_supplicant "
3454 "in which case you will need\n"
3455 "to manually remove this file before starting "
3456 "wpa_supplicant again.\n",
3457 wpa_s->conf->ctrl_interface);
3458 return -1;
3459 }
3460
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003461 wpa_s->gas = gas_query_init(wpa_s);
3462 if (wpa_s->gas == NULL) {
3463 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3464 return -1;
3465 }
3466
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003467#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003468 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003469 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3470 return -1;
3471 }
3472#endif /* CONFIG_P2P */
3473
3474 if (wpa_bss_init(wpa_s) < 0)
3475 return -1;
3476
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003477#ifdef CONFIG_EAP_PROXY
3478{
3479 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003480 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3481 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003482 if (wpa_s->mnc_len > 0) {
3483 wpa_s->imsi[len] = '\0';
3484 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3485 wpa_s->imsi, wpa_s->mnc_len);
3486 } else {
3487 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3488 }
3489}
3490#endif /* CONFIG_EAP_PROXY */
3491
Dmitry Shmidt04949592012-07-19 12:16:46 -07003492 if (pcsc_reader_init(wpa_s) < 0)
3493 return -1;
3494
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003495 if (wpas_init_ext_pw(wpa_s) < 0)
3496 return -1;
3497
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498 return 0;
3499}
3500
3501
3502static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003503 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003505 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003506 if (wpa_s->drv_priv) {
3507 wpa_supplicant_deauthenticate(wpa_s,
3508 WLAN_REASON_DEAUTH_LEAVING);
3509
3510 wpa_drv_set_countermeasures(wpa_s, 0);
3511 wpa_clear_keys(wpa_s, NULL);
3512 }
3513
3514 wpa_supplicant_cleanup(wpa_s);
3515
Dmitry Shmidt04949592012-07-19 12:16:46 -07003516#ifdef CONFIG_P2P
3517 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3518 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3519 "the management interface is being removed");
3520 wpas_p2p_deinit_global(wpa_s->global);
3521 }
3522#endif /* CONFIG_P2P */
3523
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003524 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003525 radio_remove_interface(wpa_s);
3526
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 if (wpa_s->drv_priv)
3528 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003529
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003530 if (notify)
3531 wpas_notify_iface_removed(wpa_s);
3532
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003533 if (terminate)
3534 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003535
3536 if (wpa_s->ctrl_iface) {
3537 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3538 wpa_s->ctrl_iface = NULL;
3539 }
3540
3541 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003542 wpa_config_free(wpa_s->conf);
3543 wpa_s->conf = NULL;
3544 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003545
3546 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003547}
3548
3549
3550/**
3551 * wpa_supplicant_add_iface - Add a new network interface
3552 * @global: Pointer to global data from wpa_supplicant_init()
3553 * @iface: Interface configuration options
3554 * Returns: Pointer to the created interface or %NULL on failure
3555 *
3556 * This function is used to add new network interfaces for %wpa_supplicant.
3557 * This can be called before wpa_supplicant_run() to add interfaces before the
3558 * main event loop has been started. In addition, new interfaces can be added
3559 * dynamically while %wpa_supplicant is already running. This could happen,
3560 * e.g., when a hotplug network adapter is inserted.
3561 */
3562struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3563 struct wpa_interface *iface)
3564{
3565 struct wpa_supplicant *wpa_s;
3566 struct wpa_interface t_iface;
3567 struct wpa_ssid *ssid;
3568
3569 if (global == NULL || iface == NULL)
3570 return NULL;
3571
3572 wpa_s = wpa_supplicant_alloc();
3573 if (wpa_s == NULL)
3574 return NULL;
3575
3576 wpa_s->global = global;
3577
3578 t_iface = *iface;
3579 if (global->params.override_driver) {
3580 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3581 "('%s' -> '%s')",
3582 iface->driver, global->params.override_driver);
3583 t_iface.driver = global->params.override_driver;
3584 }
3585 if (global->params.override_ctrl_interface) {
3586 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3587 "ctrl_interface ('%s' -> '%s')",
3588 iface->ctrl_interface,
3589 global->params.override_ctrl_interface);
3590 t_iface.ctrl_interface =
3591 global->params.override_ctrl_interface;
3592 }
3593 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3594 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3595 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003596 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597 return NULL;
3598 }
3599
3600 /* Notify the control interfaces about new iface */
3601 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003602 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003603 return NULL;
3604 }
3605
3606 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3607 wpas_notify_network_added(wpa_s, ssid);
3608
3609 wpa_s->next = global->ifaces;
3610 global->ifaces = wpa_s;
3611
3612 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003613 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614
3615 return wpa_s;
3616}
3617
3618
3619/**
3620 * wpa_supplicant_remove_iface - Remove a network interface
3621 * @global: Pointer to global data from wpa_supplicant_init()
3622 * @wpa_s: Pointer to the network interface to be removed
3623 * Returns: 0 if interface was removed, -1 if interface was not found
3624 *
3625 * This function can be used to dynamically remove network interfaces from
3626 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3627 * addition, this function is used to remove all remaining interfaces when
3628 * %wpa_supplicant is terminated.
3629 */
3630int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003631 struct wpa_supplicant *wpa_s,
3632 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633{
3634 struct wpa_supplicant *prev;
3635
3636 /* Remove interface from the global list of interfaces */
3637 prev = global->ifaces;
3638 if (prev == wpa_s) {
3639 global->ifaces = wpa_s->next;
3640 } else {
3641 while (prev && prev->next != wpa_s)
3642 prev = prev->next;
3643 if (prev == NULL)
3644 return -1;
3645 prev->next = wpa_s->next;
3646 }
3647
3648 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3649
3650 if (global->p2p_group_formation == wpa_s)
3651 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003652 if (global->p2p_invite_group == wpa_s)
3653 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003654 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003655
3656 return 0;
3657}
3658
3659
3660/**
3661 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3662 * @wpa_s: Pointer to the network interface
3663 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3664 */
3665const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3666{
3667 const char *eapol_method;
3668
3669 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3670 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3671 return "NO-EAP";
3672 }
3673
3674 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3675 if (eapol_method == NULL)
3676 return "UNKNOWN-EAP";
3677
3678 return eapol_method;
3679}
3680
3681
3682/**
3683 * wpa_supplicant_get_iface - Get a new network interface
3684 * @global: Pointer to global data from wpa_supplicant_init()
3685 * @ifname: Interface name
3686 * Returns: Pointer to the interface or %NULL if not found
3687 */
3688struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3689 const char *ifname)
3690{
3691 struct wpa_supplicant *wpa_s;
3692
3693 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3694 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3695 return wpa_s;
3696 }
3697 return NULL;
3698}
3699
3700
3701#ifndef CONFIG_NO_WPA_MSG
3702static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3703{
3704 struct wpa_supplicant *wpa_s = ctx;
3705 if (wpa_s == NULL)
3706 return NULL;
3707 return wpa_s->ifname;
3708}
3709#endif /* CONFIG_NO_WPA_MSG */
3710
3711
3712/**
3713 * wpa_supplicant_init - Initialize %wpa_supplicant
3714 * @params: Parameters for %wpa_supplicant
3715 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3716 *
3717 * This function is used to initialize %wpa_supplicant. After successful
3718 * initialization, the returned data pointer can be used to add and remove
3719 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3720 */
3721struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3722{
3723 struct wpa_global *global;
3724 int ret, i;
3725
3726 if (params == NULL)
3727 return NULL;
3728
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003729#ifdef CONFIG_DRIVER_NDIS
3730 {
3731 void driver_ndis_init_ops(void);
3732 driver_ndis_init_ops();
3733 }
3734#endif /* CONFIG_DRIVER_NDIS */
3735
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003736#ifndef CONFIG_NO_WPA_MSG
3737 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3738#endif /* CONFIG_NO_WPA_MSG */
3739
3740 wpa_debug_open_file(params->wpa_debug_file_path);
3741 if (params->wpa_debug_syslog)
3742 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003743 if (params->wpa_debug_tracing) {
3744 ret = wpa_debug_open_linux_tracing();
3745 if (ret) {
3746 wpa_printf(MSG_ERROR,
3747 "Failed to enable trace logging");
3748 return NULL;
3749 }
3750 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751
3752 ret = eap_register_methods();
3753 if (ret) {
3754 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3755 if (ret == -2)
3756 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3757 "the same EAP type.");
3758 return NULL;
3759 }
3760
3761 global = os_zalloc(sizeof(*global));
3762 if (global == NULL)
3763 return NULL;
3764 dl_list_init(&global->p2p_srv_bonjour);
3765 dl_list_init(&global->p2p_srv_upnp);
3766 global->params.daemonize = params->daemonize;
3767 global->params.wait_for_monitor = params->wait_for_monitor;
3768 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3769 if (params->pid_file)
3770 global->params.pid_file = os_strdup(params->pid_file);
3771 if (params->ctrl_interface)
3772 global->params.ctrl_interface =
3773 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003774 if (params->ctrl_interface_group)
3775 global->params.ctrl_interface_group =
3776 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 if (params->override_driver)
3778 global->params.override_driver =
3779 os_strdup(params->override_driver);
3780 if (params->override_ctrl_interface)
3781 global->params.override_ctrl_interface =
3782 os_strdup(params->override_ctrl_interface);
3783 wpa_debug_level = global->params.wpa_debug_level =
3784 params->wpa_debug_level;
3785 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3786 params->wpa_debug_show_keys;
3787 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3788 params->wpa_debug_timestamp;
3789
3790 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3791
3792 if (eloop_init()) {
3793 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3794 wpa_supplicant_deinit(global);
3795 return NULL;
3796 }
3797
Jouni Malinen75ecf522011-06-27 15:19:46 -07003798 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799
3800 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3801 if (global->ctrl_iface == NULL) {
3802 wpa_supplicant_deinit(global);
3803 return NULL;
3804 }
3805
3806 if (wpas_notify_supplicant_initialized(global)) {
3807 wpa_supplicant_deinit(global);
3808 return NULL;
3809 }
3810
3811 for (i = 0; wpa_drivers[i]; i++)
3812 global->drv_count++;
3813 if (global->drv_count == 0) {
3814 wpa_printf(MSG_ERROR, "No drivers enabled");
3815 wpa_supplicant_deinit(global);
3816 return NULL;
3817 }
3818 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3819 if (global->drv_priv == NULL) {
3820 wpa_supplicant_deinit(global);
3821 return NULL;
3822 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003824#ifdef CONFIG_WIFI_DISPLAY
3825 if (wifi_display_init(global) < 0) {
3826 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3827 wpa_supplicant_deinit(global);
3828 return NULL;
3829 }
3830#endif /* CONFIG_WIFI_DISPLAY */
3831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832 return global;
3833}
3834
3835
3836/**
3837 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3838 * @global: Pointer to global data from wpa_supplicant_init()
3839 * Returns: 0 after successful event loop run, -1 on failure
3840 *
3841 * This function starts the main event loop and continues running as long as
3842 * there are any remaining events. In most cases, this function is running as
3843 * long as the %wpa_supplicant process in still in use.
3844 */
3845int wpa_supplicant_run(struct wpa_global *global)
3846{
3847 struct wpa_supplicant *wpa_s;
3848
3849 if (global->params.daemonize &&
3850 wpa_supplicant_daemon(global->params.pid_file))
3851 return -1;
3852
3853 if (global->params.wait_for_monitor) {
3854 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3855 if (wpa_s->ctrl_iface)
3856 wpa_supplicant_ctrl_iface_wait(
3857 wpa_s->ctrl_iface);
3858 }
3859
3860 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3861 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3862
3863 eloop_run();
3864
3865 return 0;
3866}
3867
3868
3869/**
3870 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3871 * @global: Pointer to global data from wpa_supplicant_init()
3872 *
3873 * This function is called to deinitialize %wpa_supplicant and to free all
3874 * allocated resources. Remaining network interfaces will also be removed.
3875 */
3876void wpa_supplicant_deinit(struct wpa_global *global)
3877{
3878 int i;
3879
3880 if (global == NULL)
3881 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003882
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003883#ifdef CONFIG_WIFI_DISPLAY
3884 wifi_display_deinit(global);
3885#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003886
3887 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003888 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889
3890 if (global->ctrl_iface)
3891 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3892
3893 wpas_notify_supplicant_deinitialized(global);
3894
3895 eap_peer_unregister_methods();
3896#ifdef CONFIG_AP
3897 eap_server_unregister_methods();
3898#endif /* CONFIG_AP */
3899
3900 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3901 if (!global->drv_priv[i])
3902 continue;
3903 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3904 }
3905 os_free(global->drv_priv);
3906
3907 random_deinit();
3908
3909 eloop_destroy();
3910
3911 if (global->params.pid_file) {
3912 os_daemonize_terminate(global->params.pid_file);
3913 os_free(global->params.pid_file);
3914 }
3915 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003916 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917 os_free(global->params.override_driver);
3918 os_free(global->params.override_ctrl_interface);
3919
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003920 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003921 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003922
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003923 os_free(global);
3924 wpa_debug_close_syslog();
3925 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003926 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003927}
3928
3929
3930void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3931{
3932 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3933 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3934 char country[3];
3935 country[0] = wpa_s->conf->country[0];
3936 country[1] = wpa_s->conf->country[1];
3937 country[2] = '\0';
3938 if (wpa_drv_set_country(wpa_s, country) < 0) {
3939 wpa_printf(MSG_ERROR, "Failed to set country code "
3940 "'%s'", country);
3941 }
3942 }
3943
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003944 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3945 wpas_init_ext_pw(wpa_s);
3946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947#ifdef CONFIG_WPS
3948 wpas_wps_update_config(wpa_s);
3949#endif /* CONFIG_WPS */
3950
3951#ifdef CONFIG_P2P
3952 wpas_p2p_update_config(wpa_s);
3953#endif /* CONFIG_P2P */
3954
3955 wpa_s->conf->changed_parameters = 0;
3956}
3957
3958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959static void add_freq(int *freqs, int *num_freqs, int freq)
3960{
3961 int i;
3962
3963 for (i = 0; i < *num_freqs; i++) {
3964 if (freqs[i] == freq)
3965 return;
3966 }
3967
3968 freqs[*num_freqs] = freq;
3969 (*num_freqs)++;
3970}
3971
3972
3973static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3974{
3975 struct wpa_bss *bss, *cbss;
3976 const int max_freqs = 10;
3977 int *freqs;
3978 int num_freqs = 0;
3979
3980 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3981 if (freqs == NULL)
3982 return NULL;
3983
3984 cbss = wpa_s->current_bss;
3985
3986 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3987 if (bss == cbss)
3988 continue;
3989 if (bss->ssid_len == cbss->ssid_len &&
3990 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
3991 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
3992 add_freq(freqs, &num_freqs, bss->freq);
3993 if (num_freqs == max_freqs)
3994 break;
3995 }
3996 }
3997
3998 if (num_freqs == 0) {
3999 os_free(freqs);
4000 freqs = NULL;
4001 }
4002
4003 return freqs;
4004}
4005
4006
4007void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4008{
4009 int timeout;
4010 int count;
4011 int *freqs = NULL;
4012
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004013 wpas_connect_work_done(wpa_s);
4014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004016 * Remove possible authentication timeout since the connection failed.
4017 */
4018 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4019
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004020 if (wpa_s->disconnected) {
4021 /*
4022 * There is no point in blacklisting the AP if this event is
4023 * generated based on local request to disconnect.
4024 */
4025 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4026 "indication since interface has been put into "
4027 "disconnected state");
4028 return;
4029 }
4030
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004031 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004032 * Add the failed BSSID into the blacklist and speed up next scan
4033 * attempt if there could be other APs that could accept association.
4034 * The current blacklist count indicates how many times we have tried
4035 * connecting to this AP and multiple attempts mean that other APs are
4036 * either not available or has already been tried, so that we can start
4037 * increasing the delay here to avoid constant scanning.
4038 */
4039 count = wpa_blacklist_add(wpa_s, bssid);
4040 if (count == 1 && wpa_s->current_bss) {
4041 /*
4042 * This BSS was not in the blacklist before. If there is
4043 * another BSS available for the same ESS, we should try that
4044 * next. Otherwise, we may as well try this one once more
4045 * before allowing other, likely worse, ESSes to be considered.
4046 */
4047 freqs = get_bss_freqs_in_ess(wpa_s);
4048 if (freqs) {
4049 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4050 "has been seen; try it next");
4051 wpa_blacklist_add(wpa_s, bssid);
4052 /*
4053 * On the next scan, go through only the known channels
4054 * used in this ESS based on previous scans to speed up
4055 * common load balancing use case.
4056 */
4057 os_free(wpa_s->next_scan_freqs);
4058 wpa_s->next_scan_freqs = freqs;
4059 }
4060 }
4061
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004062 /*
4063 * Add previous failure count in case the temporary blacklist was
4064 * cleared due to no other BSSes being available.
4065 */
4066 count += wpa_s->extra_blacklist_count;
4067
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004068 if (count > 3 && wpa_s->current_ssid) {
4069 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4070 "consider temporary network disabling");
4071 wpas_auth_failed(wpa_s);
4072 }
4073
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074 switch (count) {
4075 case 1:
4076 timeout = 100;
4077 break;
4078 case 2:
4079 timeout = 500;
4080 break;
4081 case 3:
4082 timeout = 1000;
4083 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004084 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004086 break;
4087 default:
4088 timeout = 10000;
4089 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004090 }
4091
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004092 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4093 "ms", count, timeout);
4094
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004095 /*
4096 * TODO: if more than one possible AP is available in scan results,
4097 * could try the other ones before requesting a new scan.
4098 */
4099 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4100 1000 * (timeout % 1000));
4101}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004102
4103
4104int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4105{
4106 return wpa_s->conf->ap_scan == 2 ||
4107 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4108}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004109
Dmitry Shmidt04949592012-07-19 12:16:46 -07004110
4111#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4112int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4113 struct wpa_ssid *ssid,
4114 const char *field,
4115 const char *value)
4116{
4117#ifdef IEEE8021X_EAPOL
4118 struct eap_peer_config *eap = &ssid->eap;
4119
4120 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4121 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4122 (const u8 *) value, os_strlen(value));
4123
4124 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4125 case WPA_CTRL_REQ_EAP_IDENTITY:
4126 os_free(eap->identity);
4127 eap->identity = (u8 *) os_strdup(value);
4128 eap->identity_len = os_strlen(value);
4129 eap->pending_req_identity = 0;
4130 if (ssid == wpa_s->current_ssid)
4131 wpa_s->reassociate = 1;
4132 break;
4133 case WPA_CTRL_REQ_EAP_PASSWORD:
4134 os_free(eap->password);
4135 eap->password = (u8 *) os_strdup(value);
4136 eap->password_len = os_strlen(value);
4137 eap->pending_req_password = 0;
4138 if (ssid == wpa_s->current_ssid)
4139 wpa_s->reassociate = 1;
4140 break;
4141 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4142 os_free(eap->new_password);
4143 eap->new_password = (u8 *) os_strdup(value);
4144 eap->new_password_len = os_strlen(value);
4145 eap->pending_req_new_password = 0;
4146 if (ssid == wpa_s->current_ssid)
4147 wpa_s->reassociate = 1;
4148 break;
4149 case WPA_CTRL_REQ_EAP_PIN:
4150 os_free(eap->pin);
4151 eap->pin = os_strdup(value);
4152 eap->pending_req_pin = 0;
4153 if (ssid == wpa_s->current_ssid)
4154 wpa_s->reassociate = 1;
4155 break;
4156 case WPA_CTRL_REQ_EAP_OTP:
4157 os_free(eap->otp);
4158 eap->otp = (u8 *) os_strdup(value);
4159 eap->otp_len = os_strlen(value);
4160 os_free(eap->pending_req_otp);
4161 eap->pending_req_otp = NULL;
4162 eap->pending_req_otp_len = 0;
4163 break;
4164 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4165 os_free(eap->private_key_passwd);
4166 eap->private_key_passwd = (u8 *) os_strdup(value);
4167 eap->pending_req_passphrase = 0;
4168 if (ssid == wpa_s->current_ssid)
4169 wpa_s->reassociate = 1;
4170 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004171 case WPA_CTRL_REQ_SIM:
4172 os_free(eap->external_sim_resp);
4173 eap->external_sim_resp = os_strdup(value);
4174 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004175 default:
4176 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4177 return -1;
4178 }
4179
4180 return 0;
4181#else /* IEEE8021X_EAPOL */
4182 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4183 return -1;
4184#endif /* IEEE8021X_EAPOL */
4185}
4186#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4187
4188
4189int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4190{
4191 int i;
4192 unsigned int drv_enc;
4193
4194 if (ssid == NULL)
4195 return 1;
4196
4197 if (ssid->disabled)
4198 return 1;
4199
4200 if (wpa_s && wpa_s->drv_capa_known)
4201 drv_enc = wpa_s->drv_enc;
4202 else
4203 drv_enc = (unsigned int) -1;
4204
4205 for (i = 0; i < NUM_WEP_KEYS; i++) {
4206 size_t len = ssid->wep_key_len[i];
4207 if (len == 0)
4208 continue;
4209 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4210 continue;
4211 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4212 continue;
4213 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4214 continue;
4215 return 1; /* invalid WEP key */
4216 }
4217
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004218 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4219 !ssid->ext_psk)
4220 return 1;
4221
Dmitry Shmidt04949592012-07-19 12:16:46 -07004222 return 0;
4223}
4224
4225
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004226int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004227{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004228 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004229 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004230 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004231 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004232 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004233}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004234
4235
4236void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4237{
4238 struct wpa_ssid *ssid = wpa_s->current_ssid;
4239 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004240 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004241
4242 if (ssid == NULL) {
4243 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4244 "SSID block");
4245 return;
4246 }
4247
4248 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4249 return;
4250
4251 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004252
4253#ifdef CONFIG_P2P
4254 if (ssid->p2p_group &&
4255 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4256 /*
4257 * Skip the wait time since there is a short timeout on the
4258 * connection to a P2P group.
4259 */
4260 return;
4261 }
4262#endif /* CONFIG_P2P */
4263
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004264 if (ssid->auth_failures > 50)
4265 dur = 300;
4266 else if (ssid->auth_failures > 20)
4267 dur = 120;
4268 else if (ssid->auth_failures > 10)
4269 dur = 60;
4270 else if (ssid->auth_failures > 5)
4271 dur = 30;
4272 else if (ssid->auth_failures > 1)
4273 dur = 20;
4274 else
4275 dur = 10;
4276
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004277 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004278 if (now.sec + dur <= ssid->disabled_until.sec)
4279 return;
4280
4281 ssid->disabled_until.sec = now.sec + dur;
4282
4283 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4284 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4285 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4286 ssid->auth_failures, dur);
4287}
4288
4289
4290void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4291 struct wpa_ssid *ssid, int clear_failures)
4292{
4293 if (ssid == NULL)
4294 return;
4295
4296 if (ssid->disabled_until.sec) {
4297 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4298 "id=%d ssid=\"%s\"",
4299 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4300 }
4301 ssid->disabled_until.sec = 0;
4302 ssid->disabled_until.usec = 0;
4303 if (clear_failures)
4304 ssid->auth_failures = 0;
4305}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004306
4307
4308int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4309{
4310 size_t i;
4311
4312 if (wpa_s->disallow_aps_bssid == NULL)
4313 return 0;
4314
4315 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4316 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4317 bssid, ETH_ALEN) == 0)
4318 return 1;
4319 }
4320
4321 return 0;
4322}
4323
4324
4325int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4326 size_t ssid_len)
4327{
4328 size_t i;
4329
4330 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4331 return 0;
4332
4333 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4334 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4335 if (ssid_len == s->ssid_len &&
4336 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4337 return 1;
4338 }
4339
4340 return 0;
4341}
4342
4343
4344/**
4345 * wpas_request_connection - Request a new connection
4346 * @wpa_s: Pointer to the network interface
4347 *
4348 * This function is used to request a new connection to be found. It will mark
4349 * the interface to allow reassociation and request a new scan to find a
4350 * suitable network to connect to.
4351 */
4352void wpas_request_connection(struct wpa_supplicant *wpa_s)
4353{
4354 wpa_s->normal_scans = 0;
4355 wpa_supplicant_reinit_autoscan(wpa_s);
4356 wpa_s->extra_blacklist_count = 0;
4357 wpa_s->disconnected = 0;
4358 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004359
4360 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4361 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004362}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004363
4364
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004365void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4366 int *freq_array, unsigned int len)
4367{
4368 unsigned int i;
4369
4370 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4371 len, title);
4372 for (i = 0; i < len; i++)
4373 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4374}
4375
4376
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004377/*
4378 * Find the operating frequencies of any of the virtual interfaces that
4379 * are using the same radio as the current interface.
4380 */
4381int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4382 int *freq_array, unsigned int len)
4383{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004384 struct wpa_supplicant *ifs;
4385 u8 bssid[ETH_ALEN];
4386 int freq;
4387 unsigned int idx = 0, i;
4388
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004389 wpa_dbg(wpa_s, MSG_DEBUG,
4390 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004391 os_memset(freq_array, 0, sizeof(int) * len);
4392
4393 /* First add the frequency of the local interface */
4394 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4395 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4396 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4397 freq_array[idx++] = wpa_s->current_ssid->frequency;
4398 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4399 freq_array[idx++] = wpa_s->assoc_freq;
4400 }
4401
4402 /* If get_radio_name is not supported, use only the local freq */
4403 if (!wpa_s->driver->get_radio_name) {
4404 freq = wpa_drv_shared_freq(wpa_s);
4405 if (freq > 0 && idx < len &&
4406 (idx == 0 || freq_array[0] != freq))
4407 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004408 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004409 return idx;
4410 }
4411
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004412 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4413 radio_list) {
4414 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004415 continue;
4416
4417 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4418 continue;
4419
4420 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4421 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4422 freq = ifs->current_ssid->frequency;
4423 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4424 freq = ifs->assoc_freq;
4425 else
4426 continue;
4427
4428 /* Hold only distinct freqs */
4429 for (i = 0; i < idx; i++)
4430 if (freq_array[i] == freq)
4431 break;
4432
4433 if (i == idx)
4434 freq_array[idx++] = freq;
4435 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004436
4437 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004438 return idx;
4439}