blob: e21c653a7411f37ce74b17ed044cec585efe8a84 [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 Shmidt96be6222014-02-13 10:16:51 -08001659 params.bssid_hint = bss->bssid;
1660 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 } else {
1662 params.ssid = ssid->ssid;
1663 params.ssid_len = ssid->ssid_len;
1664 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001665
1666 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1667 wpa_s->conf->ap_scan == 2) {
1668 params.bssid = ssid->bssid;
1669 params.fixed_bssid = 1;
1670 }
1671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1673 params.freq == 0)
1674 params.freq = ssid->frequency; /* Initial channel for IBSS */
1675 params.wpa_ie = wpa_ie;
1676 params.wpa_ie_len = wpa_ie_len;
1677 params.pairwise_suite = cipher_pairwise;
1678 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001679 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001680 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001681 params.auth_alg = algs;
1682 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001683 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001684 for (i = 0; i < NUM_WEP_KEYS; i++) {
1685 if (ssid->wep_key_len[i])
1686 params.wep_key[i] = ssid->wep_key[i];
1687 params.wep_key_len[i] = ssid->wep_key_len[i];
1688 }
1689 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1690
1691 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001692 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1693 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001694 params.passphrase = ssid->passphrase;
1695 if (ssid->psk_set)
1696 params.psk = ssid->psk;
1697 }
1698
1699 params.drop_unencrypted = use_crypt;
1700
1701#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001702 params.mgmt_frame_protection =
1703 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1704 wpa_s->conf->pmf : ssid->ieee80211w;
1705 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1707 struct wpa_ie_data ie;
1708 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1709 ie.capabilities &
1710 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1711 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1712 "MFP: require MFP");
1713 params.mgmt_frame_protection =
1714 MGMT_FRAME_PROTECTION_REQUIRED;
1715 }
1716 }
1717#endif /* CONFIG_IEEE80211W */
1718
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001719 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720
1721 if (wpa_s->parent->set_sta_uapsd)
1722 params.uapsd = wpa_s->parent->sta_uapsd;
1723 else
1724 params.uapsd = -1;
1725
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001726#ifdef CONFIG_HT_OVERRIDES
1727 os_memset(&htcaps, 0, sizeof(htcaps));
1728 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1729 params.htcaps = (u8 *) &htcaps;
1730 params.htcaps_mask = (u8 *) &htcaps_mask;
1731 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1732#endif /* CONFIG_HT_OVERRIDES */
1733
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001734#ifdef CONFIG_P2P
1735 /*
1736 * If multi-channel concurrency is not supported, check for any
1737 * frequency conflict. In case of any frequency conflict, remove the
1738 * least prioritized connection.
1739 */
1740 if (wpa_s->num_multichan_concurrent < 2) {
1741 int freq = wpa_drv_shared_freq(wpa_s);
1742 if (freq > 0 && freq != params.freq) {
1743 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1744 freq, params.freq);
1745 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1746 params.freq,
1747 ssid) < 0)
1748 return;
1749 }
1750 }
1751#endif /* CONFIG_P2P */
1752
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001753 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001754 if (ret < 0) {
1755 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1756 "failed");
1757 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1758 /*
1759 * The driver is known to mean what is saying, so we
1760 * can stop right here; the association will not
1761 * succeed.
1762 */
1763 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001764 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1766 return;
1767 }
1768 /* try to continue anyway; new association will be tried again
1769 * after timeout */
1770 assoc_failed = 1;
1771 }
1772
1773 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1774 /* Set the key after the association just in case association
1775 * cleared the previously configured key. */
1776 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1777 /* No need to timeout authentication since there is no key
1778 * management. */
1779 wpa_supplicant_cancel_auth_timeout(wpa_s);
1780 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1781#ifdef CONFIG_IBSS_RSN
1782 } else if (ssid->mode == WPAS_MODE_IBSS &&
1783 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1784 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1785 /*
1786 * RSN IBSS authentication is per-STA and we can disable the
1787 * per-BSSID authentication.
1788 */
1789 wpa_supplicant_cancel_auth_timeout(wpa_s);
1790#endif /* CONFIG_IBSS_RSN */
1791 } else {
1792 /* Timeout for IEEE 802.11 authentication and association */
1793 int timeout = 60;
1794
1795 if (assoc_failed) {
1796 /* give IBSS a bit more time */
1797 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1798 } else if (wpa_s->conf->ap_scan == 1) {
1799 /* give IBSS a bit more time */
1800 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1801 }
1802 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1803 }
1804
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001805 if (wep_keys_set &&
1806 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807 /* Set static WEP keys again */
1808 wpa_set_wep_keys(wpa_s, ssid);
1809 }
1810
1811 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1812 /*
1813 * Do not allow EAP session resumption between different
1814 * network configurations.
1815 */
1816 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1817 }
1818 old_ssid = wpa_s->current_ssid;
1819 wpa_s->current_ssid = ssid;
1820 wpa_s->current_bss = bss;
1821 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1822 wpa_supplicant_initiate_eapol(wpa_s);
1823 if (old_ssid != wpa_s->current_ssid)
1824 wpas_notify_network_changed(wpa_s);
1825}
1826
1827
1828static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1829 const u8 *addr)
1830{
1831 struct wpa_ssid *old_ssid;
1832
1833 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001835 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 wpa_sm_set_config(wpa_s->wpa, NULL);
1837 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1838 if (old_ssid != wpa_s->current_ssid)
1839 wpas_notify_network_changed(wpa_s);
1840 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1841}
1842
1843
1844/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001845 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1846 * @wpa_s: Pointer to wpa_supplicant data
1847 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1848 *
1849 * This function is used to request %wpa_supplicant to deauthenticate from the
1850 * current AP.
1851 */
1852void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1853 int reason_code)
1854{
1855 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001856 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001857 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001859 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1860 " pending_bssid=" MACSTR " reason=%d state=%s",
1861 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1862 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1863
1864 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001866 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1867 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1868 wpa_s->wpa_state == WPA_ASSOCIATING))
1869 addr = wpa_s->pending_bssid;
1870 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1871 /*
1872 * When using driver-based BSS selection, we may not know the
1873 * BSSID with which we are currently trying to associate. We
1874 * need to notify the driver of this disconnection even in such
1875 * a case, so use the all zeros address here.
1876 */
1877 addr = wpa_s->bssid;
1878 zero_addr = 1;
1879 }
1880
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001881#ifdef CONFIG_TDLS
1882 wpa_tdls_teardown_peers(wpa_s->wpa);
1883#endif /* CONFIG_TDLS */
1884
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001885 if (addr) {
1886 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001887 os_memset(&event, 0, sizeof(event));
1888 event.deauth_info.reason_code = (u16) reason_code;
1889 event.deauth_info.locally_generated = 1;
1890 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001891 if (zero_addr)
1892 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893 }
1894
1895 wpa_supplicant_clear_connection(wpa_s, addr);
1896}
1897
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001898static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1899 struct wpa_ssid *ssid)
1900{
1901 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1902 return;
1903
1904 ssid->disabled = 0;
1905 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1906 wpas_notify_network_enabled_changed(wpa_s, ssid);
1907
1908 /*
1909 * Try to reassociate since there is no current configuration and a new
1910 * network was made available.
1911 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001912 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001913 wpa_s->reassociate = 1;
1914}
1915
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001916
1917/**
1918 * wpa_supplicant_enable_network - Mark a configured network as enabled
1919 * @wpa_s: wpa_supplicant structure for a network interface
1920 * @ssid: wpa_ssid structure for a configured network or %NULL
1921 *
1922 * Enables the specified network or all networks if no network specified.
1923 */
1924void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1925 struct wpa_ssid *ssid)
1926{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001927 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001928 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1929 wpa_supplicant_enable_one_network(wpa_s, ssid);
1930 } else
1931 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001933 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001934 if (wpa_s->sched_scanning) {
1935 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1936 "new network to scan filters");
1937 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 }
1939
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001940 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1941 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942 }
1943}
1944
1945
1946/**
1947 * wpa_supplicant_disable_network - Mark a configured network as disabled
1948 * @wpa_s: wpa_supplicant structure for a network interface
1949 * @ssid: wpa_ssid structure for a configured network or %NULL
1950 *
1951 * Disables the specified network or all networks if no network specified.
1952 */
1953void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1954 struct wpa_ssid *ssid)
1955{
1956 struct wpa_ssid *other_ssid;
1957 int was_disabled;
1958
1959 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001960 if (wpa_s->sched_scanning)
1961 wpa_supplicant_cancel_sched_scan(wpa_s);
1962
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001963 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1964 other_ssid = other_ssid->next) {
1965 was_disabled = other_ssid->disabled;
1966 if (was_disabled == 2)
1967 continue; /* do not change persistent P2P group
1968 * data */
1969
1970 other_ssid->disabled = 1;
1971
1972 if (was_disabled != other_ssid->disabled)
1973 wpas_notify_network_enabled_changed(
1974 wpa_s, other_ssid);
1975 }
1976 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001977 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1979 } else if (ssid->disabled != 2) {
1980 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001981 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1983
1984 was_disabled = ssid->disabled;
1985
1986 ssid->disabled = 1;
1987
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001988 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001989 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001990 if (wpa_s->sched_scanning) {
1991 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1992 "to remove network from filters");
1993 wpa_supplicant_cancel_sched_scan(wpa_s);
1994 wpa_supplicant_req_scan(wpa_s, 0, 0);
1995 }
1996 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001997 }
1998}
1999
2000
2001/**
2002 * wpa_supplicant_select_network - Attempt association with a network
2003 * @wpa_s: wpa_supplicant structure for a network interface
2004 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2005 */
2006void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2007 struct wpa_ssid *ssid)
2008{
2009
2010 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002011 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002013 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002014 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002015 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002016 disconnected = 1;
2017 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002019 if (ssid)
2020 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2021
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 /*
2023 * Mark all other networks disabled or mark all networks enabled if no
2024 * network specified.
2025 */
2026 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2027 other_ssid = other_ssid->next) {
2028 int was_disabled = other_ssid->disabled;
2029 if (was_disabled == 2)
2030 continue; /* do not change persistent P2P group data */
2031
2032 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002033 if (was_disabled && !other_ssid->disabled)
2034 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002035
2036 if (was_disabled != other_ssid->disabled)
2037 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2038 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002039
2040 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2041 /* We are already associated with the selected network */
2042 wpa_printf(MSG_DEBUG, "Already associated with the "
2043 "selected network - do nothing");
2044 return;
2045 }
2046
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002047 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002048 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002049 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2050 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002051 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052 wpa_s->disconnected = 0;
2053 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002054
2055 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2056 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057
2058 if (ssid)
2059 wpas_notify_network_selected(wpa_s, ssid);
2060}
2061
2062
2063/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002064 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2065 * @wpa_s: wpa_supplicant structure for a network interface
2066 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2067 * @pkcs11_module_path: PKCS #11 module path or NULL
2068 * Returns: 0 on success; -1 on failure
2069 *
2070 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2071 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2072 * module path fails the paths will be reset to the default value (NULL).
2073 */
2074int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2075 const char *pkcs11_engine_path,
2076 const char *pkcs11_module_path)
2077{
2078 char *pkcs11_engine_path_copy = NULL;
2079 char *pkcs11_module_path_copy = NULL;
2080
2081 if (pkcs11_engine_path != NULL) {
2082 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2083 if (pkcs11_engine_path_copy == NULL)
2084 return -1;
2085 }
2086 if (pkcs11_module_path != NULL) {
2087 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002088 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002089 os_free(pkcs11_engine_path_copy);
2090 return -1;
2091 }
2092 }
2093
2094 os_free(wpa_s->conf->pkcs11_engine_path);
2095 os_free(wpa_s->conf->pkcs11_module_path);
2096 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2097 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2098
2099 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2100 eapol_sm_deinit(wpa_s->eapol);
2101 wpa_s->eapol = NULL;
2102 if (wpa_supplicant_init_eapol(wpa_s)) {
2103 /* Error -> Reset paths to the default value (NULL) once. */
2104 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2105 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2106 NULL);
2107
2108 return -1;
2109 }
2110 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2111
2112 return 0;
2113}
2114
2115
2116/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002117 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2118 * @wpa_s: wpa_supplicant structure for a network interface
2119 * @ap_scan: AP scan mode
2120 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2121 *
2122 */
2123int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2124{
2125
2126 int old_ap_scan;
2127
2128 if (ap_scan < 0 || ap_scan > 2)
2129 return -1;
2130
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002131#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002132 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2133 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2134 wpa_s->wpa_state < WPA_COMPLETED) {
2135 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2136 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002137 return 0;
2138 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002139#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002140
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002141 old_ap_scan = wpa_s->conf->ap_scan;
2142 wpa_s->conf->ap_scan = ap_scan;
2143
2144 if (old_ap_scan != wpa_s->conf->ap_scan)
2145 wpas_notify_ap_scan_changed(wpa_s);
2146
2147 return 0;
2148}
2149
2150
2151/**
2152 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2153 * @wpa_s: wpa_supplicant structure for a network interface
2154 * @expire_age: Expiration age in seconds
2155 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2156 *
2157 */
2158int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2159 unsigned int bss_expire_age)
2160{
2161 if (bss_expire_age < 10) {
2162 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2163 bss_expire_age);
2164 return -1;
2165 }
2166 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2167 bss_expire_age);
2168 wpa_s->conf->bss_expiration_age = bss_expire_age;
2169
2170 return 0;
2171}
2172
2173
2174/**
2175 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2176 * @wpa_s: wpa_supplicant structure for a network interface
2177 * @expire_count: number of scans after which an unseen BSS is reclaimed
2178 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2179 *
2180 */
2181int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2182 unsigned int bss_expire_count)
2183{
2184 if (bss_expire_count < 1) {
2185 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2186 bss_expire_count);
2187 return -1;
2188 }
2189 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2190 bss_expire_count);
2191 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2192
2193 return 0;
2194}
2195
2196
2197/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002198 * wpa_supplicant_set_scan_interval - Set scan interval
2199 * @wpa_s: wpa_supplicant structure for a network interface
2200 * @scan_interval: scan interval in seconds
2201 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2202 *
2203 */
2204int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2205 int scan_interval)
2206{
2207 if (scan_interval < 0) {
2208 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2209 scan_interval);
2210 return -1;
2211 }
2212 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2213 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002214 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002215
2216 return 0;
2217}
2218
2219
2220/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 * wpa_supplicant_set_debug_params - Set global debug params
2222 * @global: wpa_global structure
2223 * @debug_level: debug level
2224 * @debug_timestamp: determines if show timestamp in debug data
2225 * @debug_show_keys: determines if show keys in debug data
2226 * Returns: 0 if succeed or -1 if debug_level has wrong value
2227 */
2228int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2229 int debug_timestamp, int debug_show_keys)
2230{
2231
2232 int old_level, old_timestamp, old_show_keys;
2233
2234 /* check for allowed debuglevels */
2235 if (debug_level != MSG_EXCESSIVE &&
2236 debug_level != MSG_MSGDUMP &&
2237 debug_level != MSG_DEBUG &&
2238 debug_level != MSG_INFO &&
2239 debug_level != MSG_WARNING &&
2240 debug_level != MSG_ERROR)
2241 return -1;
2242
2243 old_level = wpa_debug_level;
2244 old_timestamp = wpa_debug_timestamp;
2245 old_show_keys = wpa_debug_show_keys;
2246
2247 wpa_debug_level = debug_level;
2248 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2249 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2250
2251 if (wpa_debug_level != old_level)
2252 wpas_notify_debug_level_changed(global);
2253 if (wpa_debug_timestamp != old_timestamp)
2254 wpas_notify_debug_timestamp_changed(global);
2255 if (wpa_debug_show_keys != old_show_keys)
2256 wpas_notify_debug_show_keys_changed(global);
2257
2258 return 0;
2259}
2260
2261
2262/**
2263 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2264 * @wpa_s: Pointer to wpa_supplicant data
2265 * Returns: A pointer to the current network structure or %NULL on failure
2266 */
2267struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2268{
2269 struct wpa_ssid *entry;
2270 u8 ssid[MAX_SSID_LEN];
2271 int res;
2272 size_t ssid_len;
2273 u8 bssid[ETH_ALEN];
2274 int wired;
2275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276 res = wpa_drv_get_ssid(wpa_s, ssid);
2277 if (res < 0) {
2278 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2279 "driver");
2280 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002282 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002283
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002284 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002285 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2286 "driver");
2287 return NULL;
2288 }
2289
2290 wired = wpa_s->conf->ap_scan == 0 &&
2291 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2292
2293 entry = wpa_s->conf->ssid;
2294 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002295 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 ((ssid_len == entry->ssid_len &&
2297 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2298 (!entry->bssid_set ||
2299 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2300 return entry;
2301#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002302 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002303 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2304 (entry->ssid == NULL || entry->ssid_len == 0) &&
2305 (!entry->bssid_set ||
2306 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2307 return entry;
2308#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002309
Dmitry Shmidt04949592012-07-19 12:16:46 -07002310 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002311 entry->ssid_len == 0 &&
2312 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2313 return entry;
2314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 entry = entry->next;
2316 }
2317
2318 return NULL;
2319}
2320
2321
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002322static int select_driver(struct wpa_supplicant *wpa_s, int i)
2323{
2324 struct wpa_global *global = wpa_s->global;
2325
2326 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2327 global->drv_priv[i] = wpa_drivers[i]->global_init();
2328 if (global->drv_priv[i] == NULL) {
2329 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2330 "'%s'", wpa_drivers[i]->name);
2331 return -1;
2332 }
2333 }
2334
2335 wpa_s->driver = wpa_drivers[i];
2336 wpa_s->global_drv_priv = global->drv_priv[i];
2337
2338 return 0;
2339}
2340
2341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2343 const char *name)
2344{
2345 int i;
2346 size_t len;
2347 const char *pos, *driver = name;
2348
2349 if (wpa_s == NULL)
2350 return -1;
2351
2352 if (wpa_drivers[0] == NULL) {
2353 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2354 "wpa_supplicant");
2355 return -1;
2356 }
2357
2358 if (name == NULL) {
2359 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002360 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 }
2362
2363 do {
2364 pos = os_strchr(driver, ',');
2365 if (pos)
2366 len = pos - driver;
2367 else
2368 len = os_strlen(driver);
2369
2370 for (i = 0; wpa_drivers[i]; i++) {
2371 if (os_strlen(wpa_drivers[i]->name) == len &&
2372 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002373 0) {
2374 /* First driver that succeeds wins */
2375 if (select_driver(wpa_s, i) == 0)
2376 return 0;
2377 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 }
2379
2380 driver = pos + 1;
2381 } while (pos);
2382
2383 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2384 return -1;
2385}
2386
2387
2388/**
2389 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2390 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2391 * with struct wpa_driver_ops::init()
2392 * @src_addr: Source address of the EAPOL frame
2393 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2394 * @len: Length of the EAPOL data
2395 *
2396 * This function is called for each received EAPOL frame. Most driver
2397 * interfaces rely on more generic OS mechanism for receiving frames through
2398 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2399 * take care of received EAPOL frames and deliver them to the core supplicant
2400 * code by calling this function.
2401 */
2402void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2403 const u8 *buf, size_t len)
2404{
2405 struct wpa_supplicant *wpa_s = ctx;
2406
2407 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2408 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2409
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002410#ifdef CONFIG_PEERKEY
2411 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2412 wpa_s->current_ssid->peerkey &&
2413 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2414 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2415 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2416 return;
2417 }
2418#endif /* CONFIG_PEERKEY */
2419
Jouni Malinena05074c2012-12-21 21:35:35 +02002420 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2421 (wpa_s->last_eapol_matches_bssid &&
2422#ifdef CONFIG_AP
2423 !wpa_s->ap_iface &&
2424#endif /* CONFIG_AP */
2425 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 /*
2427 * There is possible race condition between receiving the
2428 * association event and the EAPOL frame since they are coming
2429 * through different paths from the driver. In order to avoid
2430 * issues in trying to process the EAPOL frame before receiving
2431 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002432 * the association event is received. This may also be needed in
2433 * driver-based roaming case, so also use src_addr != BSSID as a
2434 * trigger if we have previously confirmed that the
2435 * Authenticator uses BSSID as the src_addr (which is not the
2436 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 */
2438 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002439 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2440 wpa_supplicant_state_txt(wpa_s->wpa_state),
2441 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 wpabuf_free(wpa_s->pending_eapol_rx);
2443 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2444 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002445 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2447 ETH_ALEN);
2448 }
2449 return;
2450 }
2451
Jouni Malinena05074c2012-12-21 21:35:35 +02002452 wpa_s->last_eapol_matches_bssid =
2453 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2454
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455#ifdef CONFIG_AP
2456 if (wpa_s->ap_iface) {
2457 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2458 return;
2459 }
2460#endif /* CONFIG_AP */
2461
2462 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2463 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2464 "no key management is configured");
2465 return;
2466 }
2467
2468 if (wpa_s->eapol_received == 0 &&
2469 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2470 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2471 wpa_s->wpa_state != WPA_COMPLETED) &&
2472 (wpa_s->current_ssid == NULL ||
2473 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2474 /* Timeout for completing IEEE 802.1X and WPA authentication */
2475 wpa_supplicant_req_auth_timeout(
2476 wpa_s,
2477 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2478 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2479 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2480 70 : 10, 0);
2481 }
2482 wpa_s->eapol_received++;
2483
2484 if (wpa_s->countermeasures) {
2485 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2486 "EAPOL packet");
2487 return;
2488 }
2489
2490#ifdef CONFIG_IBSS_RSN
2491 if (wpa_s->current_ssid &&
2492 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2493 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2494 return;
2495 }
2496#endif /* CONFIG_IBSS_RSN */
2497
2498 /* Source address of the incoming EAPOL frame could be compared to the
2499 * current BSSID. However, it is possible that a centralized
2500 * Authenticator could be using another MAC address than the BSSID of
2501 * an AP, so just allow any address to be used for now. The replies are
2502 * still sent to the current BSSID (if available), though. */
2503
2504 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2505 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2506 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2507 return;
2508 wpa_drv_poll(wpa_s);
2509 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2510 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2511 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2512 /*
2513 * Set portValid = TRUE here since we are going to skip 4-way
2514 * handshake processing which would normally set portValid. We
2515 * need this to allow the EAPOL state machines to be completed
2516 * without going through EAPOL-Key handshake.
2517 */
2518 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2519 }
2520}
2521
2522
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002523int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 if (wpa_s->driver->send_eapol) {
2526 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2527 if (addr)
2528 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002529 } else if ((!wpa_s->p2p_mgmt ||
2530 !(wpa_s->drv_flags &
2531 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2532 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002534 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2536 wpa_drv_get_mac_addr(wpa_s),
2537 ETH_P_EAPOL,
2538 wpa_supplicant_rx_eapol, wpa_s, 0);
2539 if (wpa_s->l2 == NULL)
2540 return -1;
2541 } else {
2542 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2543 if (addr)
2544 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2545 }
2546
2547 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2548 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2549 return -1;
2550 }
2551
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002552 return 0;
2553}
2554
2555
Dmitry Shmidt04949592012-07-19 12:16:46 -07002556static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2557 const u8 *buf, size_t len)
2558{
2559 struct wpa_supplicant *wpa_s = ctx;
2560 const struct l2_ethhdr *eth;
2561
2562 if (len < sizeof(*eth))
2563 return;
2564 eth = (const struct l2_ethhdr *) buf;
2565
2566 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2567 !(eth->h_dest[0] & 0x01)) {
2568 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2569 " (bridge - not for this interface - ignore)",
2570 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2571 return;
2572 }
2573
2574 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2575 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2576 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2577 len - sizeof(*eth));
2578}
2579
2580
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002581/**
2582 * wpa_supplicant_driver_init - Initialize driver interface parameters
2583 * @wpa_s: Pointer to wpa_supplicant data
2584 * Returns: 0 on success, -1 on failure
2585 *
2586 * This function is called to initialize driver interface parameters.
2587 * wpa_drv_init() must have been called before this function to initialize the
2588 * driver interface.
2589 */
2590int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2591{
2592 static int interface_count = 0;
2593
2594 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2595 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002597 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2598 MAC2STR(wpa_s->own_addr));
2599 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 if (wpa_s->bridge_ifname[0]) {
2602 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2603 "interface '%s'", wpa_s->bridge_ifname);
2604 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2605 wpa_s->own_addr,
2606 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002607 wpa_supplicant_rx_eapol_bridge,
2608 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 if (wpa_s->l2_br == NULL) {
2610 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2611 "connection for the bridge interface '%s'",
2612 wpa_s->bridge_ifname);
2613 return -1;
2614 }
2615 }
2616
2617 wpa_clear_keys(wpa_s, NULL);
2618
2619 /* Make sure that TKIP countermeasures are not left enabled (could
2620 * happen if wpa_supplicant is killed during countermeasures. */
2621 wpa_drv_set_countermeasures(wpa_s, 0);
2622
2623 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2624 wpa_drv_flush_pmkid(wpa_s);
2625
2626 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002627 wpa_s->prev_scan_wildcard = 0;
2628
Dmitry Shmidt04949592012-07-19 12:16:46 -07002629 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002630 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2631 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2632 interface_count = 0;
2633 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002634 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2635 100000))
2636 wpa_supplicant_req_scan(wpa_s, interface_count,
2637 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 interface_count++;
2639 } else
2640 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2641
2642 return 0;
2643}
2644
2645
2646static int wpa_supplicant_daemon(const char *pid_file)
2647{
2648 wpa_printf(MSG_DEBUG, "Daemonize..");
2649 return os_daemonize(pid_file);
2650}
2651
2652
2653static struct wpa_supplicant * wpa_supplicant_alloc(void)
2654{
2655 struct wpa_supplicant *wpa_s;
2656
2657 wpa_s = os_zalloc(sizeof(*wpa_s));
2658 if (wpa_s == NULL)
2659 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002660 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 wpa_s->scan_interval = 5;
2662 wpa_s->new_connection = 1;
2663 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002664 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002665
2666 return wpa_s;
2667}
2668
2669
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002670#ifdef CONFIG_HT_OVERRIDES
2671
2672static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2673 struct ieee80211_ht_capabilities *htcaps,
2674 struct ieee80211_ht_capabilities *htcaps_mask,
2675 const char *ht_mcs)
2676{
2677 /* parse ht_mcs into hex array */
2678 int i;
2679 const char *tmp = ht_mcs;
2680 char *end = NULL;
2681
2682 /* If ht_mcs is null, do not set anything */
2683 if (!ht_mcs)
2684 return 0;
2685
2686 /* This is what we are setting in the kernel */
2687 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2688
2689 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2690
2691 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2692 errno = 0;
2693 long v = strtol(tmp, &end, 16);
2694 if (errno == 0) {
2695 wpa_msg(wpa_s, MSG_DEBUG,
2696 "htcap value[%i]: %ld end: %p tmp: %p",
2697 i, v, end, tmp);
2698 if (end == tmp)
2699 break;
2700
2701 htcaps->supported_mcs_set[i] = v;
2702 tmp = end;
2703 } else {
2704 wpa_msg(wpa_s, MSG_ERROR,
2705 "Failed to parse ht-mcs: %s, error: %s\n",
2706 ht_mcs, strerror(errno));
2707 return -1;
2708 }
2709 }
2710
2711 /*
2712 * If we were able to parse any values, then set mask for the MCS set.
2713 */
2714 if (i) {
2715 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2716 IEEE80211_HT_MCS_MASK_LEN - 1);
2717 /* skip the 3 reserved bits */
2718 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2719 0x1f;
2720 }
2721
2722 return 0;
2723}
2724
2725
2726static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2727 struct ieee80211_ht_capabilities *htcaps,
2728 struct ieee80211_ht_capabilities *htcaps_mask,
2729 int disabled)
2730{
2731 u16 msk;
2732
2733 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2734
2735 if (disabled == -1)
2736 return 0;
2737
2738 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2739 htcaps_mask->ht_capabilities_info |= msk;
2740 if (disabled)
2741 htcaps->ht_capabilities_info &= msk;
2742 else
2743 htcaps->ht_capabilities_info |= msk;
2744
2745 return 0;
2746}
2747
2748
2749static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2750 struct ieee80211_ht_capabilities *htcaps,
2751 struct ieee80211_ht_capabilities *htcaps_mask,
2752 int factor)
2753{
2754 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2755
2756 if (factor == -1)
2757 return 0;
2758
2759 if (factor < 0 || factor > 3) {
2760 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2761 "Must be 0-3 or -1", factor);
2762 return -EINVAL;
2763 }
2764
2765 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2766 htcaps->a_mpdu_params &= ~0x3;
2767 htcaps->a_mpdu_params |= factor & 0x3;
2768
2769 return 0;
2770}
2771
2772
2773static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2774 struct ieee80211_ht_capabilities *htcaps,
2775 struct ieee80211_ht_capabilities *htcaps_mask,
2776 int density)
2777{
2778 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2779
2780 if (density == -1)
2781 return 0;
2782
2783 if (density < 0 || density > 7) {
2784 wpa_msg(wpa_s, MSG_ERROR,
2785 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2786 density);
2787 return -EINVAL;
2788 }
2789
2790 htcaps_mask->a_mpdu_params |= 0x1C;
2791 htcaps->a_mpdu_params &= ~(0x1C);
2792 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2793
2794 return 0;
2795}
2796
2797
2798static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2799 struct ieee80211_ht_capabilities *htcaps,
2800 struct ieee80211_ht_capabilities *htcaps_mask,
2801 int disabled)
2802{
2803 /* Masking these out disables HT40 */
2804 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2805 HT_CAP_INFO_SHORT_GI40MHZ);
2806
2807 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2808
2809 if (disabled)
2810 htcaps->ht_capabilities_info &= ~msk;
2811 else
2812 htcaps->ht_capabilities_info |= msk;
2813
2814 htcaps_mask->ht_capabilities_info |= msk;
2815
2816 return 0;
2817}
2818
2819
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002820static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2821 struct ieee80211_ht_capabilities *htcaps,
2822 struct ieee80211_ht_capabilities *htcaps_mask,
2823 int disabled)
2824{
2825 /* Masking these out disables SGI */
2826 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2827 HT_CAP_INFO_SHORT_GI40MHZ);
2828
2829 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2830
2831 if (disabled)
2832 htcaps->ht_capabilities_info &= ~msk;
2833 else
2834 htcaps->ht_capabilities_info |= msk;
2835
2836 htcaps_mask->ht_capabilities_info |= msk;
2837
2838 return 0;
2839}
2840
2841
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002842void wpa_supplicant_apply_ht_overrides(
2843 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2844 struct wpa_driver_associate_params *params)
2845{
2846 struct ieee80211_ht_capabilities *htcaps;
2847 struct ieee80211_ht_capabilities *htcaps_mask;
2848
2849 if (!ssid)
2850 return;
2851
2852 params->disable_ht = ssid->disable_ht;
2853 if (!params->htcaps || !params->htcaps_mask)
2854 return;
2855
2856 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2857 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2858 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2859 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2860 ssid->disable_max_amsdu);
2861 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2862 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2863 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002864 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002865}
2866
2867#endif /* CONFIG_HT_OVERRIDES */
2868
2869
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002870#ifdef CONFIG_VHT_OVERRIDES
2871void wpa_supplicant_apply_vht_overrides(
2872 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2873 struct wpa_driver_associate_params *params)
2874{
2875 struct ieee80211_vht_capabilities *vhtcaps;
2876 struct ieee80211_vht_capabilities *vhtcaps_mask;
2877
2878 if (!ssid)
2879 return;
2880
2881 params->disable_vht = ssid->disable_vht;
2882
2883 vhtcaps = (void *) params->vhtcaps;
2884 vhtcaps_mask = (void *) params->vhtcaps_mask;
2885
2886 if (!vhtcaps || !vhtcaps_mask)
2887 return;
2888
2889 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2890 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2891
2892#define OVERRIDE_MCS(i) \
2893 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2894 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2895 3 << 2 * (i - 1); \
2896 vhtcaps->vht_supported_mcs_set.tx_map |= \
2897 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2898 } \
2899 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2900 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2901 3 << 2 * (i - 1); \
2902 vhtcaps->vht_supported_mcs_set.rx_map |= \
2903 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2904 }
2905
2906 OVERRIDE_MCS(1);
2907 OVERRIDE_MCS(2);
2908 OVERRIDE_MCS(3);
2909 OVERRIDE_MCS(4);
2910 OVERRIDE_MCS(5);
2911 OVERRIDE_MCS(6);
2912 OVERRIDE_MCS(7);
2913 OVERRIDE_MCS(8);
2914}
2915#endif /* CONFIG_VHT_OVERRIDES */
2916
2917
Dmitry Shmidt04949592012-07-19 12:16:46 -07002918static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2919{
2920#ifdef PCSC_FUNCS
2921 size_t len;
2922
2923 if (!wpa_s->conf->pcsc_reader)
2924 return 0;
2925
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002926 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002927 if (!wpa_s->scard)
2928 return 1;
2929
2930 if (wpa_s->conf->pcsc_pin &&
2931 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2932 scard_deinit(wpa_s->scard);
2933 wpa_s->scard = NULL;
2934 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2935 return -1;
2936 }
2937
2938 len = sizeof(wpa_s->imsi) - 1;
2939 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2940 scard_deinit(wpa_s->scard);
2941 wpa_s->scard = NULL;
2942 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2943 return -1;
2944 }
2945 wpa_s->imsi[len] = '\0';
2946
2947 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2948
2949 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2950 wpa_s->imsi, wpa_s->mnc_len);
2951
2952 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2953 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2954#endif /* PCSC_FUNCS */
2955
2956 return 0;
2957}
2958
2959
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002960int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2961{
2962 char *val, *pos;
2963
2964 ext_password_deinit(wpa_s->ext_pw);
2965 wpa_s->ext_pw = NULL;
2966 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2967
2968 if (!wpa_s->conf->ext_password_backend)
2969 return 0;
2970
2971 val = os_strdup(wpa_s->conf->ext_password_backend);
2972 if (val == NULL)
2973 return -1;
2974 pos = os_strchr(val, ':');
2975 if (pos)
2976 *pos++ = '\0';
2977
2978 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2979
2980 wpa_s->ext_pw = ext_password_init(val, pos);
2981 os_free(val);
2982 if (wpa_s->ext_pw == NULL) {
2983 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2984 return -1;
2985 }
2986 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2987
2988 return 0;
2989}
2990
2991
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002992static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2993 const char *rn)
2994{
2995 struct wpa_supplicant *iface = wpa_s->global->ifaces;
2996 struct wpa_radio *radio;
2997
2998 while (rn && iface) {
2999 radio = iface->radio;
3000 if (radio && os_strcmp(rn, radio->name) == 0) {
3001 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3002 wpa_s->ifname, rn);
3003 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3004 return radio;
3005 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003006
3007 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003008 }
3009
3010 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3011 wpa_s->ifname, rn ? rn : "N/A");
3012 radio = os_zalloc(sizeof(*radio));
3013 if (radio == NULL)
3014 return NULL;
3015
3016 if (rn)
3017 os_strlcpy(radio->name, rn, sizeof(radio->name));
3018 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003019 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003020 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3021
3022 return radio;
3023}
3024
3025
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003026static void radio_work_free(struct wpa_radio_work *work)
3027{
3028 if (work->wpa_s->scan_work == work) {
3029 /* This should not really happen. */
3030 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3031 work->type, work, work->started);
3032 work->wpa_s->scan_work = NULL;
3033 }
3034
3035#ifdef CONFIG_P2P
3036 if (work->wpa_s->p2p_scan_work == work) {
3037 /* This should not really happen. */
3038 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3039 work->type, work, work->started);
3040 work->wpa_s->p2p_scan_work = NULL;
3041 }
3042#endif /* CONFIG_P2P */
3043
3044 dl_list_del(&work->list);
3045 os_free(work);
3046}
3047
3048
3049static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3050{
3051 struct wpa_radio *radio = eloop_ctx;
3052 struct wpa_radio_work *work;
3053 struct os_reltime now, diff;
3054 struct wpa_supplicant *wpa_s;
3055
3056 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3057 if (work == NULL)
3058 return;
3059
3060 if (work->started)
3061 return; /* already started and still in progress */
3062
3063 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3064 radio_list);
3065 if (wpa_s && wpa_s->external_scan_running) {
3066 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3067 return;
3068 }
3069
3070 os_get_reltime(&now);
3071 os_reltime_sub(&now, &work->time, &diff);
3072 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3073 work->type, work, diff.sec, diff.usec);
3074 work->started = 1;
3075 work->time = now;
3076 work->cb(work, 0);
3077}
3078
3079
3080void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
3081{
3082 struct wpa_radio_work *work, *tmp;
3083 struct wpa_radio *radio = wpa_s->radio;
3084
3085 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3086 list) {
3087 if (type && (work->started || os_strcmp(type, work->type) != 0))
3088 continue;
3089 if (work->started) {
3090 wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
3091 work->type, work);
3092 continue;
3093 }
3094 wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
3095 work->type, work);
3096 work->cb(work, 1);
3097 radio_work_free(work);
3098 }
3099}
3100
3101
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003102static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3103{
3104 struct wpa_radio *radio = wpa_s->radio;
3105
3106 if (!radio)
3107 return;
3108
3109 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3110 wpa_s->ifname, radio->name);
3111 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003112 if (!dl_list_empty(&radio->ifaces)) {
3113 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003114 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003115 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003116
3117 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003118 radio_remove_unstarted_work(wpa_s, NULL);
3119 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3120 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003121 os_free(radio);
3122}
3123
3124
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003125void radio_work_check_next(struct wpa_supplicant *wpa_s)
3126{
3127 struct wpa_radio *radio = wpa_s->radio;
3128
3129 if (dl_list_empty(&radio->work))
3130 return;
3131 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3132 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3133}
3134
3135
3136/**
3137 * radio_add_work - Add a radio work item
3138 * @wpa_s: Pointer to wpa_supplicant data
3139 * @freq: Frequency of the offchannel operation in MHz or 0
3140 * @type: Unique identifier for each type of work
3141 * @next: Force as the next work to be executed
3142 * @cb: Callback function for indicating when radio is available
3143 * @ctx: Context pointer for the work (work->ctx in cb())
3144 * Returns: 0 on success, -1 on failure
3145 *
3146 * This function is used to request time for an operation that requires
3147 * exclusive radio control. Once the radio is available, the registered callback
3148 * function will be called. radio_work_done() must be called once the exclusive
3149 * radio operation has been completed, so that the radio is freed for other
3150 * operations. The special case of deinit=1 is used to free the context data
3151 * during interface removal. That does not allow the callback function to start
3152 * the radio operation, i.e., it must free any resources allocated for the radio
3153 * work and return.
3154 *
3155 * The @freq parameter can be used to indicate a single channel on which the
3156 * offchannel operation will occur. This may allow multiple radio work
3157 * operations to be performed in parallel if they apply for the same channel.
3158 * Setting this to 0 indicates that the work item may use multiple channels or
3159 * requires exclusive control of the radio.
3160 */
3161int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3162 const char *type, int next,
3163 void (*cb)(struct wpa_radio_work *work, int deinit),
3164 void *ctx)
3165{
3166 struct wpa_radio_work *work;
3167 int was_empty;
3168
3169 work = os_zalloc(sizeof(*work));
3170 if (work == NULL)
3171 return -1;
3172 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3173 os_get_reltime(&work->time);
3174 work->freq = freq;
3175 work->type = type;
3176 work->wpa_s = wpa_s;
3177 work->cb = cb;
3178 work->ctx = ctx;
3179
3180 was_empty = dl_list_empty(&wpa_s->radio->work);
3181 if (next)
3182 dl_list_add(&wpa_s->radio->work, &work->list);
3183 else
3184 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3185 if (was_empty) {
3186 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3187 radio_work_check_next(wpa_s);
3188 }
3189
3190 return 0;
3191}
3192
3193
3194/**
3195 * radio_work_done - Indicate that a radio work item has been completed
3196 * @work: Completed work
3197 *
3198 * This function is called once the callback function registered with
3199 * radio_add_work() has completed its work.
3200 */
3201void radio_work_done(struct wpa_radio_work *work)
3202{
3203 struct wpa_supplicant *wpa_s = work->wpa_s;
3204 struct os_reltime now, diff;
3205 unsigned int started = work->started;
3206
3207 os_get_reltime(&now);
3208 os_reltime_sub(&now, &work->time, &diff);
3209 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3210 work->type, work, started ? "done" : "canceled",
3211 diff.sec, diff.usec);
3212 radio_work_free(work);
3213 if (started)
3214 radio_work_check_next(wpa_s);
3215}
3216
3217
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003218static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3219 struct wpa_interface *iface)
3220{
3221 const char *ifname, *driver, *rn;
3222
3223 driver = iface->driver;
3224next_driver:
3225 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3226 return -1;
3227
3228 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3229 if (wpa_s->drv_priv == NULL) {
3230 const char *pos;
3231 pos = driver ? os_strchr(driver, ',') : NULL;
3232 if (pos) {
3233 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3234 "driver interface - try next driver wrapper");
3235 driver = pos + 1;
3236 goto next_driver;
3237 }
3238 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3239 "interface");
3240 return -1;
3241 }
3242 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3243 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3244 "driver_param '%s'", wpa_s->conf->driver_param);
3245 return -1;
3246 }
3247
3248 ifname = wpa_drv_get_ifname(wpa_s);
3249 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3250 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3251 "interface name with '%s'", ifname);
3252 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3253 }
3254
3255 if (wpa_s->driver->get_radio_name)
3256 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3257 else
3258 rn = NULL;
3259 if (rn && rn[0] == '\0')
3260 rn = NULL;
3261
3262 wpa_s->radio = radio_add_interface(wpa_s, rn);
3263 if (wpa_s->radio == NULL)
3264 return -1;
3265
3266 return 0;
3267}
3268
3269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3271 struct wpa_interface *iface)
3272{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003273 struct wpa_driver_capa capa;
3274
3275 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3276 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3277 iface->confname ? iface->confname : "N/A",
3278 iface->driver ? iface->driver : "default",
3279 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3280 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3281
3282 if (iface->confname) {
3283#ifdef CONFIG_BACKEND_FILE
3284 wpa_s->confname = os_rel2abs_path(iface->confname);
3285 if (wpa_s->confname == NULL) {
3286 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3287 "for configuration file '%s'.",
3288 iface->confname);
3289 return -1;
3290 }
3291 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3292 iface->confname, wpa_s->confname);
3293#else /* CONFIG_BACKEND_FILE */
3294 wpa_s->confname = os_strdup(iface->confname);
3295#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003296 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003297 if (wpa_s->conf == NULL) {
3298 wpa_printf(MSG_ERROR, "Failed to read or parse "
3299 "configuration '%s'.", wpa_s->confname);
3300 return -1;
3301 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003302 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3303 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003304
3305 /*
3306 * Override ctrl_interface and driver_param if set on command
3307 * line.
3308 */
3309 if (iface->ctrl_interface) {
3310 os_free(wpa_s->conf->ctrl_interface);
3311 wpa_s->conf->ctrl_interface =
3312 os_strdup(iface->ctrl_interface);
3313 }
3314
3315 if (iface->driver_param) {
3316 os_free(wpa_s->conf->driver_param);
3317 wpa_s->conf->driver_param =
3318 os_strdup(iface->driver_param);
3319 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003320
3321 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3322 os_free(wpa_s->conf->ctrl_interface);
3323 wpa_s->conf->ctrl_interface = NULL;
3324 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 } else
3326 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3327 iface->driver_param);
3328
3329 if (wpa_s->conf == NULL) {
3330 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3331 return -1;
3332 }
3333
3334 if (iface->ifname == NULL) {
3335 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3336 return -1;
3337 }
3338 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3339 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3340 iface->ifname);
3341 return -1;
3342 }
3343 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3344
3345 if (iface->bridge_ifname) {
3346 if (os_strlen(iface->bridge_ifname) >=
3347 sizeof(wpa_s->bridge_ifname)) {
3348 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3349 "name '%s'.", iface->bridge_ifname);
3350 return -1;
3351 }
3352 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3353 sizeof(wpa_s->bridge_ifname));
3354 }
3355
3356 /* RSNA Supplicant Key Management - INITIALIZE */
3357 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3358 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3359
3360 /* Initialize driver interface and register driver event handler before
3361 * L2 receive handler so that association events are processed before
3362 * EAPOL-Key packets if both become available for the same select()
3363 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003364 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003365 return -1;
3366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3368 return -1;
3369
3370 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3371 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3372 NULL);
3373 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3374
3375 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3376 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3377 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3378 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3379 "dot11RSNAConfigPMKLifetime");
3380 return -1;
3381 }
3382
3383 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3384 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3385 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3386 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3387 "dot11RSNAConfigPMKReauthThreshold");
3388 return -1;
3389 }
3390
3391 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3392 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3393 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3394 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3395 "dot11RSNAConfigSATimeout");
3396 return -1;
3397 }
3398
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003399 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3400 &wpa_s->hw.num_modes,
3401 &wpa_s->hw.flags);
3402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003403 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003404 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003406 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003407 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003408 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003409 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3410 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3411 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3413 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003414 wpa_s->extended_capa = capa.extended_capa;
3415 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3416 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003417 wpa_s->num_multichan_concurrent =
3418 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419 }
3420 if (wpa_s->max_remain_on_chan == 0)
3421 wpa_s->max_remain_on_chan = 1000;
3422
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003423 /*
3424 * Only take p2p_mgmt parameters when P2P Device is supported.
3425 * Doing it here as it determines whether l2_packet_init() will be done
3426 * during wpa_supplicant_driver_init().
3427 */
3428 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3429 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3430 else
3431 iface->p2p_mgmt = 1;
3432
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003433 if (wpa_s->num_multichan_concurrent == 0)
3434 wpa_s->num_multichan_concurrent = 1;
3435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003436 if (wpa_supplicant_driver_init(wpa_s) < 0)
3437 return -1;
3438
3439#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003440 if ((!iface->p2p_mgmt ||
3441 !(wpa_s->drv_flags &
3442 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3443 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444 return -1;
3445#endif /* CONFIG_TDLS */
3446
3447 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3448 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3449 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3450 return -1;
3451 }
3452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453 if (wpas_wps_init(wpa_s))
3454 return -1;
3455
3456 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3457 return -1;
3458 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3459
3460 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3461 if (wpa_s->ctrl_iface == NULL) {
3462 wpa_printf(MSG_ERROR,
3463 "Failed to initialize control interface '%s'.\n"
3464 "You may have another wpa_supplicant process "
3465 "already running or the file was\n"
3466 "left by an unclean termination of wpa_supplicant "
3467 "in which case you will need\n"
3468 "to manually remove this file before starting "
3469 "wpa_supplicant again.\n",
3470 wpa_s->conf->ctrl_interface);
3471 return -1;
3472 }
3473
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003474 wpa_s->gas = gas_query_init(wpa_s);
3475 if (wpa_s->gas == NULL) {
3476 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3477 return -1;
3478 }
3479
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003481 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3483 return -1;
3484 }
3485#endif /* CONFIG_P2P */
3486
3487 if (wpa_bss_init(wpa_s) < 0)
3488 return -1;
3489
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003490#ifdef CONFIG_EAP_PROXY
3491{
3492 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003493 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3494 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003495 if (wpa_s->mnc_len > 0) {
3496 wpa_s->imsi[len] = '\0';
3497 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3498 wpa_s->imsi, wpa_s->mnc_len);
3499 } else {
3500 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3501 }
3502}
3503#endif /* CONFIG_EAP_PROXY */
3504
Dmitry Shmidt04949592012-07-19 12:16:46 -07003505 if (pcsc_reader_init(wpa_s) < 0)
3506 return -1;
3507
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003508 if (wpas_init_ext_pw(wpa_s) < 0)
3509 return -1;
3510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511 return 0;
3512}
3513
3514
3515static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003516 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003518 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003519 if (wpa_s->drv_priv) {
3520 wpa_supplicant_deauthenticate(wpa_s,
3521 WLAN_REASON_DEAUTH_LEAVING);
3522
3523 wpa_drv_set_countermeasures(wpa_s, 0);
3524 wpa_clear_keys(wpa_s, NULL);
3525 }
3526
3527 wpa_supplicant_cleanup(wpa_s);
3528
Dmitry Shmidt04949592012-07-19 12:16:46 -07003529#ifdef CONFIG_P2P
3530 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3531 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3532 "the management interface is being removed");
3533 wpas_p2p_deinit_global(wpa_s->global);
3534 }
3535#endif /* CONFIG_P2P */
3536
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003537 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003538 radio_remove_interface(wpa_s);
3539
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003540 if (wpa_s->drv_priv)
3541 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003542
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003543 if (notify)
3544 wpas_notify_iface_removed(wpa_s);
3545
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003546 if (terminate)
3547 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003548
3549 if (wpa_s->ctrl_iface) {
3550 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3551 wpa_s->ctrl_iface = NULL;
3552 }
3553
3554 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003555 wpa_config_free(wpa_s->conf);
3556 wpa_s->conf = NULL;
3557 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003558
3559 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003560}
3561
3562
3563/**
3564 * wpa_supplicant_add_iface - Add a new network interface
3565 * @global: Pointer to global data from wpa_supplicant_init()
3566 * @iface: Interface configuration options
3567 * Returns: Pointer to the created interface or %NULL on failure
3568 *
3569 * This function is used to add new network interfaces for %wpa_supplicant.
3570 * This can be called before wpa_supplicant_run() to add interfaces before the
3571 * main event loop has been started. In addition, new interfaces can be added
3572 * dynamically while %wpa_supplicant is already running. This could happen,
3573 * e.g., when a hotplug network adapter is inserted.
3574 */
3575struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3576 struct wpa_interface *iface)
3577{
3578 struct wpa_supplicant *wpa_s;
3579 struct wpa_interface t_iface;
3580 struct wpa_ssid *ssid;
3581
3582 if (global == NULL || iface == NULL)
3583 return NULL;
3584
3585 wpa_s = wpa_supplicant_alloc();
3586 if (wpa_s == NULL)
3587 return NULL;
3588
3589 wpa_s->global = global;
3590
3591 t_iface = *iface;
3592 if (global->params.override_driver) {
3593 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3594 "('%s' -> '%s')",
3595 iface->driver, global->params.override_driver);
3596 t_iface.driver = global->params.override_driver;
3597 }
3598 if (global->params.override_ctrl_interface) {
3599 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3600 "ctrl_interface ('%s' -> '%s')",
3601 iface->ctrl_interface,
3602 global->params.override_ctrl_interface);
3603 t_iface.ctrl_interface =
3604 global->params.override_ctrl_interface;
3605 }
3606 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3607 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3608 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003609 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610 return NULL;
3611 }
3612
3613 /* Notify the control interfaces about new iface */
3614 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003615 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003616 return NULL;
3617 }
3618
3619 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3620 wpas_notify_network_added(wpa_s, ssid);
3621
3622 wpa_s->next = global->ifaces;
3623 global->ifaces = wpa_s;
3624
3625 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003626 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627
3628 return wpa_s;
3629}
3630
3631
3632/**
3633 * wpa_supplicant_remove_iface - Remove a network interface
3634 * @global: Pointer to global data from wpa_supplicant_init()
3635 * @wpa_s: Pointer to the network interface to be removed
3636 * Returns: 0 if interface was removed, -1 if interface was not found
3637 *
3638 * This function can be used to dynamically remove network interfaces from
3639 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3640 * addition, this function is used to remove all remaining interfaces when
3641 * %wpa_supplicant is terminated.
3642 */
3643int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003644 struct wpa_supplicant *wpa_s,
3645 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646{
3647 struct wpa_supplicant *prev;
3648
3649 /* Remove interface from the global list of interfaces */
3650 prev = global->ifaces;
3651 if (prev == wpa_s) {
3652 global->ifaces = wpa_s->next;
3653 } else {
3654 while (prev && prev->next != wpa_s)
3655 prev = prev->next;
3656 if (prev == NULL)
3657 return -1;
3658 prev->next = wpa_s->next;
3659 }
3660
3661 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3662
3663 if (global->p2p_group_formation == wpa_s)
3664 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003665 if (global->p2p_invite_group == wpa_s)
3666 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003667 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003668
3669 return 0;
3670}
3671
3672
3673/**
3674 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3675 * @wpa_s: Pointer to the network interface
3676 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3677 */
3678const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3679{
3680 const char *eapol_method;
3681
3682 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3683 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3684 return "NO-EAP";
3685 }
3686
3687 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3688 if (eapol_method == NULL)
3689 return "UNKNOWN-EAP";
3690
3691 return eapol_method;
3692}
3693
3694
3695/**
3696 * wpa_supplicant_get_iface - Get a new network interface
3697 * @global: Pointer to global data from wpa_supplicant_init()
3698 * @ifname: Interface name
3699 * Returns: Pointer to the interface or %NULL if not found
3700 */
3701struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3702 const char *ifname)
3703{
3704 struct wpa_supplicant *wpa_s;
3705
3706 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3707 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3708 return wpa_s;
3709 }
3710 return NULL;
3711}
3712
3713
3714#ifndef CONFIG_NO_WPA_MSG
3715static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3716{
3717 struct wpa_supplicant *wpa_s = ctx;
3718 if (wpa_s == NULL)
3719 return NULL;
3720 return wpa_s->ifname;
3721}
3722#endif /* CONFIG_NO_WPA_MSG */
3723
3724
3725/**
3726 * wpa_supplicant_init - Initialize %wpa_supplicant
3727 * @params: Parameters for %wpa_supplicant
3728 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3729 *
3730 * This function is used to initialize %wpa_supplicant. After successful
3731 * initialization, the returned data pointer can be used to add and remove
3732 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3733 */
3734struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3735{
3736 struct wpa_global *global;
3737 int ret, i;
3738
3739 if (params == NULL)
3740 return NULL;
3741
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003742#ifdef CONFIG_DRIVER_NDIS
3743 {
3744 void driver_ndis_init_ops(void);
3745 driver_ndis_init_ops();
3746 }
3747#endif /* CONFIG_DRIVER_NDIS */
3748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003749#ifndef CONFIG_NO_WPA_MSG
3750 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3751#endif /* CONFIG_NO_WPA_MSG */
3752
3753 wpa_debug_open_file(params->wpa_debug_file_path);
3754 if (params->wpa_debug_syslog)
3755 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003756 if (params->wpa_debug_tracing) {
3757 ret = wpa_debug_open_linux_tracing();
3758 if (ret) {
3759 wpa_printf(MSG_ERROR,
3760 "Failed to enable trace logging");
3761 return NULL;
3762 }
3763 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003764
3765 ret = eap_register_methods();
3766 if (ret) {
3767 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3768 if (ret == -2)
3769 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3770 "the same EAP type.");
3771 return NULL;
3772 }
3773
3774 global = os_zalloc(sizeof(*global));
3775 if (global == NULL)
3776 return NULL;
3777 dl_list_init(&global->p2p_srv_bonjour);
3778 dl_list_init(&global->p2p_srv_upnp);
3779 global->params.daemonize = params->daemonize;
3780 global->params.wait_for_monitor = params->wait_for_monitor;
3781 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3782 if (params->pid_file)
3783 global->params.pid_file = os_strdup(params->pid_file);
3784 if (params->ctrl_interface)
3785 global->params.ctrl_interface =
3786 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003787 if (params->ctrl_interface_group)
3788 global->params.ctrl_interface_group =
3789 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790 if (params->override_driver)
3791 global->params.override_driver =
3792 os_strdup(params->override_driver);
3793 if (params->override_ctrl_interface)
3794 global->params.override_ctrl_interface =
3795 os_strdup(params->override_ctrl_interface);
3796 wpa_debug_level = global->params.wpa_debug_level =
3797 params->wpa_debug_level;
3798 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3799 params->wpa_debug_show_keys;
3800 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3801 params->wpa_debug_timestamp;
3802
3803 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3804
3805 if (eloop_init()) {
3806 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3807 wpa_supplicant_deinit(global);
3808 return NULL;
3809 }
3810
Jouni Malinen75ecf522011-06-27 15:19:46 -07003811 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003812
3813 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3814 if (global->ctrl_iface == NULL) {
3815 wpa_supplicant_deinit(global);
3816 return NULL;
3817 }
3818
3819 if (wpas_notify_supplicant_initialized(global)) {
3820 wpa_supplicant_deinit(global);
3821 return NULL;
3822 }
3823
3824 for (i = 0; wpa_drivers[i]; i++)
3825 global->drv_count++;
3826 if (global->drv_count == 0) {
3827 wpa_printf(MSG_ERROR, "No drivers enabled");
3828 wpa_supplicant_deinit(global);
3829 return NULL;
3830 }
3831 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3832 if (global->drv_priv == NULL) {
3833 wpa_supplicant_deinit(global);
3834 return NULL;
3835 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003837#ifdef CONFIG_WIFI_DISPLAY
3838 if (wifi_display_init(global) < 0) {
3839 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3840 wpa_supplicant_deinit(global);
3841 return NULL;
3842 }
3843#endif /* CONFIG_WIFI_DISPLAY */
3844
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003845 return global;
3846}
3847
3848
3849/**
3850 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3851 * @global: Pointer to global data from wpa_supplicant_init()
3852 * Returns: 0 after successful event loop run, -1 on failure
3853 *
3854 * This function starts the main event loop and continues running as long as
3855 * there are any remaining events. In most cases, this function is running as
3856 * long as the %wpa_supplicant process in still in use.
3857 */
3858int wpa_supplicant_run(struct wpa_global *global)
3859{
3860 struct wpa_supplicant *wpa_s;
3861
3862 if (global->params.daemonize &&
3863 wpa_supplicant_daemon(global->params.pid_file))
3864 return -1;
3865
3866 if (global->params.wait_for_monitor) {
3867 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3868 if (wpa_s->ctrl_iface)
3869 wpa_supplicant_ctrl_iface_wait(
3870 wpa_s->ctrl_iface);
3871 }
3872
3873 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3874 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3875
3876 eloop_run();
3877
3878 return 0;
3879}
3880
3881
3882/**
3883 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3884 * @global: Pointer to global data from wpa_supplicant_init()
3885 *
3886 * This function is called to deinitialize %wpa_supplicant and to free all
3887 * allocated resources. Remaining network interfaces will also be removed.
3888 */
3889void wpa_supplicant_deinit(struct wpa_global *global)
3890{
3891 int i;
3892
3893 if (global == NULL)
3894 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003895
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003896#ifdef CONFIG_WIFI_DISPLAY
3897 wifi_display_deinit(global);
3898#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003899
3900 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003901 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003902
3903 if (global->ctrl_iface)
3904 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3905
3906 wpas_notify_supplicant_deinitialized(global);
3907
3908 eap_peer_unregister_methods();
3909#ifdef CONFIG_AP
3910 eap_server_unregister_methods();
3911#endif /* CONFIG_AP */
3912
3913 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3914 if (!global->drv_priv[i])
3915 continue;
3916 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3917 }
3918 os_free(global->drv_priv);
3919
3920 random_deinit();
3921
3922 eloop_destroy();
3923
3924 if (global->params.pid_file) {
3925 os_daemonize_terminate(global->params.pid_file);
3926 os_free(global->params.pid_file);
3927 }
3928 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003929 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003930 os_free(global->params.override_driver);
3931 os_free(global->params.override_ctrl_interface);
3932
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003933 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08003934 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003935 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003937 os_free(global);
3938 wpa_debug_close_syslog();
3939 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003940 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941}
3942
3943
3944void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3945{
3946 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3947 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3948 char country[3];
3949 country[0] = wpa_s->conf->country[0];
3950 country[1] = wpa_s->conf->country[1];
3951 country[2] = '\0';
3952 if (wpa_drv_set_country(wpa_s, country) < 0) {
3953 wpa_printf(MSG_ERROR, "Failed to set country code "
3954 "'%s'", country);
3955 }
3956 }
3957
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003958 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3959 wpas_init_ext_pw(wpa_s);
3960
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003961#ifdef CONFIG_WPS
3962 wpas_wps_update_config(wpa_s);
3963#endif /* CONFIG_WPS */
3964
3965#ifdef CONFIG_P2P
3966 wpas_p2p_update_config(wpa_s);
3967#endif /* CONFIG_P2P */
3968
3969 wpa_s->conf->changed_parameters = 0;
3970}
3971
3972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003973static void add_freq(int *freqs, int *num_freqs, int freq)
3974{
3975 int i;
3976
3977 for (i = 0; i < *num_freqs; i++) {
3978 if (freqs[i] == freq)
3979 return;
3980 }
3981
3982 freqs[*num_freqs] = freq;
3983 (*num_freqs)++;
3984}
3985
3986
3987static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3988{
3989 struct wpa_bss *bss, *cbss;
3990 const int max_freqs = 10;
3991 int *freqs;
3992 int num_freqs = 0;
3993
3994 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3995 if (freqs == NULL)
3996 return NULL;
3997
3998 cbss = wpa_s->current_bss;
3999
4000 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4001 if (bss == cbss)
4002 continue;
4003 if (bss->ssid_len == cbss->ssid_len &&
4004 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4005 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4006 add_freq(freqs, &num_freqs, bss->freq);
4007 if (num_freqs == max_freqs)
4008 break;
4009 }
4010 }
4011
4012 if (num_freqs == 0) {
4013 os_free(freqs);
4014 freqs = NULL;
4015 }
4016
4017 return freqs;
4018}
4019
4020
4021void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4022{
4023 int timeout;
4024 int count;
4025 int *freqs = NULL;
4026
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004027 wpas_connect_work_done(wpa_s);
4028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004029 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004030 * Remove possible authentication timeout since the connection failed.
4031 */
4032 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4033
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004034 if (wpa_s->disconnected) {
4035 /*
4036 * There is no point in blacklisting the AP if this event is
4037 * generated based on local request to disconnect.
4038 */
4039 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4040 "indication since interface has been put into "
4041 "disconnected state");
4042 return;
4043 }
4044
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004045 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004046 * Add the failed BSSID into the blacklist and speed up next scan
4047 * attempt if there could be other APs that could accept association.
4048 * The current blacklist count indicates how many times we have tried
4049 * connecting to this AP and multiple attempts mean that other APs are
4050 * either not available or has already been tried, so that we can start
4051 * increasing the delay here to avoid constant scanning.
4052 */
4053 count = wpa_blacklist_add(wpa_s, bssid);
4054 if (count == 1 && wpa_s->current_bss) {
4055 /*
4056 * This BSS was not in the blacklist before. If there is
4057 * another BSS available for the same ESS, we should try that
4058 * next. Otherwise, we may as well try this one once more
4059 * before allowing other, likely worse, ESSes to be considered.
4060 */
4061 freqs = get_bss_freqs_in_ess(wpa_s);
4062 if (freqs) {
4063 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4064 "has been seen; try it next");
4065 wpa_blacklist_add(wpa_s, bssid);
4066 /*
4067 * On the next scan, go through only the known channels
4068 * used in this ESS based on previous scans to speed up
4069 * common load balancing use case.
4070 */
4071 os_free(wpa_s->next_scan_freqs);
4072 wpa_s->next_scan_freqs = freqs;
4073 }
4074 }
4075
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004076 /*
4077 * Add previous failure count in case the temporary blacklist was
4078 * cleared due to no other BSSes being available.
4079 */
4080 count += wpa_s->extra_blacklist_count;
4081
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004082 if (count > 3 && wpa_s->current_ssid) {
4083 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4084 "consider temporary network disabling");
4085 wpas_auth_failed(wpa_s);
4086 }
4087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004088 switch (count) {
4089 case 1:
4090 timeout = 100;
4091 break;
4092 case 2:
4093 timeout = 500;
4094 break;
4095 case 3:
4096 timeout = 1000;
4097 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004098 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004099 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004100 break;
4101 default:
4102 timeout = 10000;
4103 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004104 }
4105
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004106 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4107 "ms", count, timeout);
4108
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004109 /*
4110 * TODO: if more than one possible AP is available in scan results,
4111 * could try the other ones before requesting a new scan.
4112 */
4113 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4114 1000 * (timeout % 1000));
4115}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004116
4117
4118int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4119{
4120 return wpa_s->conf->ap_scan == 2 ||
4121 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4122}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004123
Dmitry Shmidt04949592012-07-19 12:16:46 -07004124
4125#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4126int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4127 struct wpa_ssid *ssid,
4128 const char *field,
4129 const char *value)
4130{
4131#ifdef IEEE8021X_EAPOL
4132 struct eap_peer_config *eap = &ssid->eap;
4133
4134 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4135 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4136 (const u8 *) value, os_strlen(value));
4137
4138 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4139 case WPA_CTRL_REQ_EAP_IDENTITY:
4140 os_free(eap->identity);
4141 eap->identity = (u8 *) os_strdup(value);
4142 eap->identity_len = os_strlen(value);
4143 eap->pending_req_identity = 0;
4144 if (ssid == wpa_s->current_ssid)
4145 wpa_s->reassociate = 1;
4146 break;
4147 case WPA_CTRL_REQ_EAP_PASSWORD:
4148 os_free(eap->password);
4149 eap->password = (u8 *) os_strdup(value);
4150 eap->password_len = os_strlen(value);
4151 eap->pending_req_password = 0;
4152 if (ssid == wpa_s->current_ssid)
4153 wpa_s->reassociate = 1;
4154 break;
4155 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4156 os_free(eap->new_password);
4157 eap->new_password = (u8 *) os_strdup(value);
4158 eap->new_password_len = os_strlen(value);
4159 eap->pending_req_new_password = 0;
4160 if (ssid == wpa_s->current_ssid)
4161 wpa_s->reassociate = 1;
4162 break;
4163 case WPA_CTRL_REQ_EAP_PIN:
4164 os_free(eap->pin);
4165 eap->pin = os_strdup(value);
4166 eap->pending_req_pin = 0;
4167 if (ssid == wpa_s->current_ssid)
4168 wpa_s->reassociate = 1;
4169 break;
4170 case WPA_CTRL_REQ_EAP_OTP:
4171 os_free(eap->otp);
4172 eap->otp = (u8 *) os_strdup(value);
4173 eap->otp_len = os_strlen(value);
4174 os_free(eap->pending_req_otp);
4175 eap->pending_req_otp = NULL;
4176 eap->pending_req_otp_len = 0;
4177 break;
4178 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4179 os_free(eap->private_key_passwd);
4180 eap->private_key_passwd = (u8 *) os_strdup(value);
4181 eap->pending_req_passphrase = 0;
4182 if (ssid == wpa_s->current_ssid)
4183 wpa_s->reassociate = 1;
4184 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004185 case WPA_CTRL_REQ_SIM:
4186 os_free(eap->external_sim_resp);
4187 eap->external_sim_resp = os_strdup(value);
4188 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004189 default:
4190 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4191 return -1;
4192 }
4193
4194 return 0;
4195#else /* IEEE8021X_EAPOL */
4196 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4197 return -1;
4198#endif /* IEEE8021X_EAPOL */
4199}
4200#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4201
4202
4203int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4204{
4205 int i;
4206 unsigned int drv_enc;
4207
4208 if (ssid == NULL)
4209 return 1;
4210
4211 if (ssid->disabled)
4212 return 1;
4213
4214 if (wpa_s && wpa_s->drv_capa_known)
4215 drv_enc = wpa_s->drv_enc;
4216 else
4217 drv_enc = (unsigned int) -1;
4218
4219 for (i = 0; i < NUM_WEP_KEYS; i++) {
4220 size_t len = ssid->wep_key_len[i];
4221 if (len == 0)
4222 continue;
4223 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4224 continue;
4225 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4226 continue;
4227 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4228 continue;
4229 return 1; /* invalid WEP key */
4230 }
4231
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004232 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4233 !ssid->ext_psk)
4234 return 1;
4235
Dmitry Shmidt04949592012-07-19 12:16:46 -07004236 return 0;
4237}
4238
4239
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004240int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004241{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004242 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004243 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004244 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004245 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004246 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004247}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004248
4249
4250void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4251{
4252 struct wpa_ssid *ssid = wpa_s->current_ssid;
4253 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004254 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004255
4256 if (ssid == NULL) {
4257 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4258 "SSID block");
4259 return;
4260 }
4261
4262 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4263 return;
4264
4265 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004266
4267#ifdef CONFIG_P2P
4268 if (ssid->p2p_group &&
4269 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4270 /*
4271 * Skip the wait time since there is a short timeout on the
4272 * connection to a P2P group.
4273 */
4274 return;
4275 }
4276#endif /* CONFIG_P2P */
4277
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004278 if (ssid->auth_failures > 50)
4279 dur = 300;
4280 else if (ssid->auth_failures > 20)
4281 dur = 120;
4282 else if (ssid->auth_failures > 10)
4283 dur = 60;
4284 else if (ssid->auth_failures > 5)
4285 dur = 30;
4286 else if (ssid->auth_failures > 1)
4287 dur = 20;
4288 else
4289 dur = 10;
4290
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004291 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004292 if (now.sec + dur <= ssid->disabled_until.sec)
4293 return;
4294
4295 ssid->disabled_until.sec = now.sec + dur;
4296
4297 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4298 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4299 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4300 ssid->auth_failures, dur);
4301}
4302
4303
4304void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4305 struct wpa_ssid *ssid, int clear_failures)
4306{
4307 if (ssid == NULL)
4308 return;
4309
4310 if (ssid->disabled_until.sec) {
4311 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4312 "id=%d ssid=\"%s\"",
4313 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4314 }
4315 ssid->disabled_until.sec = 0;
4316 ssid->disabled_until.usec = 0;
4317 if (clear_failures)
4318 ssid->auth_failures = 0;
4319}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004320
4321
4322int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4323{
4324 size_t i;
4325
4326 if (wpa_s->disallow_aps_bssid == NULL)
4327 return 0;
4328
4329 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4330 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4331 bssid, ETH_ALEN) == 0)
4332 return 1;
4333 }
4334
4335 return 0;
4336}
4337
4338
4339int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4340 size_t ssid_len)
4341{
4342 size_t i;
4343
4344 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4345 return 0;
4346
4347 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4348 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4349 if (ssid_len == s->ssid_len &&
4350 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4351 return 1;
4352 }
4353
4354 return 0;
4355}
4356
4357
4358/**
4359 * wpas_request_connection - Request a new connection
4360 * @wpa_s: Pointer to the network interface
4361 *
4362 * This function is used to request a new connection to be found. It will mark
4363 * the interface to allow reassociation and request a new scan to find a
4364 * suitable network to connect to.
4365 */
4366void wpas_request_connection(struct wpa_supplicant *wpa_s)
4367{
4368 wpa_s->normal_scans = 0;
4369 wpa_supplicant_reinit_autoscan(wpa_s);
4370 wpa_s->extra_blacklist_count = 0;
4371 wpa_s->disconnected = 0;
4372 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004373
4374 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4375 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004376}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004377
4378
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004379void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4380 int *freq_array, unsigned int len)
4381{
4382 unsigned int i;
4383
4384 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4385 len, title);
4386 for (i = 0; i < len; i++)
4387 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4388}
4389
4390
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004391/*
4392 * Find the operating frequencies of any of the virtual interfaces that
4393 * are using the same radio as the current interface.
4394 */
4395int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4396 int *freq_array, unsigned int len)
4397{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004398 struct wpa_supplicant *ifs;
4399 u8 bssid[ETH_ALEN];
4400 int freq;
4401 unsigned int idx = 0, i;
4402
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004403 wpa_dbg(wpa_s, MSG_DEBUG,
4404 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004405 os_memset(freq_array, 0, sizeof(int) * len);
4406
4407 /* First add the frequency of the local interface */
4408 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4409 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4410 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4411 freq_array[idx++] = wpa_s->current_ssid->frequency;
4412 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4413 freq_array[idx++] = wpa_s->assoc_freq;
4414 }
4415
4416 /* If get_radio_name is not supported, use only the local freq */
4417 if (!wpa_s->driver->get_radio_name) {
4418 freq = wpa_drv_shared_freq(wpa_s);
4419 if (freq > 0 && idx < len &&
4420 (idx == 0 || freq_array[0] != freq))
4421 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004422 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004423 return idx;
4424 }
4425
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004426 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4427 radio_list) {
4428 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004429 continue;
4430
4431 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4432 continue;
4433
4434 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4435 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4436 freq = ifs->current_ssid->frequency;
4437 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4438 freq = ifs->assoc_freq;
4439 else
4440 continue;
4441
4442 /* Hold only distinct freqs */
4443 for (i = 0; i < idx; i++)
4444 if (freq_array[i] == freq)
4445 break;
4446
4447 if (i == idx)
4448 freq_array[idx++] = freq;
4449 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004450
4451 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004452 return idx;
4453}