blob: 35f56936ef869112a3f1912e5cd0cb6e428cf508 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 *
8 * This file implements functions for registering and unregistering
9 * %wpa_supplicant interfaces. In addition, this file contains number of
10 * functions for managing network connections.
11 */
12
13#include "includes.h"
14
15#include "common.h"
16#include "crypto/random.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080017#include "crypto/sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "eapol_supp/eapol_supp_sm.h"
19#include "eap_peer/eap.h"
Dmitry Shmidt34af3062013-07-11 10:46:32 -070020#include "eap_peer/eap_proxy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "eap_server/eap_methods.h"
22#include "rsn_supp/wpa.h"
23#include "eloop.h"
24#include "config.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070025#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "l2_packet/l2_packet.h"
27#include "wpa_supplicant_i.h"
28#include "driver_i.h"
29#include "ctrl_iface.h"
30#include "pcsc_funcs.h"
31#include "common/version.h"
32#include "rsn_supp/preauth.h"
33#include "rsn_supp/pmksa_cache.h"
34#include "common/wpa_ctrl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035#include "common/ieee802_11_defs.h"
36#include "p2p/p2p.h"
37#include "blacklist.h"
38#include "wpas_glue.h"
39#include "wps_supplicant.h"
40#include "ibss_rsn.h"
41#include "sme.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042#include "gas_query.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "ap.h"
44#include "p2p_supplicant.h"
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070045#include "wifi_display.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "notify.h"
47#include "bgscan.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070048#include "autoscan.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070049#include "bss.h"
50#include "scan.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080051#include "offchannel.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070052#include "hs20_supplicant.h"
Dmitry Shmidt44c95782013-05-17 09:51:35 -070053#include "wnm_sta.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054
55const char *wpa_supplicant_version =
56"wpa_supplicant v" VERSION_STR "\n"
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -080057"Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070058
59const char *wpa_supplicant_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080060"This software may be distributed under the terms of the BSD license.\n"
61"See README for more details.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070062#ifdef EAP_TLS_OPENSSL
63"\nThis product includes software developed by the OpenSSL Project\n"
64"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n"
65#endif /* EAP_TLS_OPENSSL */
66;
67
68#ifndef CONFIG_NO_STDOUT_DEBUG
69/* Long text divided into parts in order to fit in C89 strings size limits. */
70const char *wpa_supplicant_full_license1 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080071"";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070072const char *wpa_supplicant_full_license2 =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080073"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074"\n"
75"Redistribution and use in source and binary forms, with or without\n"
76"modification, are permitted provided that the following conditions are\n"
77"met:\n"
78"\n";
79const char *wpa_supplicant_full_license3 =
80"1. Redistributions of source code must retain the above copyright\n"
81" notice, this list of conditions and the following disclaimer.\n"
82"\n"
83"2. Redistributions in binary form must reproduce the above copyright\n"
84" notice, this list of conditions and the following disclaimer in the\n"
85" documentation and/or other materials provided with the distribution.\n"
86"\n";
87const char *wpa_supplicant_full_license4 =
88"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
89" names of its contributors may be used to endorse or promote products\n"
90" derived from this software without specific prior written permission.\n"
91"\n"
92"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
93"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
94"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
95"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n";
96const char *wpa_supplicant_full_license5 =
97"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
98"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
99"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
100"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
101"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
102"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
103"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
104"\n";
105#endif /* CONFIG_NO_STDOUT_DEBUG */
106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107/* Configure default/group WEP keys for static WEP */
108int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
109{
110 int i, set = 0;
111
112 for (i = 0; i < NUM_WEP_KEYS; i++) {
113 if (ssid->wep_key_len[i] == 0)
114 continue;
115
116 set = 1;
117 wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL,
118 i, i == ssid->wep_tx_keyidx, NULL, 0,
119 ssid->wep_key[i], ssid->wep_key_len[i]);
120 }
121
122 return set;
123}
124
125
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700126int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s,
127 struct wpa_ssid *ssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128{
129 u8 key[32];
130 size_t keylen;
131 enum wpa_alg alg;
132 u8 seq[6] = { 0 };
133
134 /* IBSS/WPA-None uses only one key (Group) for both receiving and
135 * sending unicast and multicast packets. */
136
137 if (ssid->mode != WPAS_MODE_IBSS) {
138 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not "
139 "IBSS/ad-hoc) for WPA-None", ssid->mode);
140 return -1;
141 }
142
143 if (!ssid->psk_set) {
144 wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for "
145 "WPA-None");
146 return -1;
147 }
148
149 switch (wpa_s->group_cipher) {
150 case WPA_CIPHER_CCMP:
151 os_memcpy(key, ssid->psk, 16);
152 keylen = 16;
153 alg = WPA_ALG_CCMP;
154 break;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700155 case WPA_CIPHER_GCMP:
156 os_memcpy(key, ssid->psk, 16);
157 keylen = 16;
158 alg = WPA_ALG_GCMP;
159 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160 case WPA_CIPHER_TKIP:
161 /* WPA-None uses the same Michael MIC key for both TX and RX */
162 os_memcpy(key, ssid->psk, 16 + 8);
163 os_memcpy(key + 16 + 8, ssid->psk + 16, 8);
164 keylen = 32;
165 alg = WPA_ALG_TKIP;
166 break;
167 default:
168 wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for "
169 "WPA-None", wpa_s->group_cipher);
170 return -1;
171 }
172
173 /* TODO: should actually remember the previously used seq#, both for TX
174 * and RX from each STA.. */
175
176 return wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen);
177}
178
179
180static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
181{
182 struct wpa_supplicant *wpa_s = eloop_ctx;
183 const u8 *bssid = wpa_s->bssid;
184 if (is_zero_ether_addr(bssid))
185 bssid = wpa_s->pending_bssid;
186 wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
187 MAC2STR(bssid));
188 wpa_blacklist_add(wpa_s, bssid);
189 wpa_sm_notify_disassoc(wpa_s->wpa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800190 wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700191 wpa_s->reassociate = 1;
192
193 /*
194 * If we timed out, the AP or the local radio may be busy.
195 * So, wait a second until scanning again.
196 */
197 wpa_supplicant_req_scan(wpa_s, 1, 0);
198}
199
200
201/**
202 * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication
203 * @wpa_s: Pointer to wpa_supplicant data
204 * @sec: Number of seconds after which to time out authentication
205 * @usec: Number of microseconds after which to time out authentication
206 *
207 * This function is used to schedule a timeout for the current authentication
208 * attempt.
209 */
210void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
211 int sec, int usec)
212{
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700213 if (wpa_s->conf->ap_scan == 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED))
215 return;
216
217 wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec "
218 "%d usec", sec, usec);
219 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
220 eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL);
221}
222
223
224/**
225 * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout
226 * @wpa_s: Pointer to wpa_supplicant data
227 *
228 * This function is used to cancel authentication timeout scheduled with
229 * wpa_supplicant_req_auth_timeout() and it is called when authentication has
230 * been completed.
231 */
232void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
233{
234 wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
235 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
236 wpa_blacklist_del(wpa_s, wpa_s->bssid);
237}
238
239
240/**
241 * wpa_supplicant_initiate_eapol - Configure EAPOL state machine
242 * @wpa_s: Pointer to wpa_supplicant data
243 *
244 * This function is used to configure EAPOL state machine based on the selected
245 * authentication mode.
246 */
247void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s)
248{
249#ifdef IEEE8021X_EAPOL
250 struct eapol_config eapol_conf;
251 struct wpa_ssid *ssid = wpa_s->current_ssid;
252
253#ifdef CONFIG_IBSS_RSN
254 if (ssid->mode == WPAS_MODE_IBSS &&
255 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
256 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
257 /*
258 * RSN IBSS authentication is per-STA and we can disable the
259 * per-BSSID EAPOL authentication.
260 */
261 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
262 eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
263 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
264 return;
265 }
266#endif /* CONFIG_IBSS_RSN */
267
268 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
269 eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE);
270
271 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
272 wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE)
273 eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized);
274 else
275 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
276
277 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
278 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
279 eapol_conf.accept_802_1x_keys = 1;
280 eapol_conf.required_keys = 0;
281 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) {
282 eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST;
283 }
284 if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) {
285 eapol_conf.required_keys |=
286 EAPOL_REQUIRE_KEY_BROADCAST;
287 }
288
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700289 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700290 eapol_conf.required_keys = 0;
291 }
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700292 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700293 eapol_conf.workaround = ssid->eap_workaround;
294 eapol_conf.eap_disabled =
295 !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) &&
296 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA &&
297 wpa_s->key_mgmt != WPA_KEY_MGMT_WPS;
Dmitry Shmidt051af732013-10-22 13:52:46 -0700298 eapol_conf.external_sim = wpa_s->conf->external_sim;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
300#endif /* IEEE8021X_EAPOL */
301}
302
303
304/**
305 * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode
306 * @wpa_s: Pointer to wpa_supplicant data
307 * @ssid: Configuration data for the network
308 *
309 * This function is used to configure WPA state machine and related parameters
310 * to a mode where WPA is not enabled. This is called as part of the
311 * authentication configuration when the selected network does not use WPA.
312 */
313void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s,
314 struct wpa_ssid *ssid)
315{
316 int i;
317
318 if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
319 wpa_s->key_mgmt = WPA_KEY_MGMT_WPS;
320 else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)
321 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA;
322 else
323 wpa_s->key_mgmt = WPA_KEY_MGMT_NONE;
324 wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0);
325 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0);
326 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
327 wpa_s->pairwise_cipher = WPA_CIPHER_NONE;
328 wpa_s->group_cipher = WPA_CIPHER_NONE;
329 wpa_s->mgmt_group_cipher = 0;
330
331 for (i = 0; i < NUM_WEP_KEYS; i++) {
332 if (ssid->wep_key_len[i] > 5) {
333 wpa_s->pairwise_cipher = WPA_CIPHER_WEP104;
334 wpa_s->group_cipher = WPA_CIPHER_WEP104;
335 break;
336 } else if (ssid->wep_key_len[i] > 0) {
337 wpa_s->pairwise_cipher = WPA_CIPHER_WEP40;
338 wpa_s->group_cipher = WPA_CIPHER_WEP40;
339 break;
340 }
341 }
342
343 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0);
344 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
345 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
346 wpa_s->pairwise_cipher);
347 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
348#ifdef CONFIG_IEEE80211W
349 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
350 wpa_s->mgmt_group_cipher);
351#endif /* CONFIG_IEEE80211W */
352
353 pmksa_cache_clear_current(wpa_s->wpa);
354}
355
356
Dmitry Shmidt04949592012-07-19 12:16:46 -0700357void free_hw_features(struct wpa_supplicant *wpa_s)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800358{
359 int i;
360 if (wpa_s->hw.modes == NULL)
361 return;
362
363 for (i = 0; i < wpa_s->hw.num_modes; i++) {
364 os_free(wpa_s->hw.modes[i].channels);
365 os_free(wpa_s->hw.modes[i].rates);
366 }
367
368 os_free(wpa_s->hw.modes);
369 wpa_s->hw.modes = NULL;
370}
371
372
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700373static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
374{
375 bgscan_deinit(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700376 autoscan_deinit(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700377 scard_deinit(wpa_s->scard);
378 wpa_s->scard = NULL;
379 wpa_sm_set_scard_ctx(wpa_s->wpa, NULL);
380 eapol_sm_register_scard_ctx(wpa_s->eapol, NULL);
381 l2_packet_deinit(wpa_s->l2);
382 wpa_s->l2 = NULL;
383 if (wpa_s->l2_br) {
384 l2_packet_deinit(wpa_s->l2_br);
385 wpa_s->l2_br = NULL;
386 }
387
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700388 if (wpa_s->conf != NULL) {
389 struct wpa_ssid *ssid;
390 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
391 wpas_notify_network_removed(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700392 }
393
394 os_free(wpa_s->confname);
395 wpa_s->confname = NULL;
396
Jouni Malinen5d1c8ad2013-04-23 12:34:56 -0700397 os_free(wpa_s->confanother);
398 wpa_s->confanother = NULL;
399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700400 wpa_sm_set_eapol(wpa_s->wpa, NULL);
401 eapol_sm_deinit(wpa_s->eapol);
402 wpa_s->eapol = NULL;
403
404 rsn_preauth_deinit(wpa_s->wpa);
405
406#ifdef CONFIG_TDLS
407 wpa_tdls_deinit(wpa_s->wpa);
408#endif /* CONFIG_TDLS */
409
410 pmksa_candidate_free(wpa_s->wpa);
411 wpa_sm_deinit(wpa_s->wpa);
412 wpa_s->wpa = NULL;
413 wpa_blacklist_clear(wpa_s);
414
415 wpa_bss_deinit(wpa_s);
416
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -0700417 wpa_supplicant_cancel_delayed_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700418 wpa_supplicant_cancel_scan(wpa_s);
419 wpa_supplicant_cancel_auth_timeout(wpa_s);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800420 eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL);
421#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT
422 eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report,
423 wpa_s, NULL);
424#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700425
426 wpas_wps_deinit(wpa_s);
427
428 wpabuf_free(wpa_s->pending_eapol_rx);
429 wpa_s->pending_eapol_rx = NULL;
430
431#ifdef CONFIG_IBSS_RSN
432 ibss_rsn_deinit(wpa_s->ibss_rsn);
433 wpa_s->ibss_rsn = NULL;
434#endif /* CONFIG_IBSS_RSN */
435
436 sme_deinit(wpa_s);
437
438#ifdef CONFIG_AP
439 wpa_supplicant_ap_deinit(wpa_s);
440#endif /* CONFIG_AP */
441
442#ifdef CONFIG_P2P
443 wpas_p2p_deinit(wpa_s);
444#endif /* CONFIG_P2P */
445
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800446#ifdef CONFIG_OFFCHANNEL
447 offchannel_deinit(wpa_s);
448#endif /* CONFIG_OFFCHANNEL */
449
450 wpa_supplicant_cancel_sched_scan(wpa_s);
451
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700452 os_free(wpa_s->next_scan_freqs);
453 wpa_s->next_scan_freqs = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800454
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800455 os_free(wpa_s->manual_scan_freqs);
456 wpa_s->manual_scan_freqs = NULL;
457
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800458 gas_query_deinit(wpa_s->gas);
459 wpa_s->gas = NULL;
460
461 free_hw_features(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700462
463 os_free(wpa_s->bssid_filter);
464 wpa_s->bssid_filter = NULL;
465
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800466 os_free(wpa_s->disallow_aps_bssid);
467 wpa_s->disallow_aps_bssid = NULL;
468 os_free(wpa_s->disallow_aps_ssid);
469 wpa_s->disallow_aps_ssid = NULL;
470
Dmitry Shmidt04949592012-07-19 12:16:46 -0700471 wnm_bss_keep_alive_deinit(wpa_s);
Dmitry Shmidt44c95782013-05-17 09:51:35 -0700472#ifdef CONFIG_WNM
473 wnm_deallocate_memory(wpa_s);
474#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475
476 ext_password_deinit(wpa_s->ext_pw);
477 wpa_s->ext_pw = NULL;
478
479 wpabuf_free(wpa_s->last_gas_resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800480 wpa_s->last_gas_resp = NULL;
481 wpabuf_free(wpa_s->prev_gas_resp);
482 wpa_s->prev_gas_resp = NULL;
Dmitry Shmidt9bce59c2012-09-11 15:06:38 -0700483
484 os_free(wpa_s->last_scan_res);
485 wpa_s->last_scan_res = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486}
487
488
489/**
490 * wpa_clear_keys - Clear keys configured for the driver
491 * @wpa_s: Pointer to wpa_supplicant data
492 * @addr: Previously used BSSID or %NULL if not available
493 *
494 * This function clears the encryption keys that has been previously configured
495 * for the driver.
496 */
497void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
498{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800499 int i, max;
500
501#ifdef CONFIG_IEEE80211W
502 max = 6;
503#else /* CONFIG_IEEE80211W */
504 max = 4;
505#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700506
507 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800508 for (i = 0; i < max; i++) {
509 if (wpa_s->keys_cleared & BIT(i))
510 continue;
511 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
512 NULL, 0);
513 }
514 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
515 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
517 0);
518 /* MLME-SETPROTECTION.request(None) */
519 wpa_drv_mlme_setprotection(
520 wpa_s, addr,
521 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
522 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
523 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800524 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525}
526
527
528/**
529 * wpa_supplicant_state_txt - Get the connection state name as a text string
530 * @state: State (wpa_state; WPA_*)
531 * Returns: The state name as a printable text string
532 */
533const char * wpa_supplicant_state_txt(enum wpa_states state)
534{
535 switch (state) {
536 case WPA_DISCONNECTED:
537 return "DISCONNECTED";
538 case WPA_INACTIVE:
539 return "INACTIVE";
540 case WPA_INTERFACE_DISABLED:
541 return "INTERFACE_DISABLED";
542 case WPA_SCANNING:
543 return "SCANNING";
544 case WPA_AUTHENTICATING:
545 return "AUTHENTICATING";
546 case WPA_ASSOCIATING:
547 return "ASSOCIATING";
548 case WPA_ASSOCIATED:
549 return "ASSOCIATED";
550 case WPA_4WAY_HANDSHAKE:
551 return "4WAY_HANDSHAKE";
552 case WPA_GROUP_HANDSHAKE:
553 return "GROUP_HANDSHAKE";
554 case WPA_COMPLETED:
555 return "COMPLETED";
556 default:
557 return "UNKNOWN";
558 }
559}
560
561
562#ifdef CONFIG_BGSCAN
563
564static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
565{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800566 const char *name;
567
568 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
569 name = wpa_s->current_ssid->bgscan;
570 else
571 name = wpa_s->conf->bgscan;
572 if (name == NULL)
573 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800574 if (wpas_driver_bss_selection(wpa_s))
575 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
577 return;
578
579 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800580 if (wpa_s->current_ssid) {
581 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700582 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
583 "bgscan");
584 /*
585 * Live without bgscan; it is only used as a roaming
586 * optimization, so the initial connection is not
587 * affected.
588 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700589 } else {
590 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700592 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
593 0);
594 if (scan_res) {
595 bgscan_notify_scan(wpa_s, scan_res);
596 wpa_scan_results_free(scan_res);
597 }
598 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 } else
600 wpa_s->bgscan_ssid = NULL;
601}
602
603
604static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
605{
606 if (wpa_s->bgscan_ssid != NULL) {
607 bgscan_deinit(wpa_s);
608 wpa_s->bgscan_ssid = NULL;
609 }
610}
611
612#endif /* CONFIG_BGSCAN */
613
614
Dmitry Shmidt04949592012-07-19 12:16:46 -0700615static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
616{
617 if (autoscan_init(wpa_s, 0))
618 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
619}
620
621
622static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
623{
624 autoscan_deinit(wpa_s);
625}
626
627
628void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
629{
630 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
631 wpa_s->wpa_state == WPA_SCANNING) {
632 autoscan_deinit(wpa_s);
633 wpa_supplicant_start_autoscan(wpa_s);
634 }
635}
636
637
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700638/**
639 * wpa_supplicant_set_state - Set current connection state
640 * @wpa_s: Pointer to wpa_supplicant data
641 * @state: The new connection state
642 *
643 * This function is called whenever the connection state changes, e.g.,
644 * association is completed for WPA/WPA2 4-Way Handshake is started.
645 */
646void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
647 enum wpa_states state)
648{
649 enum wpa_states old_state = wpa_s->wpa_state;
650
651 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
652 wpa_supplicant_state_txt(wpa_s->wpa_state),
653 wpa_supplicant_state_txt(state));
654
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800655 if (state == WPA_INTERFACE_DISABLED) {
656 /* Assure normal scan when interface is restored */
657 wpa_s->normal_scans = 0;
658 }
659
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800660 if (state == WPA_COMPLETED)
661 wpas_connect_work_done(wpa_s);
662
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663 if (state != WPA_SCANNING)
664 wpa_supplicant_notify_scanning(wpa_s, 0);
665
666 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700668#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700669 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800670 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800671 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672 ssid ? ssid->id : -1,
673 ssid && ssid->id_str ? ssid->id_str : "");
674#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700675 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800676 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678 wpa_drv_set_operstate(wpa_s, 1);
679#ifndef IEEE8021X_EAPOL
680 wpa_drv_set_supp_port(wpa_s, 1);
681#endif /* IEEE8021X_EAPOL */
682 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700683 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684#ifdef CONFIG_P2P
685 wpas_p2p_completed(wpa_s);
686#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700687
688 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
690 state == WPA_ASSOCIATED) {
691 wpa_s->new_connection = 1;
692 wpa_drv_set_operstate(wpa_s, 0);
693#ifndef IEEE8021X_EAPOL
694 wpa_drv_set_supp_port(wpa_s, 0);
695#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700696 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 }
698 wpa_s->wpa_state = state;
699
700#ifdef CONFIG_BGSCAN
701 if (state == WPA_COMPLETED)
702 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800703 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700704 wpa_supplicant_stop_bgscan(wpa_s);
705#endif /* CONFIG_BGSCAN */
706
Dmitry Shmidt04949592012-07-19 12:16:46 -0700707 if (state == WPA_AUTHENTICATING)
708 wpa_supplicant_stop_autoscan(wpa_s);
709
710 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
711 wpa_supplicant_start_autoscan(wpa_s);
712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700713 if (wpa_s->wpa_state != old_state) {
714 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
715
716 if (wpa_s->wpa_state == WPA_COMPLETED ||
717 old_state == WPA_COMPLETED)
718 wpas_notify_auth_changed(wpa_s);
719 }
720}
721
722
723void wpa_supplicant_terminate_proc(struct wpa_global *global)
724{
725 int pending = 0;
726#ifdef CONFIG_WPS
727 struct wpa_supplicant *wpa_s = global->ifaces;
728 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800729 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700730#ifdef CONFIG_P2P
731 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
732 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
733 wpas_p2p_disconnect(wpa_s);
734#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 if (wpas_wps_terminate_pending(wpa_s) == 1)
736 pending = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800737 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 }
739#endif /* CONFIG_WPS */
740 if (pending)
741 return;
742 eloop_terminate();
743}
744
745
746static void wpa_supplicant_terminate(int sig, void *signal_ctx)
747{
748 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749 wpa_supplicant_terminate_proc(global);
750}
751
752
753void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
754{
755 enum wpa_states old_state = wpa_s->wpa_state;
756
757 wpa_s->pairwise_cipher = 0;
758 wpa_s->group_cipher = 0;
759 wpa_s->mgmt_group_cipher = 0;
760 wpa_s->key_mgmt = 0;
761 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700762 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763
764 if (wpa_s->wpa_state != old_state)
765 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
766}
767
768
769/**
770 * wpa_supplicant_reload_configuration - Reload configuration data
771 * @wpa_s: Pointer to wpa_supplicant data
772 * Returns: 0 on success or -1 if configuration parsing failed
773 *
774 * This function can be used to request that the configuration data is reloaded
775 * (e.g., after configuration file change). This function is reloading
776 * configuration only for one interface, so this may need to be called multiple
777 * times if %wpa_supplicant is controlling multiple interfaces and all
778 * interfaces need reconfiguration.
779 */
780int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
781{
782 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700783 int reconf_ctrl;
784 int old_ap_scan;
785
786 if (wpa_s->confname == NULL)
787 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700788 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789 if (conf == NULL) {
790 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
791 "file '%s' - exiting", wpa_s->confname);
792 return -1;
793 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700794 wpa_config_read(wpa_s->confanother, conf);
795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 conf->changed_parameters = (unsigned int) -1;
797
798 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
799 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
800 os_strcmp(conf->ctrl_interface,
801 wpa_s->conf->ctrl_interface) != 0);
802
803 if (reconf_ctrl && wpa_s->ctrl_iface) {
804 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
805 wpa_s->ctrl_iface = NULL;
806 }
807
808 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800809 if (wpa_s->current_ssid) {
810 wpa_supplicant_deauthenticate(wpa_s,
811 WLAN_REASON_DEAUTH_LEAVING);
812 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700813
814 /*
815 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
816 * pkcs11_engine_path, pkcs11_module_path.
817 */
818 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
819 /*
820 * Clear forced success to clear EAP state for next
821 * authentication.
822 */
823 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
824 }
825 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
826 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800827 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
829 rsn_preauth_deinit(wpa_s->wpa);
830
831 old_ap_scan = wpa_s->conf->ap_scan;
832 wpa_config_free(wpa_s->conf);
833 wpa_s->conf = conf;
834 if (old_ap_scan != wpa_s->conf->ap_scan)
835 wpas_notify_ap_scan_changed(wpa_s);
836
837 if (reconf_ctrl)
838 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
839
840 wpa_supplicant_update_config(wpa_s);
841
842 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700843 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700844 wpa_s->reassociate = 1;
845 wpa_supplicant_req_scan(wpa_s, 0, 0);
846 }
847 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
848 return 0;
849}
850
851
852static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
853{
854 struct wpa_global *global = signal_ctx;
855 struct wpa_supplicant *wpa_s;
856 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
857 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
858 sig);
859 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
860 wpa_supplicant_terminate_proc(global);
861 }
862 }
863}
864
865
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
867 struct wpa_ssid *ssid,
868 struct wpa_ie_data *ie)
869{
870 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
871 if (ret) {
872 if (ret == -2) {
873 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
874 "from association info");
875 }
876 return -1;
877 }
878
879 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
880 "cipher suites");
881 if (!(ie->group_cipher & ssid->group_cipher)) {
882 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
883 "cipher 0x%x (mask 0x%x) - reject",
884 ie->group_cipher, ssid->group_cipher);
885 return -1;
886 }
887 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
888 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
889 "cipher 0x%x (mask 0x%x) - reject",
890 ie->pairwise_cipher, ssid->pairwise_cipher);
891 return -1;
892 }
893 if (!(ie->key_mgmt & ssid->key_mgmt)) {
894 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
895 "management 0x%x (mask 0x%x) - reject",
896 ie->key_mgmt, ssid->key_mgmt);
897 return -1;
898 }
899
900#ifdef CONFIG_IEEE80211W
901 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800902 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
903 wpa_s->conf->pmf : ssid->ieee80211w) ==
904 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700905 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
906 "that does not support management frame protection - "
907 "reject");
908 return -1;
909 }
910#endif /* CONFIG_IEEE80211W */
911
912 return 0;
913}
914
915
916/**
917 * wpa_supplicant_set_suites - Set authentication and encryption parameters
918 * @wpa_s: Pointer to wpa_supplicant data
919 * @bss: Scan results for the selected BSS, or %NULL if not available
920 * @ssid: Configuration data for the selected network
921 * @wpa_ie: Buffer for the WPA/RSN IE
922 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
923 * used buffer length in case the functions returns success.
924 * Returns: 0 on success or -1 on failure
925 *
926 * This function is used to configure authentication and encryption parameters
927 * based on the network configuration and scan result for the selected BSS (if
928 * available).
929 */
930int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
931 struct wpa_bss *bss, struct wpa_ssid *ssid,
932 u8 *wpa_ie, size_t *wpa_ie_len)
933{
934 struct wpa_ie_data ie;
935 int sel, proto;
936 const u8 *bss_wpa, *bss_rsn;
937
938 if (bss) {
939 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
940 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
941 } else
942 bss_wpa = bss_rsn = NULL;
943
944 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
945 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
946 (ie.group_cipher & ssid->group_cipher) &&
947 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
948 (ie.key_mgmt & ssid->key_mgmt)) {
949 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
950 proto = WPA_PROTO_RSN;
951 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
952 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
953 (ie.group_cipher & ssid->group_cipher) &&
954 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
955 (ie.key_mgmt & ssid->key_mgmt)) {
956 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
957 proto = WPA_PROTO_WPA;
958 } else if (bss) {
959 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
960 return -1;
961 } else {
962 if (ssid->proto & WPA_PROTO_RSN)
963 proto = WPA_PROTO_RSN;
964 else
965 proto = WPA_PROTO_WPA;
966 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
967 os_memset(&ie, 0, sizeof(ie));
968 ie.group_cipher = ssid->group_cipher;
969 ie.pairwise_cipher = ssid->pairwise_cipher;
970 ie.key_mgmt = ssid->key_mgmt;
971#ifdef CONFIG_IEEE80211W
972 ie.mgmt_group_cipher =
973 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
974 WPA_CIPHER_AES_128_CMAC : 0;
975#endif /* CONFIG_IEEE80211W */
976 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
977 "based on configuration");
978 } else
979 proto = ie.proto;
980 }
981
982 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
983 "pairwise %d key_mgmt %d proto %d",
984 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
985#ifdef CONFIG_IEEE80211W
986 if (ssid->ieee80211w) {
987 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
988 ie.mgmt_group_cipher);
989 }
990#endif /* CONFIG_IEEE80211W */
991
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800992 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
994 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
995 !!(ssid->proto & WPA_PROTO_RSN));
996
997 if (bss || !wpa_s->ap_ies_from_associnfo) {
998 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
999 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1000 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1001 bss_rsn ? 2 + bss_rsn[1] : 0))
1002 return -1;
1003 }
1004
1005 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001006 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1007 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1009 "cipher");
1010 return -1;
1011 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001012 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1013 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014
1015 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001016 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1017 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1019 "cipher");
1020 return -1;
1021 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001022 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1023 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001024
1025 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001026#ifdef CONFIG_SAE
1027 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1028 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1029#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (0) {
1031#ifdef CONFIG_IEEE80211R
1032 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1033 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1034 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1035 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1036 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1037 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1038#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001039#ifdef CONFIG_SAE
1040 } else if (sel & WPA_KEY_MGMT_SAE) {
1041 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1042 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1043 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1044 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1045 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1046#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047#ifdef CONFIG_IEEE80211W
1048 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1049 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1050 wpa_dbg(wpa_s, MSG_DEBUG,
1051 "WPA: using KEY_MGMT 802.1X with SHA256");
1052 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1053 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1054 wpa_dbg(wpa_s, MSG_DEBUG,
1055 "WPA: using KEY_MGMT PSK with SHA256");
1056#endif /* CONFIG_IEEE80211W */
1057 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1058 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1059 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1060 } else if (sel & WPA_KEY_MGMT_PSK) {
1061 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1062 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1063 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1064 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1065 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
1066 } else {
1067 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1068 "authenticated key management type");
1069 return -1;
1070 }
1071
1072 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1073 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1074 wpa_s->pairwise_cipher);
1075 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1076
1077#ifdef CONFIG_IEEE80211W
1078 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001079 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1080 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001081 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1082 sel = 0;
1083 if (sel & WPA_CIPHER_AES_128_CMAC) {
1084 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1085 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1086 "AES-128-CMAC");
1087 } else {
1088 wpa_s->mgmt_group_cipher = 0;
1089 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1090 }
1091 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1092 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001093 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1094 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1095 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096#endif /* CONFIG_IEEE80211W */
1097
1098 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1099 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1100 return -1;
1101 }
1102
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001103 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001104 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001105#ifndef CONFIG_NO_PBKDF2
1106 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1107 ssid->passphrase) {
1108 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001109 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1110 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001111 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1112 psk, PMK_LEN);
1113 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1114 }
1115#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001116#ifdef CONFIG_EXT_PASSWORD
1117 if (ssid->ext_psk) {
1118 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1119 ssid->ext_psk);
1120 char pw_str[64 + 1];
1121 u8 psk[PMK_LEN];
1122
1123 if (pw == NULL) {
1124 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1125 "found from external storage");
1126 return -1;
1127 }
1128
1129 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1130 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1131 "PSK length %d in external storage",
1132 (int) wpabuf_len(pw));
1133 ext_password_free(pw);
1134 return -1;
1135 }
1136
1137 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1138 pw_str[wpabuf_len(pw)] = '\0';
1139
1140#ifndef CONFIG_NO_PBKDF2
1141 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1142 {
1143 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1144 4096, psk, PMK_LEN);
1145 os_memset(pw_str, 0, sizeof(pw_str));
1146 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1147 "external passphrase)",
1148 psk, PMK_LEN);
1149 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1150 } else
1151#endif /* CONFIG_NO_PBKDF2 */
1152 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1153 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1154 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1155 "Invalid PSK hex string");
1156 os_memset(pw_str, 0, sizeof(pw_str));
1157 ext_password_free(pw);
1158 return -1;
1159 }
1160 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1161 } else {
1162 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1163 "PSK available");
1164 os_memset(pw_str, 0, sizeof(pw_str));
1165 ext_password_free(pw);
1166 return -1;
1167 }
1168
1169 os_memset(pw_str, 0, sizeof(pw_str));
1170 ext_password_free(pw);
1171 }
1172#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001173 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1175
1176 return 0;
1177}
1178
1179
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001180static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1181{
1182 *pos = 0x00;
1183
1184 switch (idx) {
1185 case 0: /* Bits 0-7 */
1186 break;
1187 case 1: /* Bits 8-15 */
1188 break;
1189 case 2: /* Bits 16-23 */
1190#ifdef CONFIG_WNM
1191 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1192 *pos |= 0x08; /* Bit 19 - BSS Transition */
1193#endif /* CONFIG_WNM */
1194 break;
1195 case 3: /* Bits 24-31 */
1196#ifdef CONFIG_WNM
1197 *pos |= 0x02; /* Bit 25 - SSID List */
1198#endif /* CONFIG_WNM */
1199#ifdef CONFIG_INTERWORKING
1200 if (wpa_s->conf->interworking)
1201 *pos |= 0x80; /* Bit 31 - Interworking */
1202#endif /* CONFIG_INTERWORKING */
1203 break;
1204 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001205#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001206 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1207 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001208#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001209 break;
1210 case 5: /* Bits 40-47 */
1211 break;
1212 case 6: /* Bits 48-55 */
1213 break;
1214 }
1215}
1216
1217
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001218int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1219{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001220 u8 *pos = buf;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001221 u8 len = 4, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001222
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001223 if (len < wpa_s->extended_capa_len)
1224 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001225
1226 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001227 *pos++ = len;
1228 for (i = 0; i < len; i++, pos++) {
1229 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001230
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001231 if (i < wpa_s->extended_capa_len) {
1232 *pos &= ~wpa_s->extended_capa_mask[i];
1233 *pos |= wpa_s->extended_capa[i];
1234 }
1235 }
1236
1237 while (len > 0 && buf[1 + len] == 0) {
1238 len--;
1239 buf[1] = len;
1240 }
1241 if (len == 0)
1242 return 0;
1243
1244 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001245}
1246
1247
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001248static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1249 struct wpa_bss *test_bss)
1250{
1251 struct wpa_bss *bss;
1252
1253 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1254 if (bss == test_bss)
1255 return 1;
1256 }
1257
1258 return 0;
1259}
1260
1261
1262static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1263 struct wpa_ssid *test_ssid)
1264{
1265 struct wpa_ssid *ssid;
1266
1267 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1268 if (ssid == test_ssid)
1269 return 1;
1270 }
1271
1272 return 0;
1273}
1274
1275
1276int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1277 struct wpa_ssid *test_ssid)
1278{
1279 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1280 return 0;
1281
1282 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1283}
1284
1285
1286void wpas_connect_work_free(struct wpa_connect_work *cwork)
1287{
1288 if (cwork == NULL)
1289 return;
1290 os_free(cwork);
1291}
1292
1293
1294void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1295{
1296 struct wpa_connect_work *cwork;
1297 struct wpa_radio_work *work = wpa_s->connect_work;
1298
1299 if (!work)
1300 return;
1301
1302 wpa_s->connect_work = NULL;
1303 cwork = work->ctx;
1304 work->ctx = NULL;
1305 wpas_connect_work_free(cwork);
1306 radio_work_done(work);
1307}
1308
1309
1310static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1311
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312/**
1313 * wpa_supplicant_associate - Request association
1314 * @wpa_s: Pointer to wpa_supplicant data
1315 * @bss: Scan results for the selected BSS, or %NULL if not available
1316 * @ssid: Configuration data for the selected network
1317 *
1318 * This function is used to request %wpa_supplicant to associate with a BSS.
1319 */
1320void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1321 struct wpa_bss *bss, struct wpa_ssid *ssid)
1322{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001323 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001324
1325#ifdef CONFIG_IBSS_RSN
1326 ibss_rsn_deinit(wpa_s->ibss_rsn);
1327 wpa_s->ibss_rsn = NULL;
1328#endif /* CONFIG_IBSS_RSN */
1329
1330 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1331 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1332#ifdef CONFIG_AP
1333 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1334 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1335 "mode");
1336 return;
1337 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001338 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1339 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001340 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1341 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001342 return;
1343 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001344 wpa_s->current_bss = bss;
1345#else /* CONFIG_AP */
1346 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1347 "the build");
1348#endif /* CONFIG_AP */
1349 return;
1350 }
1351
1352#ifdef CONFIG_TDLS
1353 if (bss)
1354 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1355 bss->ie_len);
1356#endif /* CONFIG_TDLS */
1357
1358 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1359 ssid->mode == IEEE80211_MODE_INFRA) {
1360 sme_authenticate(wpa_s, bss, ssid);
1361 return;
1362 }
1363
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001364 if (wpa_s->connect_work) {
1365 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1366 return;
1367 }
1368
1369 cwork = os_zalloc(sizeof(*cwork));
1370 if (cwork == NULL)
1371 return;
1372
1373 cwork->bss = bss;
1374 cwork->ssid = ssid;
1375
1376 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1377 wpas_start_assoc_cb, cwork) < 0) {
1378 os_free(cwork);
1379 }
1380}
1381
1382
1383static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1384{
1385 struct wpa_connect_work *cwork = work->ctx;
1386 struct wpa_bss *bss = cwork->bss;
1387 struct wpa_ssid *ssid = cwork->ssid;
1388 struct wpa_supplicant *wpa_s = work->wpa_s;
1389 u8 wpa_ie[200];
1390 size_t wpa_ie_len;
1391 int use_crypt, ret, i, bssid_changed;
1392 int algs = WPA_AUTH_ALG_OPEN;
1393 unsigned int cipher_pairwise, cipher_group;
1394 struct wpa_driver_associate_params params;
1395 int wep_keys_set = 0;
1396 int assoc_failed = 0;
1397 struct wpa_ssid *old_ssid;
1398#ifdef CONFIG_HT_OVERRIDES
1399 struct ieee80211_ht_capabilities htcaps;
1400 struct ieee80211_ht_capabilities htcaps_mask;
1401#endif /* CONFIG_HT_OVERRIDES */
1402
1403 if (deinit) {
1404 wpas_connect_work_free(cwork);
1405 return;
1406 }
1407
1408 wpa_s->connect_work = work;
1409
1410 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1411 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1412 wpas_connect_work_done(wpa_s);
1413 return;
1414 }
1415
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001416 os_memset(&params, 0, sizeof(params));
1417 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001418 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001419 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001420#ifdef CONFIG_IEEE80211R
1421 const u8 *ie, *md = NULL;
1422#endif /* CONFIG_IEEE80211R */
1423 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1424 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1425 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1426 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1427 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1428 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1429 if (bssid_changed)
1430 wpas_notify_bssid_changed(wpa_s);
1431#ifdef CONFIG_IEEE80211R
1432 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1433 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1434 md = ie + 2;
1435 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1436 if (md) {
1437 /* Prepare for the next transition */
1438 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1439 }
1440#endif /* CONFIG_IEEE80211R */
1441#ifdef CONFIG_WPS
1442 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1443 wpa_s->conf->ap_scan == 2 &&
1444 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1445 /* Use ap_scan==1 style network selection to find the network
1446 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001447 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448 wpa_s->reassociate = 1;
1449 wpa_supplicant_req_scan(wpa_s, 0, 0);
1450 return;
1451#endif /* CONFIG_WPS */
1452 } else {
1453 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1454 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1455 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1456 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001457 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458 wpa_supplicant_cancel_scan(wpa_s);
1459
1460 /* Starting new association, so clear the possibly used WPA IE from the
1461 * previous association. */
1462 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1463
1464#ifdef IEEE8021X_EAPOL
1465 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1466 if (ssid->leap) {
1467 if (ssid->non_leap == 0)
1468 algs = WPA_AUTH_ALG_LEAP;
1469 else
1470 algs |= WPA_AUTH_ALG_LEAP;
1471 }
1472 }
1473#endif /* IEEE8021X_EAPOL */
1474 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1475 if (ssid->auth_alg) {
1476 algs = ssid->auth_alg;
1477 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1478 "0x%x", algs);
1479 }
1480
1481 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1482 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001483 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001484 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001485 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1486 wpa_s->conf->okc :
1487 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488 (ssid->proto & WPA_PROTO_RSN);
1489 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001490 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1492 wpa_ie_len = sizeof(wpa_ie);
1493 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1494 wpa_ie, &wpa_ie_len)) {
1495 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1496 "key management and encryption suites");
1497 return;
1498 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001499 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1500 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1501 /*
1502 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1503 * use non-WPA since the scan results did not indicate that the
1504 * AP is using WPA or WPA2.
1505 */
1506 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1507 wpa_ie_len = 0;
1508 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001509 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510 wpa_ie_len = sizeof(wpa_ie);
1511 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1512 wpa_ie, &wpa_ie_len)) {
1513 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1514 "key management and encryption suites (no "
1515 "scan results)");
1516 return;
1517 }
1518#ifdef CONFIG_WPS
1519 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1520 struct wpabuf *wps_ie;
1521 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1522 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1523 wpa_ie_len = wpabuf_len(wps_ie);
1524 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1525 } else
1526 wpa_ie_len = 0;
1527 wpabuf_free(wps_ie);
1528 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1529 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1530 params.wps = WPS_MODE_PRIVACY;
1531 else
1532 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001533 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534#endif /* CONFIG_WPS */
1535 } else {
1536 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1537 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001538 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001539 }
1540
1541#ifdef CONFIG_P2P
1542 if (wpa_s->global->p2p) {
1543 u8 *pos;
1544 size_t len;
1545 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 pos = wpa_ie + wpa_ie_len;
1547 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001548 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1549 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001550 if (res >= 0)
1551 wpa_ie_len += res;
1552 }
1553
1554 wpa_s->cross_connect_disallowed = 0;
1555 if (bss) {
1556 struct wpabuf *p2p;
1557 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1558 if (p2p) {
1559 wpa_s->cross_connect_disallowed =
1560 p2p_get_cross_connect_disallowed(p2p);
1561 wpabuf_free(p2p);
1562 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1563 "connection",
1564 wpa_s->cross_connect_disallowed ?
1565 "disallows" : "allows");
1566 }
1567 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001568
1569 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001570#endif /* CONFIG_P2P */
1571
Dmitry Shmidt04949592012-07-19 12:16:46 -07001572#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001573 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001574 struct wpabuf *hs20;
1575 hs20 = wpabuf_alloc(20);
1576 if (hs20) {
1577 wpas_hs20_add_indication(hs20);
1578 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1579 wpabuf_len(hs20));
1580 wpa_ie_len += wpabuf_len(hs20);
1581 wpabuf_free(hs20);
1582 }
1583 }
1584#endif /* CONFIG_HS20 */
1585
Dmitry Shmidt56052862013-10-04 10:23:25 -07001586 /*
1587 * Workaround: Add Extended Capabilities element only if the AP
1588 * included this element in Beacon/Probe Response frames. Some older
1589 * APs seem to have interoperability issues if this element is
1590 * included, so while the standard may require us to include the
1591 * element in all cases, it is justifiable to skip it to avoid
1592 * interoperability issues.
1593 */
1594 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1595 u8 ext_capab[10];
1596 int ext_capab_len;
1597 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1598 if (ext_capab_len > 0) {
1599 u8 *pos = wpa_ie;
1600 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1601 pos += 2 + pos[1];
1602 os_memmove(pos + ext_capab_len, pos,
1603 wpa_ie_len - (pos - wpa_ie));
1604 wpa_ie_len += ext_capab_len;
1605 os_memcpy(pos, ext_capab, ext_capab_len);
1606 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001607 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001609 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1610 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001611 cipher_pairwise = wpa_s->pairwise_cipher;
1612 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1614 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1615 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1616 use_crypt = 0;
1617 if (wpa_set_wep_keys(wpa_s, ssid)) {
1618 use_crypt = 1;
1619 wep_keys_set = 1;
1620 }
1621 }
1622 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1623 use_crypt = 0;
1624
1625#ifdef IEEE8021X_EAPOL
1626 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1627 if ((ssid->eapol_flags &
1628 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1629 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1630 !wep_keys_set) {
1631 use_crypt = 0;
1632 } else {
1633 /* Assume that dynamic WEP-104 keys will be used and
1634 * set cipher suites in order for drivers to expect
1635 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001636 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001637 }
1638 }
1639#endif /* IEEE8021X_EAPOL */
1640
1641 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1642 /* Set the key before (and later after) association */
1643 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1644 }
1645
1646 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1647 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001648 params.ssid = bss->ssid;
1649 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001650 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1651 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1652 MACSTR " freq=%u MHz based on scan results "
1653 "(bssid_set=%d)",
1654 MAC2STR(bss->bssid), bss->freq,
1655 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001656 params.bssid = bss->bssid;
1657 params.freq = bss->freq;
1658 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659 } else {
1660 params.ssid = ssid->ssid;
1661 params.ssid_len = ssid->ssid_len;
1662 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001663
1664 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1665 wpa_s->conf->ap_scan == 2) {
1666 params.bssid = ssid->bssid;
1667 params.fixed_bssid = 1;
1668 }
1669
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001670 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1671 params.freq == 0)
1672 params.freq = ssid->frequency; /* Initial channel for IBSS */
1673 params.wpa_ie = wpa_ie;
1674 params.wpa_ie_len = wpa_ie_len;
1675 params.pairwise_suite = cipher_pairwise;
1676 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001677 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001678 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679 params.auth_alg = algs;
1680 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001681 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682 for (i = 0; i < NUM_WEP_KEYS; i++) {
1683 if (ssid->wep_key_len[i])
1684 params.wep_key[i] = ssid->wep_key[i];
1685 params.wep_key_len[i] = ssid->wep_key_len[i];
1686 }
1687 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1688
1689 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001690 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1691 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692 params.passphrase = ssid->passphrase;
1693 if (ssid->psk_set)
1694 params.psk = ssid->psk;
1695 }
1696
1697 params.drop_unencrypted = use_crypt;
1698
1699#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001700 params.mgmt_frame_protection =
1701 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1702 wpa_s->conf->pmf : ssid->ieee80211w;
1703 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1705 struct wpa_ie_data ie;
1706 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1707 ie.capabilities &
1708 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1709 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1710 "MFP: require MFP");
1711 params.mgmt_frame_protection =
1712 MGMT_FRAME_PROTECTION_REQUIRED;
1713 }
1714 }
1715#endif /* CONFIG_IEEE80211W */
1716
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001717 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718
1719 if (wpa_s->parent->set_sta_uapsd)
1720 params.uapsd = wpa_s->parent->sta_uapsd;
1721 else
1722 params.uapsd = -1;
1723
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001724#ifdef CONFIG_HT_OVERRIDES
1725 os_memset(&htcaps, 0, sizeof(htcaps));
1726 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1727 params.htcaps = (u8 *) &htcaps;
1728 params.htcaps_mask = (u8 *) &htcaps_mask;
1729 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1730#endif /* CONFIG_HT_OVERRIDES */
1731
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001732#ifdef CONFIG_P2P
1733 /*
1734 * If multi-channel concurrency is not supported, check for any
1735 * frequency conflict. In case of any frequency conflict, remove the
1736 * least prioritized connection.
1737 */
1738 if (wpa_s->num_multichan_concurrent < 2) {
1739 int freq = wpa_drv_shared_freq(wpa_s);
1740 if (freq > 0 && freq != params.freq) {
1741 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1742 freq, params.freq);
1743 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1744 params.freq,
1745 ssid) < 0)
1746 return;
1747 }
1748 }
1749#endif /* CONFIG_P2P */
1750
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001751 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001752 if (ret < 0) {
1753 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1754 "failed");
1755 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1756 /*
1757 * The driver is known to mean what is saying, so we
1758 * can stop right here; the association will not
1759 * succeed.
1760 */
1761 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001762 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1764 return;
1765 }
1766 /* try to continue anyway; new association will be tried again
1767 * after timeout */
1768 assoc_failed = 1;
1769 }
1770
1771 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1772 /* Set the key after the association just in case association
1773 * cleared the previously configured key. */
1774 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1775 /* No need to timeout authentication since there is no key
1776 * management. */
1777 wpa_supplicant_cancel_auth_timeout(wpa_s);
1778 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1779#ifdef CONFIG_IBSS_RSN
1780 } else if (ssid->mode == WPAS_MODE_IBSS &&
1781 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1782 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1783 /*
1784 * RSN IBSS authentication is per-STA and we can disable the
1785 * per-BSSID authentication.
1786 */
1787 wpa_supplicant_cancel_auth_timeout(wpa_s);
1788#endif /* CONFIG_IBSS_RSN */
1789 } else {
1790 /* Timeout for IEEE 802.11 authentication and association */
1791 int timeout = 60;
1792
1793 if (assoc_failed) {
1794 /* give IBSS a bit more time */
1795 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1796 } else if (wpa_s->conf->ap_scan == 1) {
1797 /* give IBSS a bit more time */
1798 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1799 }
1800 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1801 }
1802
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001803 if (wep_keys_set &&
1804 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805 /* Set static WEP keys again */
1806 wpa_set_wep_keys(wpa_s, ssid);
1807 }
1808
1809 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1810 /*
1811 * Do not allow EAP session resumption between different
1812 * network configurations.
1813 */
1814 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1815 }
1816 old_ssid = wpa_s->current_ssid;
1817 wpa_s->current_ssid = ssid;
1818 wpa_s->current_bss = bss;
1819 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1820 wpa_supplicant_initiate_eapol(wpa_s);
1821 if (old_ssid != wpa_s->current_ssid)
1822 wpas_notify_network_changed(wpa_s);
1823}
1824
1825
1826static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1827 const u8 *addr)
1828{
1829 struct wpa_ssid *old_ssid;
1830
1831 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001833 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 wpa_sm_set_config(wpa_s->wpa, NULL);
1835 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1836 if (old_ssid != wpa_s->current_ssid)
1837 wpas_notify_network_changed(wpa_s);
1838 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1839}
1840
1841
1842/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1844 * @wpa_s: Pointer to wpa_supplicant data
1845 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1846 *
1847 * This function is used to request %wpa_supplicant to deauthenticate from the
1848 * current AP.
1849 */
1850void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1851 int reason_code)
1852{
1853 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001854 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001855 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001857 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1858 " pending_bssid=" MACSTR " reason=%d state=%s",
1859 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1860 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1861
1862 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001864 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1865 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1866 wpa_s->wpa_state == WPA_ASSOCIATING))
1867 addr = wpa_s->pending_bssid;
1868 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1869 /*
1870 * When using driver-based BSS selection, we may not know the
1871 * BSSID with which we are currently trying to associate. We
1872 * need to notify the driver of this disconnection even in such
1873 * a case, so use the all zeros address here.
1874 */
1875 addr = wpa_s->bssid;
1876 zero_addr = 1;
1877 }
1878
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001879#ifdef CONFIG_TDLS
1880 wpa_tdls_teardown_peers(wpa_s->wpa);
1881#endif /* CONFIG_TDLS */
1882
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001883 if (addr) {
1884 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001885 os_memset(&event, 0, sizeof(event));
1886 event.deauth_info.reason_code = (u16) reason_code;
1887 event.deauth_info.locally_generated = 1;
1888 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001889 if (zero_addr)
1890 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 }
1892
1893 wpa_supplicant_clear_connection(wpa_s, addr);
1894}
1895
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001896static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1897 struct wpa_ssid *ssid)
1898{
1899 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1900 return;
1901
1902 ssid->disabled = 0;
1903 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1904 wpas_notify_network_enabled_changed(wpa_s, ssid);
1905
1906 /*
1907 * Try to reassociate since there is no current configuration and a new
1908 * network was made available.
1909 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001910 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001911 wpa_s->reassociate = 1;
1912}
1913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001914
1915/**
1916 * wpa_supplicant_enable_network - Mark a configured network as enabled
1917 * @wpa_s: wpa_supplicant structure for a network interface
1918 * @ssid: wpa_ssid structure for a configured network or %NULL
1919 *
1920 * Enables the specified network or all networks if no network specified.
1921 */
1922void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1923 struct wpa_ssid *ssid)
1924{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001926 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1927 wpa_supplicant_enable_one_network(wpa_s, ssid);
1928 } else
1929 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001931 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001932 if (wpa_s->sched_scanning) {
1933 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1934 "new network to scan filters");
1935 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 }
1937
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001938 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1939 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001940 }
1941}
1942
1943
1944/**
1945 * wpa_supplicant_disable_network - Mark a configured network as disabled
1946 * @wpa_s: wpa_supplicant structure for a network interface
1947 * @ssid: wpa_ssid structure for a configured network or %NULL
1948 *
1949 * Disables the specified network or all networks if no network specified.
1950 */
1951void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1952 struct wpa_ssid *ssid)
1953{
1954 struct wpa_ssid *other_ssid;
1955 int was_disabled;
1956
1957 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001958 if (wpa_s->sched_scanning)
1959 wpa_supplicant_cancel_sched_scan(wpa_s);
1960
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001961 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1962 other_ssid = other_ssid->next) {
1963 was_disabled = other_ssid->disabled;
1964 if (was_disabled == 2)
1965 continue; /* do not change persistent P2P group
1966 * data */
1967
1968 other_ssid->disabled = 1;
1969
1970 if (was_disabled != other_ssid->disabled)
1971 wpas_notify_network_enabled_changed(
1972 wpa_s, other_ssid);
1973 }
1974 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001975 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1977 } else if (ssid->disabled != 2) {
1978 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001979 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1981
1982 was_disabled = ssid->disabled;
1983
1984 ssid->disabled = 1;
1985
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001986 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001987 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001988 if (wpa_s->sched_scanning) {
1989 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1990 "to remove network from filters");
1991 wpa_supplicant_cancel_sched_scan(wpa_s);
1992 wpa_supplicant_req_scan(wpa_s, 0, 0);
1993 }
1994 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001995 }
1996}
1997
1998
1999/**
2000 * wpa_supplicant_select_network - Attempt association with a network
2001 * @wpa_s: wpa_supplicant structure for a network interface
2002 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2003 */
2004void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2005 struct wpa_ssid *ssid)
2006{
2007
2008 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002009 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002011 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002012 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002014 disconnected = 1;
2015 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002017 if (ssid)
2018 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2019
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 /*
2021 * Mark all other networks disabled or mark all networks enabled if no
2022 * network specified.
2023 */
2024 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2025 other_ssid = other_ssid->next) {
2026 int was_disabled = other_ssid->disabled;
2027 if (was_disabled == 2)
2028 continue; /* do not change persistent P2P group data */
2029
2030 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002031 if (was_disabled && !other_ssid->disabled)
2032 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002033
2034 if (was_disabled != other_ssid->disabled)
2035 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2036 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002037
2038 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2039 /* We are already associated with the selected network */
2040 wpa_printf(MSG_DEBUG, "Already associated with the "
2041 "selected network - do nothing");
2042 return;
2043 }
2044
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002045 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002046 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002047 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2048 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002049 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 wpa_s->disconnected = 0;
2051 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002052
2053 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2054 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055
2056 if (ssid)
2057 wpas_notify_network_selected(wpa_s, ssid);
2058}
2059
2060
2061/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002062 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2063 * @wpa_s: wpa_supplicant structure for a network interface
2064 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2065 * @pkcs11_module_path: PKCS #11 module path or NULL
2066 * Returns: 0 on success; -1 on failure
2067 *
2068 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2069 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2070 * module path fails the paths will be reset to the default value (NULL).
2071 */
2072int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2073 const char *pkcs11_engine_path,
2074 const char *pkcs11_module_path)
2075{
2076 char *pkcs11_engine_path_copy = NULL;
2077 char *pkcs11_module_path_copy = NULL;
2078
2079 if (pkcs11_engine_path != NULL) {
2080 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2081 if (pkcs11_engine_path_copy == NULL)
2082 return -1;
2083 }
2084 if (pkcs11_module_path != NULL) {
2085 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
2086 if (pkcs11_engine_path_copy == NULL) {
2087 os_free(pkcs11_engine_path_copy);
2088 return -1;
2089 }
2090 }
2091
2092 os_free(wpa_s->conf->pkcs11_engine_path);
2093 os_free(wpa_s->conf->pkcs11_module_path);
2094 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2095 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2096
2097 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2098 eapol_sm_deinit(wpa_s->eapol);
2099 wpa_s->eapol = NULL;
2100 if (wpa_supplicant_init_eapol(wpa_s)) {
2101 /* Error -> Reset paths to the default value (NULL) once. */
2102 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2103 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2104 NULL);
2105
2106 return -1;
2107 }
2108 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2109
2110 return 0;
2111}
2112
2113
2114/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2116 * @wpa_s: wpa_supplicant structure for a network interface
2117 * @ap_scan: AP scan mode
2118 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2119 *
2120 */
2121int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2122{
2123
2124 int old_ap_scan;
2125
2126 if (ap_scan < 0 || ap_scan > 2)
2127 return -1;
2128
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002129#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002130 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2131 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2132 wpa_s->wpa_state < WPA_COMPLETED) {
2133 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2134 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002135 return 0;
2136 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002137#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139 old_ap_scan = wpa_s->conf->ap_scan;
2140 wpa_s->conf->ap_scan = ap_scan;
2141
2142 if (old_ap_scan != wpa_s->conf->ap_scan)
2143 wpas_notify_ap_scan_changed(wpa_s);
2144
2145 return 0;
2146}
2147
2148
2149/**
2150 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2151 * @wpa_s: wpa_supplicant structure for a network interface
2152 * @expire_age: Expiration age in seconds
2153 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2154 *
2155 */
2156int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2157 unsigned int bss_expire_age)
2158{
2159 if (bss_expire_age < 10) {
2160 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2161 bss_expire_age);
2162 return -1;
2163 }
2164 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2165 bss_expire_age);
2166 wpa_s->conf->bss_expiration_age = bss_expire_age;
2167
2168 return 0;
2169}
2170
2171
2172/**
2173 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2174 * @wpa_s: wpa_supplicant structure for a network interface
2175 * @expire_count: number of scans after which an unseen BSS is reclaimed
2176 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2177 *
2178 */
2179int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2180 unsigned int bss_expire_count)
2181{
2182 if (bss_expire_count < 1) {
2183 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2184 bss_expire_count);
2185 return -1;
2186 }
2187 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2188 bss_expire_count);
2189 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2190
2191 return 0;
2192}
2193
2194
2195/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002196 * wpa_supplicant_set_scan_interval - Set scan interval
2197 * @wpa_s: wpa_supplicant structure for a network interface
2198 * @scan_interval: scan interval in seconds
2199 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2200 *
2201 */
2202int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2203 int scan_interval)
2204{
2205 if (scan_interval < 0) {
2206 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2207 scan_interval);
2208 return -1;
2209 }
2210 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2211 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002212 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002213
2214 return 0;
2215}
2216
2217
2218/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 * wpa_supplicant_set_debug_params - Set global debug params
2220 * @global: wpa_global structure
2221 * @debug_level: debug level
2222 * @debug_timestamp: determines if show timestamp in debug data
2223 * @debug_show_keys: determines if show keys in debug data
2224 * Returns: 0 if succeed or -1 if debug_level has wrong value
2225 */
2226int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2227 int debug_timestamp, int debug_show_keys)
2228{
2229
2230 int old_level, old_timestamp, old_show_keys;
2231
2232 /* check for allowed debuglevels */
2233 if (debug_level != MSG_EXCESSIVE &&
2234 debug_level != MSG_MSGDUMP &&
2235 debug_level != MSG_DEBUG &&
2236 debug_level != MSG_INFO &&
2237 debug_level != MSG_WARNING &&
2238 debug_level != MSG_ERROR)
2239 return -1;
2240
2241 old_level = wpa_debug_level;
2242 old_timestamp = wpa_debug_timestamp;
2243 old_show_keys = wpa_debug_show_keys;
2244
2245 wpa_debug_level = debug_level;
2246 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2247 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2248
2249 if (wpa_debug_level != old_level)
2250 wpas_notify_debug_level_changed(global);
2251 if (wpa_debug_timestamp != old_timestamp)
2252 wpas_notify_debug_timestamp_changed(global);
2253 if (wpa_debug_show_keys != old_show_keys)
2254 wpas_notify_debug_show_keys_changed(global);
2255
2256 return 0;
2257}
2258
2259
2260/**
2261 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2262 * @wpa_s: Pointer to wpa_supplicant data
2263 * Returns: A pointer to the current network structure or %NULL on failure
2264 */
2265struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2266{
2267 struct wpa_ssid *entry;
2268 u8 ssid[MAX_SSID_LEN];
2269 int res;
2270 size_t ssid_len;
2271 u8 bssid[ETH_ALEN];
2272 int wired;
2273
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002274 res = wpa_drv_get_ssid(wpa_s, ssid);
2275 if (res < 0) {
2276 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2277 "driver");
2278 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002280 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002282 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002283 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2284 "driver");
2285 return NULL;
2286 }
2287
2288 wired = wpa_s->conf->ap_scan == 0 &&
2289 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2290
2291 entry = wpa_s->conf->ssid;
2292 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002293 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002294 ((ssid_len == entry->ssid_len &&
2295 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2296 (!entry->bssid_set ||
2297 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2298 return entry;
2299#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002300 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002301 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2302 (entry->ssid == NULL || entry->ssid_len == 0) &&
2303 (!entry->bssid_set ||
2304 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2305 return entry;
2306#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002307
Dmitry Shmidt04949592012-07-19 12:16:46 -07002308 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002309 entry->ssid_len == 0 &&
2310 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2311 return entry;
2312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 entry = entry->next;
2314 }
2315
2316 return NULL;
2317}
2318
2319
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002320static int select_driver(struct wpa_supplicant *wpa_s, int i)
2321{
2322 struct wpa_global *global = wpa_s->global;
2323
2324 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2325 global->drv_priv[i] = wpa_drivers[i]->global_init();
2326 if (global->drv_priv[i] == NULL) {
2327 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2328 "'%s'", wpa_drivers[i]->name);
2329 return -1;
2330 }
2331 }
2332
2333 wpa_s->driver = wpa_drivers[i];
2334 wpa_s->global_drv_priv = global->drv_priv[i];
2335
2336 return 0;
2337}
2338
2339
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2341 const char *name)
2342{
2343 int i;
2344 size_t len;
2345 const char *pos, *driver = name;
2346
2347 if (wpa_s == NULL)
2348 return -1;
2349
2350 if (wpa_drivers[0] == NULL) {
2351 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2352 "wpa_supplicant");
2353 return -1;
2354 }
2355
2356 if (name == NULL) {
2357 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002358 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 }
2360
2361 do {
2362 pos = os_strchr(driver, ',');
2363 if (pos)
2364 len = pos - driver;
2365 else
2366 len = os_strlen(driver);
2367
2368 for (i = 0; wpa_drivers[i]; i++) {
2369 if (os_strlen(wpa_drivers[i]->name) == len &&
2370 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002371 0) {
2372 /* First driver that succeeds wins */
2373 if (select_driver(wpa_s, i) == 0)
2374 return 0;
2375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376 }
2377
2378 driver = pos + 1;
2379 } while (pos);
2380
2381 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2382 return -1;
2383}
2384
2385
2386/**
2387 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2388 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2389 * with struct wpa_driver_ops::init()
2390 * @src_addr: Source address of the EAPOL frame
2391 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2392 * @len: Length of the EAPOL data
2393 *
2394 * This function is called for each received EAPOL frame. Most driver
2395 * interfaces rely on more generic OS mechanism for receiving frames through
2396 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2397 * take care of received EAPOL frames and deliver them to the core supplicant
2398 * code by calling this function.
2399 */
2400void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2401 const u8 *buf, size_t len)
2402{
2403 struct wpa_supplicant *wpa_s = ctx;
2404
2405 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2406 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2407
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002408#ifdef CONFIG_PEERKEY
2409 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2410 wpa_s->current_ssid->peerkey &&
2411 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2412 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2413 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2414 return;
2415 }
2416#endif /* CONFIG_PEERKEY */
2417
Jouni Malinena05074c2012-12-21 21:35:35 +02002418 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2419 (wpa_s->last_eapol_matches_bssid &&
2420#ifdef CONFIG_AP
2421 !wpa_s->ap_iface &&
2422#endif /* CONFIG_AP */
2423 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 /*
2425 * There is possible race condition between receiving the
2426 * association event and the EAPOL frame since they are coming
2427 * through different paths from the driver. In order to avoid
2428 * issues in trying to process the EAPOL frame before receiving
2429 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002430 * the association event is received. This may also be needed in
2431 * driver-based roaming case, so also use src_addr != BSSID as a
2432 * trigger if we have previously confirmed that the
2433 * Authenticator uses BSSID as the src_addr (which is not the
2434 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 */
2436 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002437 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2438 wpa_supplicant_state_txt(wpa_s->wpa_state),
2439 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 wpabuf_free(wpa_s->pending_eapol_rx);
2441 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2442 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002443 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2445 ETH_ALEN);
2446 }
2447 return;
2448 }
2449
Jouni Malinena05074c2012-12-21 21:35:35 +02002450 wpa_s->last_eapol_matches_bssid =
2451 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453#ifdef CONFIG_AP
2454 if (wpa_s->ap_iface) {
2455 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2456 return;
2457 }
2458#endif /* CONFIG_AP */
2459
2460 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2461 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2462 "no key management is configured");
2463 return;
2464 }
2465
2466 if (wpa_s->eapol_received == 0 &&
2467 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2468 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2469 wpa_s->wpa_state != WPA_COMPLETED) &&
2470 (wpa_s->current_ssid == NULL ||
2471 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2472 /* Timeout for completing IEEE 802.1X and WPA authentication */
2473 wpa_supplicant_req_auth_timeout(
2474 wpa_s,
2475 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2476 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2477 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2478 70 : 10, 0);
2479 }
2480 wpa_s->eapol_received++;
2481
2482 if (wpa_s->countermeasures) {
2483 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2484 "EAPOL packet");
2485 return;
2486 }
2487
2488#ifdef CONFIG_IBSS_RSN
2489 if (wpa_s->current_ssid &&
2490 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2491 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2492 return;
2493 }
2494#endif /* CONFIG_IBSS_RSN */
2495
2496 /* Source address of the incoming EAPOL frame could be compared to the
2497 * current BSSID. However, it is possible that a centralized
2498 * Authenticator could be using another MAC address than the BSSID of
2499 * an AP, so just allow any address to be used for now. The replies are
2500 * still sent to the current BSSID (if available), though. */
2501
2502 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2503 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2504 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2505 return;
2506 wpa_drv_poll(wpa_s);
2507 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2508 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2509 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2510 /*
2511 * Set portValid = TRUE here since we are going to skip 4-way
2512 * handshake processing which would normally set portValid. We
2513 * need this to allow the EAPOL state machines to be completed
2514 * without going through EAPOL-Key handshake.
2515 */
2516 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2517 }
2518}
2519
2520
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002521int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 if (wpa_s->driver->send_eapol) {
2524 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2525 if (addr)
2526 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002527 } else if ((!wpa_s->p2p_mgmt ||
2528 !(wpa_s->drv_flags &
2529 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2530 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002532 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2534 wpa_drv_get_mac_addr(wpa_s),
2535 ETH_P_EAPOL,
2536 wpa_supplicant_rx_eapol, wpa_s, 0);
2537 if (wpa_s->l2 == NULL)
2538 return -1;
2539 } else {
2540 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2541 if (addr)
2542 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2543 }
2544
2545 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2546 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2547 return -1;
2548 }
2549
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002550 return 0;
2551}
2552
2553
Dmitry Shmidt04949592012-07-19 12:16:46 -07002554static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2555 const u8 *buf, size_t len)
2556{
2557 struct wpa_supplicant *wpa_s = ctx;
2558 const struct l2_ethhdr *eth;
2559
2560 if (len < sizeof(*eth))
2561 return;
2562 eth = (const struct l2_ethhdr *) buf;
2563
2564 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2565 !(eth->h_dest[0] & 0x01)) {
2566 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2567 " (bridge - not for this interface - ignore)",
2568 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2569 return;
2570 }
2571
2572 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2573 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2574 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2575 len - sizeof(*eth));
2576}
2577
2578
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002579/**
2580 * wpa_supplicant_driver_init - Initialize driver interface parameters
2581 * @wpa_s: Pointer to wpa_supplicant data
2582 * Returns: 0 on success, -1 on failure
2583 *
2584 * This function is called to initialize driver interface parameters.
2585 * wpa_drv_init() must have been called before this function to initialize the
2586 * driver interface.
2587 */
2588int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2589{
2590 static int interface_count = 0;
2591
2592 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2593 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002595 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2596 MAC2STR(wpa_s->own_addr));
2597 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 if (wpa_s->bridge_ifname[0]) {
2600 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2601 "interface '%s'", wpa_s->bridge_ifname);
2602 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2603 wpa_s->own_addr,
2604 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002605 wpa_supplicant_rx_eapol_bridge,
2606 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 if (wpa_s->l2_br == NULL) {
2608 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2609 "connection for the bridge interface '%s'",
2610 wpa_s->bridge_ifname);
2611 return -1;
2612 }
2613 }
2614
2615 wpa_clear_keys(wpa_s, NULL);
2616
2617 /* Make sure that TKIP countermeasures are not left enabled (could
2618 * happen if wpa_supplicant is killed during countermeasures. */
2619 wpa_drv_set_countermeasures(wpa_s, 0);
2620
2621 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2622 wpa_drv_flush_pmkid(wpa_s);
2623
2624 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002625 wpa_s->prev_scan_wildcard = 0;
2626
Dmitry Shmidt04949592012-07-19 12:16:46 -07002627 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002628 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2629 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2630 interface_count = 0;
2631 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002632 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2633 100000))
2634 wpa_supplicant_req_scan(wpa_s, interface_count,
2635 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 interface_count++;
2637 } else
2638 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2639
2640 return 0;
2641}
2642
2643
2644static int wpa_supplicant_daemon(const char *pid_file)
2645{
2646 wpa_printf(MSG_DEBUG, "Daemonize..");
2647 return os_daemonize(pid_file);
2648}
2649
2650
2651static struct wpa_supplicant * wpa_supplicant_alloc(void)
2652{
2653 struct wpa_supplicant *wpa_s;
2654
2655 wpa_s = os_zalloc(sizeof(*wpa_s));
2656 if (wpa_s == NULL)
2657 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002658 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 wpa_s->scan_interval = 5;
2660 wpa_s->new_connection = 1;
2661 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002662 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663
2664 return wpa_s;
2665}
2666
2667
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002668#ifdef CONFIG_HT_OVERRIDES
2669
2670static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2671 struct ieee80211_ht_capabilities *htcaps,
2672 struct ieee80211_ht_capabilities *htcaps_mask,
2673 const char *ht_mcs)
2674{
2675 /* parse ht_mcs into hex array */
2676 int i;
2677 const char *tmp = ht_mcs;
2678 char *end = NULL;
2679
2680 /* If ht_mcs is null, do not set anything */
2681 if (!ht_mcs)
2682 return 0;
2683
2684 /* This is what we are setting in the kernel */
2685 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2686
2687 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2688
2689 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2690 errno = 0;
2691 long v = strtol(tmp, &end, 16);
2692 if (errno == 0) {
2693 wpa_msg(wpa_s, MSG_DEBUG,
2694 "htcap value[%i]: %ld end: %p tmp: %p",
2695 i, v, end, tmp);
2696 if (end == tmp)
2697 break;
2698
2699 htcaps->supported_mcs_set[i] = v;
2700 tmp = end;
2701 } else {
2702 wpa_msg(wpa_s, MSG_ERROR,
2703 "Failed to parse ht-mcs: %s, error: %s\n",
2704 ht_mcs, strerror(errno));
2705 return -1;
2706 }
2707 }
2708
2709 /*
2710 * If we were able to parse any values, then set mask for the MCS set.
2711 */
2712 if (i) {
2713 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2714 IEEE80211_HT_MCS_MASK_LEN - 1);
2715 /* skip the 3 reserved bits */
2716 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2717 0x1f;
2718 }
2719
2720 return 0;
2721}
2722
2723
2724static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2725 struct ieee80211_ht_capabilities *htcaps,
2726 struct ieee80211_ht_capabilities *htcaps_mask,
2727 int disabled)
2728{
2729 u16 msk;
2730
2731 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2732
2733 if (disabled == -1)
2734 return 0;
2735
2736 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2737 htcaps_mask->ht_capabilities_info |= msk;
2738 if (disabled)
2739 htcaps->ht_capabilities_info &= msk;
2740 else
2741 htcaps->ht_capabilities_info |= msk;
2742
2743 return 0;
2744}
2745
2746
2747static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2748 struct ieee80211_ht_capabilities *htcaps,
2749 struct ieee80211_ht_capabilities *htcaps_mask,
2750 int factor)
2751{
2752 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2753
2754 if (factor == -1)
2755 return 0;
2756
2757 if (factor < 0 || factor > 3) {
2758 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2759 "Must be 0-3 or -1", factor);
2760 return -EINVAL;
2761 }
2762
2763 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2764 htcaps->a_mpdu_params &= ~0x3;
2765 htcaps->a_mpdu_params |= factor & 0x3;
2766
2767 return 0;
2768}
2769
2770
2771static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2772 struct ieee80211_ht_capabilities *htcaps,
2773 struct ieee80211_ht_capabilities *htcaps_mask,
2774 int density)
2775{
2776 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2777
2778 if (density == -1)
2779 return 0;
2780
2781 if (density < 0 || density > 7) {
2782 wpa_msg(wpa_s, MSG_ERROR,
2783 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2784 density);
2785 return -EINVAL;
2786 }
2787
2788 htcaps_mask->a_mpdu_params |= 0x1C;
2789 htcaps->a_mpdu_params &= ~(0x1C);
2790 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2791
2792 return 0;
2793}
2794
2795
2796static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2797 struct ieee80211_ht_capabilities *htcaps,
2798 struct ieee80211_ht_capabilities *htcaps_mask,
2799 int disabled)
2800{
2801 /* Masking these out disables HT40 */
2802 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2803 HT_CAP_INFO_SHORT_GI40MHZ);
2804
2805 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2806
2807 if (disabled)
2808 htcaps->ht_capabilities_info &= ~msk;
2809 else
2810 htcaps->ht_capabilities_info |= msk;
2811
2812 htcaps_mask->ht_capabilities_info |= msk;
2813
2814 return 0;
2815}
2816
2817
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002818static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2819 struct ieee80211_ht_capabilities *htcaps,
2820 struct ieee80211_ht_capabilities *htcaps_mask,
2821 int disabled)
2822{
2823 /* Masking these out disables SGI */
2824 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2825 HT_CAP_INFO_SHORT_GI40MHZ);
2826
2827 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2828
2829 if (disabled)
2830 htcaps->ht_capabilities_info &= ~msk;
2831 else
2832 htcaps->ht_capabilities_info |= msk;
2833
2834 htcaps_mask->ht_capabilities_info |= msk;
2835
2836 return 0;
2837}
2838
2839
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002840void wpa_supplicant_apply_ht_overrides(
2841 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2842 struct wpa_driver_associate_params *params)
2843{
2844 struct ieee80211_ht_capabilities *htcaps;
2845 struct ieee80211_ht_capabilities *htcaps_mask;
2846
2847 if (!ssid)
2848 return;
2849
2850 params->disable_ht = ssid->disable_ht;
2851 if (!params->htcaps || !params->htcaps_mask)
2852 return;
2853
2854 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2855 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2856 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2857 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2858 ssid->disable_max_amsdu);
2859 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2860 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2861 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002862 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002863}
2864
2865#endif /* CONFIG_HT_OVERRIDES */
2866
2867
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002868#ifdef CONFIG_VHT_OVERRIDES
2869void wpa_supplicant_apply_vht_overrides(
2870 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2871 struct wpa_driver_associate_params *params)
2872{
2873 struct ieee80211_vht_capabilities *vhtcaps;
2874 struct ieee80211_vht_capabilities *vhtcaps_mask;
2875
2876 if (!ssid)
2877 return;
2878
2879 params->disable_vht = ssid->disable_vht;
2880
2881 vhtcaps = (void *) params->vhtcaps;
2882 vhtcaps_mask = (void *) params->vhtcaps_mask;
2883
2884 if (!vhtcaps || !vhtcaps_mask)
2885 return;
2886
2887 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2888 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2889
2890#define OVERRIDE_MCS(i) \
2891 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2892 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2893 3 << 2 * (i - 1); \
2894 vhtcaps->vht_supported_mcs_set.tx_map |= \
2895 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2896 } \
2897 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2898 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2899 3 << 2 * (i - 1); \
2900 vhtcaps->vht_supported_mcs_set.rx_map |= \
2901 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2902 }
2903
2904 OVERRIDE_MCS(1);
2905 OVERRIDE_MCS(2);
2906 OVERRIDE_MCS(3);
2907 OVERRIDE_MCS(4);
2908 OVERRIDE_MCS(5);
2909 OVERRIDE_MCS(6);
2910 OVERRIDE_MCS(7);
2911 OVERRIDE_MCS(8);
2912}
2913#endif /* CONFIG_VHT_OVERRIDES */
2914
2915
Dmitry Shmidt04949592012-07-19 12:16:46 -07002916static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2917{
2918#ifdef PCSC_FUNCS
2919 size_t len;
2920
2921 if (!wpa_s->conf->pcsc_reader)
2922 return 0;
2923
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002924 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002925 if (!wpa_s->scard)
2926 return 1;
2927
2928 if (wpa_s->conf->pcsc_pin &&
2929 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2930 scard_deinit(wpa_s->scard);
2931 wpa_s->scard = NULL;
2932 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2933 return -1;
2934 }
2935
2936 len = sizeof(wpa_s->imsi) - 1;
2937 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2938 scard_deinit(wpa_s->scard);
2939 wpa_s->scard = NULL;
2940 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2941 return -1;
2942 }
2943 wpa_s->imsi[len] = '\0';
2944
2945 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2946
2947 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2948 wpa_s->imsi, wpa_s->mnc_len);
2949
2950 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2951 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2952#endif /* PCSC_FUNCS */
2953
2954 return 0;
2955}
2956
2957
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002958int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2959{
2960 char *val, *pos;
2961
2962 ext_password_deinit(wpa_s->ext_pw);
2963 wpa_s->ext_pw = NULL;
2964 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2965
2966 if (!wpa_s->conf->ext_password_backend)
2967 return 0;
2968
2969 val = os_strdup(wpa_s->conf->ext_password_backend);
2970 if (val == NULL)
2971 return -1;
2972 pos = os_strchr(val, ':');
2973 if (pos)
2974 *pos++ = '\0';
2975
2976 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2977
2978 wpa_s->ext_pw = ext_password_init(val, pos);
2979 os_free(val);
2980 if (wpa_s->ext_pw == NULL) {
2981 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2982 return -1;
2983 }
2984 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2985
2986 return 0;
2987}
2988
2989
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002990static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2991 const char *rn)
2992{
2993 struct wpa_supplicant *iface = wpa_s->global->ifaces;
2994 struct wpa_radio *radio;
2995
2996 while (rn && iface) {
2997 radio = iface->radio;
2998 if (radio && os_strcmp(rn, radio->name) == 0) {
2999 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3000 wpa_s->ifname, rn);
3001 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3002 return radio;
3003 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003004
3005 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003006 }
3007
3008 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3009 wpa_s->ifname, rn ? rn : "N/A");
3010 radio = os_zalloc(sizeof(*radio));
3011 if (radio == NULL)
3012 return NULL;
3013
3014 if (rn)
3015 os_strlcpy(radio->name, rn, sizeof(radio->name));
3016 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003017 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003018 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3019
3020 return radio;
3021}
3022
3023
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003024static void radio_work_free(struct wpa_radio_work *work)
3025{
3026 if (work->wpa_s->scan_work == work) {
3027 /* This should not really happen. */
3028 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3029 work->type, work, work->started);
3030 work->wpa_s->scan_work = NULL;
3031 }
3032
3033#ifdef CONFIG_P2P
3034 if (work->wpa_s->p2p_scan_work == work) {
3035 /* This should not really happen. */
3036 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3037 work->type, work, work->started);
3038 work->wpa_s->p2p_scan_work = NULL;
3039 }
3040#endif /* CONFIG_P2P */
3041
3042 dl_list_del(&work->list);
3043 os_free(work);
3044}
3045
3046
3047static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3048{
3049 struct wpa_radio *radio = eloop_ctx;
3050 struct wpa_radio_work *work;
3051 struct os_reltime now, diff;
3052 struct wpa_supplicant *wpa_s;
3053
3054 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3055 if (work == NULL)
3056 return;
3057
3058 if (work->started)
3059 return; /* already started and still in progress */
3060
3061 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3062 radio_list);
3063 if (wpa_s && wpa_s->external_scan_running) {
3064 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3065 return;
3066 }
3067
3068 os_get_reltime(&now);
3069 os_reltime_sub(&now, &work->time, &diff);
3070 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3071 work->type, work, diff.sec, diff.usec);
3072 work->started = 1;
3073 work->time = now;
3074 work->cb(work, 0);
3075}
3076
3077
3078void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
3079{
3080 struct wpa_radio_work *work, *tmp;
3081 struct wpa_radio *radio = wpa_s->radio;
3082
3083 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3084 list) {
3085 if (type && (work->started || os_strcmp(type, work->type) != 0))
3086 continue;
3087 if (work->started) {
3088 wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
3089 work->type, work);
3090 continue;
3091 }
3092 wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
3093 work->type, work);
3094 work->cb(work, 1);
3095 radio_work_free(work);
3096 }
3097}
3098
3099
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003100static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3101{
3102 struct wpa_radio *radio = wpa_s->radio;
3103
3104 if (!radio)
3105 return;
3106
3107 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3108 wpa_s->ifname, radio->name);
3109 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003110 if (!dl_list_empty(&radio->ifaces)) {
3111 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003112 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003113 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003114
3115 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003116 radio_remove_unstarted_work(wpa_s, NULL);
3117 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3118 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003119 os_free(radio);
3120}
3121
3122
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003123void radio_work_check_next(struct wpa_supplicant *wpa_s)
3124{
3125 struct wpa_radio *radio = wpa_s->radio;
3126
3127 if (dl_list_empty(&radio->work))
3128 return;
3129 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3130 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3131}
3132
3133
3134/**
3135 * radio_add_work - Add a radio work item
3136 * @wpa_s: Pointer to wpa_supplicant data
3137 * @freq: Frequency of the offchannel operation in MHz or 0
3138 * @type: Unique identifier for each type of work
3139 * @next: Force as the next work to be executed
3140 * @cb: Callback function for indicating when radio is available
3141 * @ctx: Context pointer for the work (work->ctx in cb())
3142 * Returns: 0 on success, -1 on failure
3143 *
3144 * This function is used to request time for an operation that requires
3145 * exclusive radio control. Once the radio is available, the registered callback
3146 * function will be called. radio_work_done() must be called once the exclusive
3147 * radio operation has been completed, so that the radio is freed for other
3148 * operations. The special case of deinit=1 is used to free the context data
3149 * during interface removal. That does not allow the callback function to start
3150 * the radio operation, i.e., it must free any resources allocated for the radio
3151 * work and return.
3152 *
3153 * The @freq parameter can be used to indicate a single channel on which the
3154 * offchannel operation will occur. This may allow multiple radio work
3155 * operations to be performed in parallel if they apply for the same channel.
3156 * Setting this to 0 indicates that the work item may use multiple channels or
3157 * requires exclusive control of the radio.
3158 */
3159int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3160 const char *type, int next,
3161 void (*cb)(struct wpa_radio_work *work, int deinit),
3162 void *ctx)
3163{
3164 struct wpa_radio_work *work;
3165 int was_empty;
3166
3167 work = os_zalloc(sizeof(*work));
3168 if (work == NULL)
3169 return -1;
3170 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3171 os_get_reltime(&work->time);
3172 work->freq = freq;
3173 work->type = type;
3174 work->wpa_s = wpa_s;
3175 work->cb = cb;
3176 work->ctx = ctx;
3177
3178 was_empty = dl_list_empty(&wpa_s->radio->work);
3179 if (next)
3180 dl_list_add(&wpa_s->radio->work, &work->list);
3181 else
3182 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3183 if (was_empty) {
3184 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3185 radio_work_check_next(wpa_s);
3186 }
3187
3188 return 0;
3189}
3190
3191
3192/**
3193 * radio_work_done - Indicate that a radio work item has been completed
3194 * @work: Completed work
3195 *
3196 * This function is called once the callback function registered with
3197 * radio_add_work() has completed its work.
3198 */
3199void radio_work_done(struct wpa_radio_work *work)
3200{
3201 struct wpa_supplicant *wpa_s = work->wpa_s;
3202 struct os_reltime now, diff;
3203 unsigned int started = work->started;
3204
3205 os_get_reltime(&now);
3206 os_reltime_sub(&now, &work->time, &diff);
3207 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3208 work->type, work, started ? "done" : "canceled",
3209 diff.sec, diff.usec);
3210 radio_work_free(work);
3211 if (started)
3212 radio_work_check_next(wpa_s);
3213}
3214
3215
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003216static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3217 struct wpa_interface *iface)
3218{
3219 const char *ifname, *driver, *rn;
3220
3221 driver = iface->driver;
3222next_driver:
3223 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3224 return -1;
3225
3226 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3227 if (wpa_s->drv_priv == NULL) {
3228 const char *pos;
3229 pos = driver ? os_strchr(driver, ',') : NULL;
3230 if (pos) {
3231 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3232 "driver interface - try next driver wrapper");
3233 driver = pos + 1;
3234 goto next_driver;
3235 }
3236 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3237 "interface");
3238 return -1;
3239 }
3240 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3241 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3242 "driver_param '%s'", wpa_s->conf->driver_param);
3243 return -1;
3244 }
3245
3246 ifname = wpa_drv_get_ifname(wpa_s);
3247 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3248 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3249 "interface name with '%s'", ifname);
3250 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3251 }
3252
3253 if (wpa_s->driver->get_radio_name)
3254 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3255 else
3256 rn = NULL;
3257 if (rn && rn[0] == '\0')
3258 rn = NULL;
3259
3260 wpa_s->radio = radio_add_interface(wpa_s, rn);
3261 if (wpa_s->radio == NULL)
3262 return -1;
3263
3264 return 0;
3265}
3266
3267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3269 struct wpa_interface *iface)
3270{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 struct wpa_driver_capa capa;
3272
3273 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3274 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3275 iface->confname ? iface->confname : "N/A",
3276 iface->driver ? iface->driver : "default",
3277 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3278 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3279
3280 if (iface->confname) {
3281#ifdef CONFIG_BACKEND_FILE
3282 wpa_s->confname = os_rel2abs_path(iface->confname);
3283 if (wpa_s->confname == NULL) {
3284 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3285 "for configuration file '%s'.",
3286 iface->confname);
3287 return -1;
3288 }
3289 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3290 iface->confname, wpa_s->confname);
3291#else /* CONFIG_BACKEND_FILE */
3292 wpa_s->confname = os_strdup(iface->confname);
3293#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003294 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003295 if (wpa_s->conf == NULL) {
3296 wpa_printf(MSG_ERROR, "Failed to read or parse "
3297 "configuration '%s'.", wpa_s->confname);
3298 return -1;
3299 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003300 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3301 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003302
3303 /*
3304 * Override ctrl_interface and driver_param if set on command
3305 * line.
3306 */
3307 if (iface->ctrl_interface) {
3308 os_free(wpa_s->conf->ctrl_interface);
3309 wpa_s->conf->ctrl_interface =
3310 os_strdup(iface->ctrl_interface);
3311 }
3312
3313 if (iface->driver_param) {
3314 os_free(wpa_s->conf->driver_param);
3315 wpa_s->conf->driver_param =
3316 os_strdup(iface->driver_param);
3317 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003318
3319 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3320 os_free(wpa_s->conf->ctrl_interface);
3321 wpa_s->conf->ctrl_interface = NULL;
3322 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323 } else
3324 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3325 iface->driver_param);
3326
3327 if (wpa_s->conf == NULL) {
3328 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3329 return -1;
3330 }
3331
3332 if (iface->ifname == NULL) {
3333 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3334 return -1;
3335 }
3336 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3337 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3338 iface->ifname);
3339 return -1;
3340 }
3341 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3342
3343 if (iface->bridge_ifname) {
3344 if (os_strlen(iface->bridge_ifname) >=
3345 sizeof(wpa_s->bridge_ifname)) {
3346 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3347 "name '%s'.", iface->bridge_ifname);
3348 return -1;
3349 }
3350 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3351 sizeof(wpa_s->bridge_ifname));
3352 }
3353
3354 /* RSNA Supplicant Key Management - INITIALIZE */
3355 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3356 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3357
3358 /* Initialize driver interface and register driver event handler before
3359 * L2 receive handler so that association events are processed before
3360 * EAPOL-Key packets if both become available for the same select()
3361 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003362 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003363 return -1;
3364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003365 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3366 return -1;
3367
3368 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3369 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3370 NULL);
3371 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3372
3373 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3374 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3375 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3376 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3377 "dot11RSNAConfigPMKLifetime");
3378 return -1;
3379 }
3380
3381 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3382 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3383 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3384 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3385 "dot11RSNAConfigPMKReauthThreshold");
3386 return -1;
3387 }
3388
3389 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3390 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3391 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3392 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3393 "dot11RSNAConfigSATimeout");
3394 return -1;
3395 }
3396
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003397 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3398 &wpa_s->hw.num_modes,
3399 &wpa_s->hw.flags);
3400
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003402 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003403 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003404 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003405 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003406 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003407 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3408 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3409 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3411 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003412 wpa_s->extended_capa = capa.extended_capa;
3413 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3414 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003415 wpa_s->num_multichan_concurrent =
3416 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417 }
3418 if (wpa_s->max_remain_on_chan == 0)
3419 wpa_s->max_remain_on_chan = 1000;
3420
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003421 /*
3422 * Only take p2p_mgmt parameters when P2P Device is supported.
3423 * Doing it here as it determines whether l2_packet_init() will be done
3424 * during wpa_supplicant_driver_init().
3425 */
3426 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3427 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3428 else
3429 iface->p2p_mgmt = 1;
3430
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003431 if (wpa_s->num_multichan_concurrent == 0)
3432 wpa_s->num_multichan_concurrent = 1;
3433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003434 if (wpa_supplicant_driver_init(wpa_s) < 0)
3435 return -1;
3436
3437#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003438 if ((!iface->p2p_mgmt ||
3439 !(wpa_s->drv_flags &
3440 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3441 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442 return -1;
3443#endif /* CONFIG_TDLS */
3444
3445 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3446 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3447 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3448 return -1;
3449 }
3450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003451 if (wpas_wps_init(wpa_s))
3452 return -1;
3453
3454 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3455 return -1;
3456 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3457
3458 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3459 if (wpa_s->ctrl_iface == NULL) {
3460 wpa_printf(MSG_ERROR,
3461 "Failed to initialize control interface '%s'.\n"
3462 "You may have another wpa_supplicant process "
3463 "already running or the file was\n"
3464 "left by an unclean termination of wpa_supplicant "
3465 "in which case you will need\n"
3466 "to manually remove this file before starting "
3467 "wpa_supplicant again.\n",
3468 wpa_s->conf->ctrl_interface);
3469 return -1;
3470 }
3471
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003472 wpa_s->gas = gas_query_init(wpa_s);
3473 if (wpa_s->gas == NULL) {
3474 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3475 return -1;
3476 }
3477
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003478#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003479 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3481 return -1;
3482 }
3483#endif /* CONFIG_P2P */
3484
3485 if (wpa_bss_init(wpa_s) < 0)
3486 return -1;
3487
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003488#ifdef CONFIG_EAP_PROXY
3489{
3490 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003491 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3492 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003493 if (wpa_s->mnc_len > 0) {
3494 wpa_s->imsi[len] = '\0';
3495 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3496 wpa_s->imsi, wpa_s->mnc_len);
3497 } else {
3498 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3499 }
3500}
3501#endif /* CONFIG_EAP_PROXY */
3502
Dmitry Shmidt04949592012-07-19 12:16:46 -07003503 if (pcsc_reader_init(wpa_s) < 0)
3504 return -1;
3505
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003506 if (wpas_init_ext_pw(wpa_s) < 0)
3507 return -1;
3508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003509 return 0;
3510}
3511
3512
3513static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003514 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003516 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517 if (wpa_s->drv_priv) {
3518 wpa_supplicant_deauthenticate(wpa_s,
3519 WLAN_REASON_DEAUTH_LEAVING);
3520
3521 wpa_drv_set_countermeasures(wpa_s, 0);
3522 wpa_clear_keys(wpa_s, NULL);
3523 }
3524
3525 wpa_supplicant_cleanup(wpa_s);
3526
Dmitry Shmidt04949592012-07-19 12:16:46 -07003527#ifdef CONFIG_P2P
3528 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3529 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3530 "the management interface is being removed");
3531 wpas_p2p_deinit_global(wpa_s->global);
3532 }
3533#endif /* CONFIG_P2P */
3534
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003535 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003536 radio_remove_interface(wpa_s);
3537
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003538 if (wpa_s->drv_priv)
3539 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003540
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003541 if (notify)
3542 wpas_notify_iface_removed(wpa_s);
3543
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003544 if (terminate)
3545 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003546
3547 if (wpa_s->ctrl_iface) {
3548 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3549 wpa_s->ctrl_iface = NULL;
3550 }
3551
3552 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003553 wpa_config_free(wpa_s->conf);
3554 wpa_s->conf = NULL;
3555 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003556
3557 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003558}
3559
3560
3561/**
3562 * wpa_supplicant_add_iface - Add a new network interface
3563 * @global: Pointer to global data from wpa_supplicant_init()
3564 * @iface: Interface configuration options
3565 * Returns: Pointer to the created interface or %NULL on failure
3566 *
3567 * This function is used to add new network interfaces for %wpa_supplicant.
3568 * This can be called before wpa_supplicant_run() to add interfaces before the
3569 * main event loop has been started. In addition, new interfaces can be added
3570 * dynamically while %wpa_supplicant is already running. This could happen,
3571 * e.g., when a hotplug network adapter is inserted.
3572 */
3573struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3574 struct wpa_interface *iface)
3575{
3576 struct wpa_supplicant *wpa_s;
3577 struct wpa_interface t_iface;
3578 struct wpa_ssid *ssid;
3579
3580 if (global == NULL || iface == NULL)
3581 return NULL;
3582
3583 wpa_s = wpa_supplicant_alloc();
3584 if (wpa_s == NULL)
3585 return NULL;
3586
3587 wpa_s->global = global;
3588
3589 t_iface = *iface;
3590 if (global->params.override_driver) {
3591 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3592 "('%s' -> '%s')",
3593 iface->driver, global->params.override_driver);
3594 t_iface.driver = global->params.override_driver;
3595 }
3596 if (global->params.override_ctrl_interface) {
3597 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3598 "ctrl_interface ('%s' -> '%s')",
3599 iface->ctrl_interface,
3600 global->params.override_ctrl_interface);
3601 t_iface.ctrl_interface =
3602 global->params.override_ctrl_interface;
3603 }
3604 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3605 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3606 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003607 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003608 return NULL;
3609 }
3610
3611 /* Notify the control interfaces about new iface */
3612 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003613 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 return NULL;
3615 }
3616
3617 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3618 wpas_notify_network_added(wpa_s, ssid);
3619
3620 wpa_s->next = global->ifaces;
3621 global->ifaces = wpa_s;
3622
3623 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003624 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003625
3626 return wpa_s;
3627}
3628
3629
3630/**
3631 * wpa_supplicant_remove_iface - Remove a network interface
3632 * @global: Pointer to global data from wpa_supplicant_init()
3633 * @wpa_s: Pointer to the network interface to be removed
3634 * Returns: 0 if interface was removed, -1 if interface was not found
3635 *
3636 * This function can be used to dynamically remove network interfaces from
3637 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3638 * addition, this function is used to remove all remaining interfaces when
3639 * %wpa_supplicant is terminated.
3640 */
3641int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003642 struct wpa_supplicant *wpa_s,
3643 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003644{
3645 struct wpa_supplicant *prev;
3646
3647 /* Remove interface from the global list of interfaces */
3648 prev = global->ifaces;
3649 if (prev == wpa_s) {
3650 global->ifaces = wpa_s->next;
3651 } else {
3652 while (prev && prev->next != wpa_s)
3653 prev = prev->next;
3654 if (prev == NULL)
3655 return -1;
3656 prev->next = wpa_s->next;
3657 }
3658
3659 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3660
3661 if (global->p2p_group_formation == wpa_s)
3662 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003663 if (global->p2p_invite_group == wpa_s)
3664 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003665 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666
3667 return 0;
3668}
3669
3670
3671/**
3672 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3673 * @wpa_s: Pointer to the network interface
3674 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3675 */
3676const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3677{
3678 const char *eapol_method;
3679
3680 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3681 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3682 return "NO-EAP";
3683 }
3684
3685 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3686 if (eapol_method == NULL)
3687 return "UNKNOWN-EAP";
3688
3689 return eapol_method;
3690}
3691
3692
3693/**
3694 * wpa_supplicant_get_iface - Get a new network interface
3695 * @global: Pointer to global data from wpa_supplicant_init()
3696 * @ifname: Interface name
3697 * Returns: Pointer to the interface or %NULL if not found
3698 */
3699struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3700 const char *ifname)
3701{
3702 struct wpa_supplicant *wpa_s;
3703
3704 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3705 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3706 return wpa_s;
3707 }
3708 return NULL;
3709}
3710
3711
3712#ifndef CONFIG_NO_WPA_MSG
3713static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3714{
3715 struct wpa_supplicant *wpa_s = ctx;
3716 if (wpa_s == NULL)
3717 return NULL;
3718 return wpa_s->ifname;
3719}
3720#endif /* CONFIG_NO_WPA_MSG */
3721
3722
3723/**
3724 * wpa_supplicant_init - Initialize %wpa_supplicant
3725 * @params: Parameters for %wpa_supplicant
3726 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3727 *
3728 * This function is used to initialize %wpa_supplicant. After successful
3729 * initialization, the returned data pointer can be used to add and remove
3730 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3731 */
3732struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3733{
3734 struct wpa_global *global;
3735 int ret, i;
3736
3737 if (params == NULL)
3738 return NULL;
3739
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003740#ifdef CONFIG_DRIVER_NDIS
3741 {
3742 void driver_ndis_init_ops(void);
3743 driver_ndis_init_ops();
3744 }
3745#endif /* CONFIG_DRIVER_NDIS */
3746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747#ifndef CONFIG_NO_WPA_MSG
3748 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3749#endif /* CONFIG_NO_WPA_MSG */
3750
3751 wpa_debug_open_file(params->wpa_debug_file_path);
3752 if (params->wpa_debug_syslog)
3753 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003754 if (params->wpa_debug_tracing) {
3755 ret = wpa_debug_open_linux_tracing();
3756 if (ret) {
3757 wpa_printf(MSG_ERROR,
3758 "Failed to enable trace logging");
3759 return NULL;
3760 }
3761 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003762
3763 ret = eap_register_methods();
3764 if (ret) {
3765 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3766 if (ret == -2)
3767 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3768 "the same EAP type.");
3769 return NULL;
3770 }
3771
3772 global = os_zalloc(sizeof(*global));
3773 if (global == NULL)
3774 return NULL;
3775 dl_list_init(&global->p2p_srv_bonjour);
3776 dl_list_init(&global->p2p_srv_upnp);
3777 global->params.daemonize = params->daemonize;
3778 global->params.wait_for_monitor = params->wait_for_monitor;
3779 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3780 if (params->pid_file)
3781 global->params.pid_file = os_strdup(params->pid_file);
3782 if (params->ctrl_interface)
3783 global->params.ctrl_interface =
3784 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003785 if (params->ctrl_interface_group)
3786 global->params.ctrl_interface_group =
3787 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003788 if (params->override_driver)
3789 global->params.override_driver =
3790 os_strdup(params->override_driver);
3791 if (params->override_ctrl_interface)
3792 global->params.override_ctrl_interface =
3793 os_strdup(params->override_ctrl_interface);
3794 wpa_debug_level = global->params.wpa_debug_level =
3795 params->wpa_debug_level;
3796 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3797 params->wpa_debug_show_keys;
3798 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3799 params->wpa_debug_timestamp;
3800
3801 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3802
3803 if (eloop_init()) {
3804 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3805 wpa_supplicant_deinit(global);
3806 return NULL;
3807 }
3808
Jouni Malinen75ecf522011-06-27 15:19:46 -07003809 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810
3811 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3812 if (global->ctrl_iface == NULL) {
3813 wpa_supplicant_deinit(global);
3814 return NULL;
3815 }
3816
3817 if (wpas_notify_supplicant_initialized(global)) {
3818 wpa_supplicant_deinit(global);
3819 return NULL;
3820 }
3821
3822 for (i = 0; wpa_drivers[i]; i++)
3823 global->drv_count++;
3824 if (global->drv_count == 0) {
3825 wpa_printf(MSG_ERROR, "No drivers enabled");
3826 wpa_supplicant_deinit(global);
3827 return NULL;
3828 }
3829 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3830 if (global->drv_priv == NULL) {
3831 wpa_supplicant_deinit(global);
3832 return NULL;
3833 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003834
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003835#ifdef CONFIG_WIFI_DISPLAY
3836 if (wifi_display_init(global) < 0) {
3837 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3838 wpa_supplicant_deinit(global);
3839 return NULL;
3840 }
3841#endif /* CONFIG_WIFI_DISPLAY */
3842
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003843 return global;
3844}
3845
3846
3847/**
3848 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3849 * @global: Pointer to global data from wpa_supplicant_init()
3850 * Returns: 0 after successful event loop run, -1 on failure
3851 *
3852 * This function starts the main event loop and continues running as long as
3853 * there are any remaining events. In most cases, this function is running as
3854 * long as the %wpa_supplicant process in still in use.
3855 */
3856int wpa_supplicant_run(struct wpa_global *global)
3857{
3858 struct wpa_supplicant *wpa_s;
3859
3860 if (global->params.daemonize &&
3861 wpa_supplicant_daemon(global->params.pid_file))
3862 return -1;
3863
3864 if (global->params.wait_for_monitor) {
3865 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3866 if (wpa_s->ctrl_iface)
3867 wpa_supplicant_ctrl_iface_wait(
3868 wpa_s->ctrl_iface);
3869 }
3870
3871 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3872 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3873
3874 eloop_run();
3875
3876 return 0;
3877}
3878
3879
3880/**
3881 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3882 * @global: Pointer to global data from wpa_supplicant_init()
3883 *
3884 * This function is called to deinitialize %wpa_supplicant and to free all
3885 * allocated resources. Remaining network interfaces will also be removed.
3886 */
3887void wpa_supplicant_deinit(struct wpa_global *global)
3888{
3889 int i;
3890
3891 if (global == NULL)
3892 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003893
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003894#ifdef CONFIG_WIFI_DISPLAY
3895 wifi_display_deinit(global);
3896#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003897
3898 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003899 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003900
3901 if (global->ctrl_iface)
3902 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3903
3904 wpas_notify_supplicant_deinitialized(global);
3905
3906 eap_peer_unregister_methods();
3907#ifdef CONFIG_AP
3908 eap_server_unregister_methods();
3909#endif /* CONFIG_AP */
3910
3911 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3912 if (!global->drv_priv[i])
3913 continue;
3914 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3915 }
3916 os_free(global->drv_priv);
3917
3918 random_deinit();
3919
3920 eloop_destroy();
3921
3922 if (global->params.pid_file) {
3923 os_daemonize_terminate(global->params.pid_file);
3924 os_free(global->params.pid_file);
3925 }
3926 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003927 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003928 os_free(global->params.override_driver);
3929 os_free(global->params.override_ctrl_interface);
3930
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003931 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003932 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003933 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003934
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 os_free(global);
3936 wpa_debug_close_syslog();
3937 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003938 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003939}
3940
3941
3942void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3943{
3944 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3945 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3946 char country[3];
3947 country[0] = wpa_s->conf->country[0];
3948 country[1] = wpa_s->conf->country[1];
3949 country[2] = '\0';
3950 if (wpa_drv_set_country(wpa_s, country) < 0) {
3951 wpa_printf(MSG_ERROR, "Failed to set country code "
3952 "'%s'", country);
3953 }
3954 }
3955
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003956 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3957 wpas_init_ext_pw(wpa_s);
3958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003959#ifdef CONFIG_WPS
3960 wpas_wps_update_config(wpa_s);
3961#endif /* CONFIG_WPS */
3962
3963#ifdef CONFIG_P2P
3964 wpas_p2p_update_config(wpa_s);
3965#endif /* CONFIG_P2P */
3966
3967 wpa_s->conf->changed_parameters = 0;
3968}
3969
3970
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003971static void add_freq(int *freqs, int *num_freqs, int freq)
3972{
3973 int i;
3974
3975 for (i = 0; i < *num_freqs; i++) {
3976 if (freqs[i] == freq)
3977 return;
3978 }
3979
3980 freqs[*num_freqs] = freq;
3981 (*num_freqs)++;
3982}
3983
3984
3985static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3986{
3987 struct wpa_bss *bss, *cbss;
3988 const int max_freqs = 10;
3989 int *freqs;
3990 int num_freqs = 0;
3991
3992 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3993 if (freqs == NULL)
3994 return NULL;
3995
3996 cbss = wpa_s->current_bss;
3997
3998 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3999 if (bss == cbss)
4000 continue;
4001 if (bss->ssid_len == cbss->ssid_len &&
4002 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4003 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4004 add_freq(freqs, &num_freqs, bss->freq);
4005 if (num_freqs == max_freqs)
4006 break;
4007 }
4008 }
4009
4010 if (num_freqs == 0) {
4011 os_free(freqs);
4012 freqs = NULL;
4013 }
4014
4015 return freqs;
4016}
4017
4018
4019void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4020{
4021 int timeout;
4022 int count;
4023 int *freqs = NULL;
4024
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004025 wpas_connect_work_done(wpa_s);
4026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004027 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004028 * Remove possible authentication timeout since the connection failed.
4029 */
4030 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4031
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004032 if (wpa_s->disconnected) {
4033 /*
4034 * There is no point in blacklisting the AP if this event is
4035 * generated based on local request to disconnect.
4036 */
4037 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4038 "indication since interface has been put into "
4039 "disconnected state");
4040 return;
4041 }
4042
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004043 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 * Add the failed BSSID into the blacklist and speed up next scan
4045 * attempt if there could be other APs that could accept association.
4046 * The current blacklist count indicates how many times we have tried
4047 * connecting to this AP and multiple attempts mean that other APs are
4048 * either not available or has already been tried, so that we can start
4049 * increasing the delay here to avoid constant scanning.
4050 */
4051 count = wpa_blacklist_add(wpa_s, bssid);
4052 if (count == 1 && wpa_s->current_bss) {
4053 /*
4054 * This BSS was not in the blacklist before. If there is
4055 * another BSS available for the same ESS, we should try that
4056 * next. Otherwise, we may as well try this one once more
4057 * before allowing other, likely worse, ESSes to be considered.
4058 */
4059 freqs = get_bss_freqs_in_ess(wpa_s);
4060 if (freqs) {
4061 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4062 "has been seen; try it next");
4063 wpa_blacklist_add(wpa_s, bssid);
4064 /*
4065 * On the next scan, go through only the known channels
4066 * used in this ESS based on previous scans to speed up
4067 * common load balancing use case.
4068 */
4069 os_free(wpa_s->next_scan_freqs);
4070 wpa_s->next_scan_freqs = freqs;
4071 }
4072 }
4073
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004074 /*
4075 * Add previous failure count in case the temporary blacklist was
4076 * cleared due to no other BSSes being available.
4077 */
4078 count += wpa_s->extra_blacklist_count;
4079
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004080 if (count > 3 && wpa_s->current_ssid) {
4081 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4082 "consider temporary network disabling");
4083 wpas_auth_failed(wpa_s);
4084 }
4085
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004086 switch (count) {
4087 case 1:
4088 timeout = 100;
4089 break;
4090 case 2:
4091 timeout = 500;
4092 break;
4093 case 3:
4094 timeout = 1000;
4095 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004096 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004097 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004098 break;
4099 default:
4100 timeout = 10000;
4101 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004102 }
4103
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004104 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4105 "ms", count, timeout);
4106
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 /*
4108 * TODO: if more than one possible AP is available in scan results,
4109 * could try the other ones before requesting a new scan.
4110 */
4111 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4112 1000 * (timeout % 1000));
4113}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004114
4115
4116int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4117{
4118 return wpa_s->conf->ap_scan == 2 ||
4119 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4120}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004121
Dmitry Shmidt04949592012-07-19 12:16:46 -07004122
4123#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4124int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4125 struct wpa_ssid *ssid,
4126 const char *field,
4127 const char *value)
4128{
4129#ifdef IEEE8021X_EAPOL
4130 struct eap_peer_config *eap = &ssid->eap;
4131
4132 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4133 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4134 (const u8 *) value, os_strlen(value));
4135
4136 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4137 case WPA_CTRL_REQ_EAP_IDENTITY:
4138 os_free(eap->identity);
4139 eap->identity = (u8 *) os_strdup(value);
4140 eap->identity_len = os_strlen(value);
4141 eap->pending_req_identity = 0;
4142 if (ssid == wpa_s->current_ssid)
4143 wpa_s->reassociate = 1;
4144 break;
4145 case WPA_CTRL_REQ_EAP_PASSWORD:
4146 os_free(eap->password);
4147 eap->password = (u8 *) os_strdup(value);
4148 eap->password_len = os_strlen(value);
4149 eap->pending_req_password = 0;
4150 if (ssid == wpa_s->current_ssid)
4151 wpa_s->reassociate = 1;
4152 break;
4153 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4154 os_free(eap->new_password);
4155 eap->new_password = (u8 *) os_strdup(value);
4156 eap->new_password_len = os_strlen(value);
4157 eap->pending_req_new_password = 0;
4158 if (ssid == wpa_s->current_ssid)
4159 wpa_s->reassociate = 1;
4160 break;
4161 case WPA_CTRL_REQ_EAP_PIN:
4162 os_free(eap->pin);
4163 eap->pin = os_strdup(value);
4164 eap->pending_req_pin = 0;
4165 if (ssid == wpa_s->current_ssid)
4166 wpa_s->reassociate = 1;
4167 break;
4168 case WPA_CTRL_REQ_EAP_OTP:
4169 os_free(eap->otp);
4170 eap->otp = (u8 *) os_strdup(value);
4171 eap->otp_len = os_strlen(value);
4172 os_free(eap->pending_req_otp);
4173 eap->pending_req_otp = NULL;
4174 eap->pending_req_otp_len = 0;
4175 break;
4176 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4177 os_free(eap->private_key_passwd);
4178 eap->private_key_passwd = (u8 *) os_strdup(value);
4179 eap->pending_req_passphrase = 0;
4180 if (ssid == wpa_s->current_ssid)
4181 wpa_s->reassociate = 1;
4182 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004183 case WPA_CTRL_REQ_SIM:
4184 os_free(eap->external_sim_resp);
4185 eap->external_sim_resp = os_strdup(value);
4186 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004187 default:
4188 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4189 return -1;
4190 }
4191
4192 return 0;
4193#else /* IEEE8021X_EAPOL */
4194 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4195 return -1;
4196#endif /* IEEE8021X_EAPOL */
4197}
4198#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4199
4200
4201int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4202{
4203 int i;
4204 unsigned int drv_enc;
4205
4206 if (ssid == NULL)
4207 return 1;
4208
4209 if (ssid->disabled)
4210 return 1;
4211
4212 if (wpa_s && wpa_s->drv_capa_known)
4213 drv_enc = wpa_s->drv_enc;
4214 else
4215 drv_enc = (unsigned int) -1;
4216
4217 for (i = 0; i < NUM_WEP_KEYS; i++) {
4218 size_t len = ssid->wep_key_len[i];
4219 if (len == 0)
4220 continue;
4221 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4222 continue;
4223 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4224 continue;
4225 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4226 continue;
4227 return 1; /* invalid WEP key */
4228 }
4229
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004230 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4231 !ssid->ext_psk)
4232 return 1;
4233
Dmitry Shmidt04949592012-07-19 12:16:46 -07004234 return 0;
4235}
4236
4237
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004238int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004239{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004240 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004241 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004242 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004243 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004244 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004245}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004246
4247
4248void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4249{
4250 struct wpa_ssid *ssid = wpa_s->current_ssid;
4251 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004252 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004253
4254 if (ssid == NULL) {
4255 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4256 "SSID block");
4257 return;
4258 }
4259
4260 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4261 return;
4262
4263 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004264
4265#ifdef CONFIG_P2P
4266 if (ssid->p2p_group &&
4267 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4268 /*
4269 * Skip the wait time since there is a short timeout on the
4270 * connection to a P2P group.
4271 */
4272 return;
4273 }
4274#endif /* CONFIG_P2P */
4275
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004276 if (ssid->auth_failures > 50)
4277 dur = 300;
4278 else if (ssid->auth_failures > 20)
4279 dur = 120;
4280 else if (ssid->auth_failures > 10)
4281 dur = 60;
4282 else if (ssid->auth_failures > 5)
4283 dur = 30;
4284 else if (ssid->auth_failures > 1)
4285 dur = 20;
4286 else
4287 dur = 10;
4288
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004289 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004290 if (now.sec + dur <= ssid->disabled_until.sec)
4291 return;
4292
4293 ssid->disabled_until.sec = now.sec + dur;
4294
4295 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4296 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4297 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4298 ssid->auth_failures, dur);
4299}
4300
4301
4302void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4303 struct wpa_ssid *ssid, int clear_failures)
4304{
4305 if (ssid == NULL)
4306 return;
4307
4308 if (ssid->disabled_until.sec) {
4309 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4310 "id=%d ssid=\"%s\"",
4311 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4312 }
4313 ssid->disabled_until.sec = 0;
4314 ssid->disabled_until.usec = 0;
4315 if (clear_failures)
4316 ssid->auth_failures = 0;
4317}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004318
4319
4320int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4321{
4322 size_t i;
4323
4324 if (wpa_s->disallow_aps_bssid == NULL)
4325 return 0;
4326
4327 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4328 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4329 bssid, ETH_ALEN) == 0)
4330 return 1;
4331 }
4332
4333 return 0;
4334}
4335
4336
4337int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4338 size_t ssid_len)
4339{
4340 size_t i;
4341
4342 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4343 return 0;
4344
4345 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4346 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4347 if (ssid_len == s->ssid_len &&
4348 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4349 return 1;
4350 }
4351
4352 return 0;
4353}
4354
4355
4356/**
4357 * wpas_request_connection - Request a new connection
4358 * @wpa_s: Pointer to the network interface
4359 *
4360 * This function is used to request a new connection to be found. It will mark
4361 * the interface to allow reassociation and request a new scan to find a
4362 * suitable network to connect to.
4363 */
4364void wpas_request_connection(struct wpa_supplicant *wpa_s)
4365{
4366 wpa_s->normal_scans = 0;
4367 wpa_supplicant_reinit_autoscan(wpa_s);
4368 wpa_s->extra_blacklist_count = 0;
4369 wpa_s->disconnected = 0;
4370 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004371
4372 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4373 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004374}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004375
4376
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004377void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4378 int *freq_array, unsigned int len)
4379{
4380 unsigned int i;
4381
4382 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4383 len, title);
4384 for (i = 0; i < len; i++)
4385 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4386}
4387
4388
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004389/*
4390 * Find the operating frequencies of any of the virtual interfaces that
4391 * are using the same radio as the current interface.
4392 */
4393int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4394 int *freq_array, unsigned int len)
4395{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004396 struct wpa_supplicant *ifs;
4397 u8 bssid[ETH_ALEN];
4398 int freq;
4399 unsigned int idx = 0, i;
4400
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004401 wpa_dbg(wpa_s, MSG_DEBUG,
4402 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004403 os_memset(freq_array, 0, sizeof(int) * len);
4404
4405 /* First add the frequency of the local interface */
4406 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4407 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4408 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4409 freq_array[idx++] = wpa_s->current_ssid->frequency;
4410 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4411 freq_array[idx++] = wpa_s->assoc_freq;
4412 }
4413
4414 /* If get_radio_name is not supported, use only the local freq */
4415 if (!wpa_s->driver->get_radio_name) {
4416 freq = wpa_drv_shared_freq(wpa_s);
4417 if (freq > 0 && idx < len &&
4418 (idx == 0 || freq_array[0] != freq))
4419 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004420 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004421 return idx;
4422 }
4423
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004424 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4425 radio_list) {
4426 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004427 continue;
4428
4429 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4430 continue;
4431
4432 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4433 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4434 freq = ifs->current_ssid->frequency;
4435 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4436 freq = ifs->assoc_freq;
4437 else
4438 continue;
4439
4440 /* Hold only distinct freqs */
4441 for (i = 0; i < idx; i++)
4442 if (freq_array[i] == freq)
4443 break;
4444
4445 if (i == idx)
4446 freq_array[idx++] = freq;
4447 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004448
4449 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004450 return idx;
4451}