blob: aa9c32d6d9d55eaf38728156db22cc1a78ee38ba [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 }
1568#endif /* CONFIG_P2P */
1569
Dmitry Shmidt04949592012-07-19 12:16:46 -07001570#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001571 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001572 struct wpabuf *hs20;
1573 hs20 = wpabuf_alloc(20);
1574 if (hs20) {
1575 wpas_hs20_add_indication(hs20);
1576 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1577 wpabuf_len(hs20));
1578 wpa_ie_len += wpabuf_len(hs20);
1579 wpabuf_free(hs20);
1580 }
1581 }
1582#endif /* CONFIG_HS20 */
1583
Dmitry Shmidt56052862013-10-04 10:23:25 -07001584 /*
1585 * Workaround: Add Extended Capabilities element only if the AP
1586 * included this element in Beacon/Probe Response frames. Some older
1587 * APs seem to have interoperability issues if this element is
1588 * included, so while the standard may require us to include the
1589 * element in all cases, it is justifiable to skip it to avoid
1590 * interoperability issues.
1591 */
1592 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1593 u8 ext_capab[10];
1594 int ext_capab_len;
1595 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1596 if (ext_capab_len > 0) {
1597 u8 *pos = wpa_ie;
1598 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1599 pos += 2 + pos[1];
1600 os_memmove(pos + ext_capab_len, pos,
1601 wpa_ie_len - (pos - wpa_ie));
1602 wpa_ie_len += ext_capab_len;
1603 os_memcpy(pos, ext_capab, ext_capab_len);
1604 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001605 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001607 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1608 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001609 cipher_pairwise = wpa_s->pairwise_cipher;
1610 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1612 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1613 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1614 use_crypt = 0;
1615 if (wpa_set_wep_keys(wpa_s, ssid)) {
1616 use_crypt = 1;
1617 wep_keys_set = 1;
1618 }
1619 }
1620 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1621 use_crypt = 0;
1622
1623#ifdef IEEE8021X_EAPOL
1624 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1625 if ((ssid->eapol_flags &
1626 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1627 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1628 !wep_keys_set) {
1629 use_crypt = 0;
1630 } else {
1631 /* Assume that dynamic WEP-104 keys will be used and
1632 * set cipher suites in order for drivers to expect
1633 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001634 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001635 }
1636 }
1637#endif /* IEEE8021X_EAPOL */
1638
1639 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1640 /* Set the key before (and later after) association */
1641 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1642 }
1643
1644 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1645 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001646 params.ssid = bss->ssid;
1647 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001648 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1649 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1650 MACSTR " freq=%u MHz based on scan results "
1651 "(bssid_set=%d)",
1652 MAC2STR(bss->bssid), bss->freq,
1653 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001654 params.bssid = bss->bssid;
1655 params.freq = bss->freq;
1656 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001657 } else {
1658 params.ssid = ssid->ssid;
1659 params.ssid_len = ssid->ssid_len;
1660 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001661
1662 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1663 wpa_s->conf->ap_scan == 2) {
1664 params.bssid = ssid->bssid;
1665 params.fixed_bssid = 1;
1666 }
1667
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001668 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1669 params.freq == 0)
1670 params.freq = ssid->frequency; /* Initial channel for IBSS */
1671 params.wpa_ie = wpa_ie;
1672 params.wpa_ie_len = wpa_ie_len;
1673 params.pairwise_suite = cipher_pairwise;
1674 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001675 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001676 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001677 params.auth_alg = algs;
1678 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001679 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680 for (i = 0; i < NUM_WEP_KEYS; i++) {
1681 if (ssid->wep_key_len[i])
1682 params.wep_key[i] = ssid->wep_key[i];
1683 params.wep_key_len[i] = ssid->wep_key_len[i];
1684 }
1685 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1686
1687 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001688 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1689 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 params.passphrase = ssid->passphrase;
1691 if (ssid->psk_set)
1692 params.psk = ssid->psk;
1693 }
1694
1695 params.drop_unencrypted = use_crypt;
1696
1697#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001698 params.mgmt_frame_protection =
1699 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1700 wpa_s->conf->pmf : ssid->ieee80211w;
1701 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1703 struct wpa_ie_data ie;
1704 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1705 ie.capabilities &
1706 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1707 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1708 "MFP: require MFP");
1709 params.mgmt_frame_protection =
1710 MGMT_FRAME_PROTECTION_REQUIRED;
1711 }
1712 }
1713#endif /* CONFIG_IEEE80211W */
1714
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001715 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716
1717 if (wpa_s->parent->set_sta_uapsd)
1718 params.uapsd = wpa_s->parent->sta_uapsd;
1719 else
1720 params.uapsd = -1;
1721
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001722#ifdef CONFIG_HT_OVERRIDES
1723 os_memset(&htcaps, 0, sizeof(htcaps));
1724 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1725 params.htcaps = (u8 *) &htcaps;
1726 params.htcaps_mask = (u8 *) &htcaps_mask;
1727 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1728#endif /* CONFIG_HT_OVERRIDES */
1729
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001730#ifdef CONFIG_P2P
1731 /*
1732 * If multi-channel concurrency is not supported, check for any
1733 * frequency conflict. In case of any frequency conflict, remove the
1734 * least prioritized connection.
1735 */
1736 if (wpa_s->num_multichan_concurrent < 2) {
1737 int freq = wpa_drv_shared_freq(wpa_s);
1738 if (freq > 0 && freq != params.freq) {
1739 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1740 freq, params.freq);
1741 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1742 params.freq,
1743 ssid) < 0)
1744 return;
1745 }
1746 }
1747#endif /* CONFIG_P2P */
1748
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001749 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750 if (ret < 0) {
1751 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1752 "failed");
1753 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1754 /*
1755 * The driver is known to mean what is saying, so we
1756 * can stop right here; the association will not
1757 * succeed.
1758 */
1759 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001760 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1762 return;
1763 }
1764 /* try to continue anyway; new association will be tried again
1765 * after timeout */
1766 assoc_failed = 1;
1767 }
1768
1769 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1770 /* Set the key after the association just in case association
1771 * cleared the previously configured key. */
1772 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1773 /* No need to timeout authentication since there is no key
1774 * management. */
1775 wpa_supplicant_cancel_auth_timeout(wpa_s);
1776 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1777#ifdef CONFIG_IBSS_RSN
1778 } else if (ssid->mode == WPAS_MODE_IBSS &&
1779 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1780 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1781 /*
1782 * RSN IBSS authentication is per-STA and we can disable the
1783 * per-BSSID authentication.
1784 */
1785 wpa_supplicant_cancel_auth_timeout(wpa_s);
1786#endif /* CONFIG_IBSS_RSN */
1787 } else {
1788 /* Timeout for IEEE 802.11 authentication and association */
1789 int timeout = 60;
1790
1791 if (assoc_failed) {
1792 /* give IBSS a bit more time */
1793 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1794 } else if (wpa_s->conf->ap_scan == 1) {
1795 /* give IBSS a bit more time */
1796 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1797 }
1798 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1799 }
1800
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001801 if (wep_keys_set &&
1802 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001803 /* Set static WEP keys again */
1804 wpa_set_wep_keys(wpa_s, ssid);
1805 }
1806
1807 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1808 /*
1809 * Do not allow EAP session resumption between different
1810 * network configurations.
1811 */
1812 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1813 }
1814 old_ssid = wpa_s->current_ssid;
1815 wpa_s->current_ssid = ssid;
1816 wpa_s->current_bss = bss;
1817 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1818 wpa_supplicant_initiate_eapol(wpa_s);
1819 if (old_ssid != wpa_s->current_ssid)
1820 wpas_notify_network_changed(wpa_s);
1821}
1822
1823
1824static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1825 const u8 *addr)
1826{
1827 struct wpa_ssid *old_ssid;
1828
1829 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001831 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832 wpa_sm_set_config(wpa_s->wpa, NULL);
1833 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1834 if (old_ssid != wpa_s->current_ssid)
1835 wpas_notify_network_changed(wpa_s);
1836 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1837}
1838
1839
1840/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1842 * @wpa_s: Pointer to wpa_supplicant data
1843 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1844 *
1845 * This function is used to request %wpa_supplicant to deauthenticate from the
1846 * current AP.
1847 */
1848void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1849 int reason_code)
1850{
1851 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001852 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001853 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001855 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1856 " pending_bssid=" MACSTR " reason=%d state=%s",
1857 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1858 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1859
1860 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001862 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1863 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1864 wpa_s->wpa_state == WPA_ASSOCIATING))
1865 addr = wpa_s->pending_bssid;
1866 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1867 /*
1868 * When using driver-based BSS selection, we may not know the
1869 * BSSID with which we are currently trying to associate. We
1870 * need to notify the driver of this disconnection even in such
1871 * a case, so use the all zeros address here.
1872 */
1873 addr = wpa_s->bssid;
1874 zero_addr = 1;
1875 }
1876
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001877#ifdef CONFIG_TDLS
1878 wpa_tdls_teardown_peers(wpa_s->wpa);
1879#endif /* CONFIG_TDLS */
1880
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001881 if (addr) {
1882 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001883 os_memset(&event, 0, sizeof(event));
1884 event.deauth_info.reason_code = (u16) reason_code;
1885 event.deauth_info.locally_generated = 1;
1886 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001887 if (zero_addr)
1888 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 }
1890
1891 wpa_supplicant_clear_connection(wpa_s, addr);
1892}
1893
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001894static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1895 struct wpa_ssid *ssid)
1896{
1897 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1898 return;
1899
1900 ssid->disabled = 0;
1901 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1902 wpas_notify_network_enabled_changed(wpa_s, ssid);
1903
1904 /*
1905 * Try to reassociate since there is no current configuration and a new
1906 * network was made available.
1907 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001908 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001909 wpa_s->reassociate = 1;
1910}
1911
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912
1913/**
1914 * wpa_supplicant_enable_network - Mark a configured network as enabled
1915 * @wpa_s: wpa_supplicant structure for a network interface
1916 * @ssid: wpa_ssid structure for a configured network or %NULL
1917 *
1918 * Enables the specified network or all networks if no network specified.
1919 */
1920void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1921 struct wpa_ssid *ssid)
1922{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001923 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001924 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1925 wpa_supplicant_enable_one_network(wpa_s, ssid);
1926 } else
1927 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001928
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001929 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001930 if (wpa_s->sched_scanning) {
1931 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1932 "new network to scan filters");
1933 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 }
1935
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001936 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1937 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001938 }
1939}
1940
1941
1942/**
1943 * wpa_supplicant_disable_network - Mark a configured network as disabled
1944 * @wpa_s: wpa_supplicant structure for a network interface
1945 * @ssid: wpa_ssid structure for a configured network or %NULL
1946 *
1947 * Disables the specified network or all networks if no network specified.
1948 */
1949void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1950 struct wpa_ssid *ssid)
1951{
1952 struct wpa_ssid *other_ssid;
1953 int was_disabled;
1954
1955 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001956 if (wpa_s->sched_scanning)
1957 wpa_supplicant_cancel_sched_scan(wpa_s);
1958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001959 for (other_ssid = wpa_s->conf->ssid; other_ssid;
1960 other_ssid = other_ssid->next) {
1961 was_disabled = other_ssid->disabled;
1962 if (was_disabled == 2)
1963 continue; /* do not change persistent P2P group
1964 * data */
1965
1966 other_ssid->disabled = 1;
1967
1968 if (was_disabled != other_ssid->disabled)
1969 wpas_notify_network_enabled_changed(
1970 wpa_s, other_ssid);
1971 }
1972 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001973 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
1975 } else if (ssid->disabled != 2) {
1976 if (ssid == 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
1980 was_disabled = ssid->disabled;
1981
1982 ssid->disabled = 1;
1983
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001984 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001986 if (wpa_s->sched_scanning) {
1987 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
1988 "to remove network from filters");
1989 wpa_supplicant_cancel_sched_scan(wpa_s);
1990 wpa_supplicant_req_scan(wpa_s, 0, 0);
1991 }
1992 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993 }
1994}
1995
1996
1997/**
1998 * wpa_supplicant_select_network - Attempt association with a network
1999 * @wpa_s: wpa_supplicant structure for a network interface
2000 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2001 */
2002void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2003 struct wpa_ssid *ssid)
2004{
2005
2006 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002007 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002009 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002010 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002012 disconnected = 1;
2013 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002015 if (ssid)
2016 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2017
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002018 /*
2019 * Mark all other networks disabled or mark all networks enabled if no
2020 * network specified.
2021 */
2022 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2023 other_ssid = other_ssid->next) {
2024 int was_disabled = other_ssid->disabled;
2025 if (was_disabled == 2)
2026 continue; /* do not change persistent P2P group data */
2027
2028 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002029 if (was_disabled && !other_ssid->disabled)
2030 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031
2032 if (was_disabled != other_ssid->disabled)
2033 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2034 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002035
2036 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2037 /* We are already associated with the selected network */
2038 wpa_printf(MSG_DEBUG, "Already associated with the "
2039 "selected network - do nothing");
2040 return;
2041 }
2042
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002043 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002044 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002045 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2046 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002047 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048 wpa_s->disconnected = 0;
2049 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002050
2051 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2052 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053
2054 if (ssid)
2055 wpas_notify_network_selected(wpa_s, ssid);
2056}
2057
2058
2059/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002060 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2061 * @wpa_s: wpa_supplicant structure for a network interface
2062 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2063 * @pkcs11_module_path: PKCS #11 module path or NULL
2064 * Returns: 0 on success; -1 on failure
2065 *
2066 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2067 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2068 * module path fails the paths will be reset to the default value (NULL).
2069 */
2070int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2071 const char *pkcs11_engine_path,
2072 const char *pkcs11_module_path)
2073{
2074 char *pkcs11_engine_path_copy = NULL;
2075 char *pkcs11_module_path_copy = NULL;
2076
2077 if (pkcs11_engine_path != NULL) {
2078 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2079 if (pkcs11_engine_path_copy == NULL)
2080 return -1;
2081 }
2082 if (pkcs11_module_path != NULL) {
2083 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
2084 if (pkcs11_engine_path_copy == NULL) {
2085 os_free(pkcs11_engine_path_copy);
2086 return -1;
2087 }
2088 }
2089
2090 os_free(wpa_s->conf->pkcs11_engine_path);
2091 os_free(wpa_s->conf->pkcs11_module_path);
2092 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2093 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2094
2095 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2096 eapol_sm_deinit(wpa_s->eapol);
2097 wpa_s->eapol = NULL;
2098 if (wpa_supplicant_init_eapol(wpa_s)) {
2099 /* Error -> Reset paths to the default value (NULL) once. */
2100 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2101 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2102 NULL);
2103
2104 return -1;
2105 }
2106 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2107
2108 return 0;
2109}
2110
2111
2112/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2114 * @wpa_s: wpa_supplicant structure for a network interface
2115 * @ap_scan: AP scan mode
2116 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2117 *
2118 */
2119int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2120{
2121
2122 int old_ap_scan;
2123
2124 if (ap_scan < 0 || ap_scan > 2)
2125 return -1;
2126
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002127#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002128 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2129 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2130 wpa_s->wpa_state < WPA_COMPLETED) {
2131 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2132 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002133 return 0;
2134 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002135#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002136
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 old_ap_scan = wpa_s->conf->ap_scan;
2138 wpa_s->conf->ap_scan = ap_scan;
2139
2140 if (old_ap_scan != wpa_s->conf->ap_scan)
2141 wpas_notify_ap_scan_changed(wpa_s);
2142
2143 return 0;
2144}
2145
2146
2147/**
2148 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2149 * @wpa_s: wpa_supplicant structure for a network interface
2150 * @expire_age: Expiration age in seconds
2151 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2152 *
2153 */
2154int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2155 unsigned int bss_expire_age)
2156{
2157 if (bss_expire_age < 10) {
2158 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2159 bss_expire_age);
2160 return -1;
2161 }
2162 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2163 bss_expire_age);
2164 wpa_s->conf->bss_expiration_age = bss_expire_age;
2165
2166 return 0;
2167}
2168
2169
2170/**
2171 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2172 * @wpa_s: wpa_supplicant structure for a network interface
2173 * @expire_count: number of scans after which an unseen BSS is reclaimed
2174 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2175 *
2176 */
2177int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2178 unsigned int bss_expire_count)
2179{
2180 if (bss_expire_count < 1) {
2181 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2182 bss_expire_count);
2183 return -1;
2184 }
2185 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2186 bss_expire_count);
2187 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2188
2189 return 0;
2190}
2191
2192
2193/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002194 * wpa_supplicant_set_scan_interval - Set scan interval
2195 * @wpa_s: wpa_supplicant structure for a network interface
2196 * @scan_interval: scan interval in seconds
2197 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2198 *
2199 */
2200int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2201 int scan_interval)
2202{
2203 if (scan_interval < 0) {
2204 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2205 scan_interval);
2206 return -1;
2207 }
2208 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2209 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002210 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002211
2212 return 0;
2213}
2214
2215
2216/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217 * wpa_supplicant_set_debug_params - Set global debug params
2218 * @global: wpa_global structure
2219 * @debug_level: debug level
2220 * @debug_timestamp: determines if show timestamp in debug data
2221 * @debug_show_keys: determines if show keys in debug data
2222 * Returns: 0 if succeed or -1 if debug_level has wrong value
2223 */
2224int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2225 int debug_timestamp, int debug_show_keys)
2226{
2227
2228 int old_level, old_timestamp, old_show_keys;
2229
2230 /* check for allowed debuglevels */
2231 if (debug_level != MSG_EXCESSIVE &&
2232 debug_level != MSG_MSGDUMP &&
2233 debug_level != MSG_DEBUG &&
2234 debug_level != MSG_INFO &&
2235 debug_level != MSG_WARNING &&
2236 debug_level != MSG_ERROR)
2237 return -1;
2238
2239 old_level = wpa_debug_level;
2240 old_timestamp = wpa_debug_timestamp;
2241 old_show_keys = wpa_debug_show_keys;
2242
2243 wpa_debug_level = debug_level;
2244 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2245 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2246
2247 if (wpa_debug_level != old_level)
2248 wpas_notify_debug_level_changed(global);
2249 if (wpa_debug_timestamp != old_timestamp)
2250 wpas_notify_debug_timestamp_changed(global);
2251 if (wpa_debug_show_keys != old_show_keys)
2252 wpas_notify_debug_show_keys_changed(global);
2253
2254 return 0;
2255}
2256
2257
2258/**
2259 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2260 * @wpa_s: Pointer to wpa_supplicant data
2261 * Returns: A pointer to the current network structure or %NULL on failure
2262 */
2263struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2264{
2265 struct wpa_ssid *entry;
2266 u8 ssid[MAX_SSID_LEN];
2267 int res;
2268 size_t ssid_len;
2269 u8 bssid[ETH_ALEN];
2270 int wired;
2271
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002272 res = wpa_drv_get_ssid(wpa_s, ssid);
2273 if (res < 0) {
2274 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2275 "driver");
2276 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002277 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002278 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002279
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002280 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2282 "driver");
2283 return NULL;
2284 }
2285
2286 wired = wpa_s->conf->ap_scan == 0 &&
2287 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2288
2289 entry = wpa_s->conf->ssid;
2290 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002291 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292 ((ssid_len == entry->ssid_len &&
2293 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2294 (!entry->bssid_set ||
2295 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2296 return entry;
2297#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002298 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002299 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2300 (entry->ssid == NULL || entry->ssid_len == 0) &&
2301 (!entry->bssid_set ||
2302 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2303 return entry;
2304#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002305
Dmitry Shmidt04949592012-07-19 12:16:46 -07002306 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002307 entry->ssid_len == 0 &&
2308 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2309 return entry;
2310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002311 entry = entry->next;
2312 }
2313
2314 return NULL;
2315}
2316
2317
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002318static int select_driver(struct wpa_supplicant *wpa_s, int i)
2319{
2320 struct wpa_global *global = wpa_s->global;
2321
2322 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2323 global->drv_priv[i] = wpa_drivers[i]->global_init();
2324 if (global->drv_priv[i] == NULL) {
2325 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2326 "'%s'", wpa_drivers[i]->name);
2327 return -1;
2328 }
2329 }
2330
2331 wpa_s->driver = wpa_drivers[i];
2332 wpa_s->global_drv_priv = global->drv_priv[i];
2333
2334 return 0;
2335}
2336
2337
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2339 const char *name)
2340{
2341 int i;
2342 size_t len;
2343 const char *pos, *driver = name;
2344
2345 if (wpa_s == NULL)
2346 return -1;
2347
2348 if (wpa_drivers[0] == NULL) {
2349 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2350 "wpa_supplicant");
2351 return -1;
2352 }
2353
2354 if (name == NULL) {
2355 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002356 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 }
2358
2359 do {
2360 pos = os_strchr(driver, ',');
2361 if (pos)
2362 len = pos - driver;
2363 else
2364 len = os_strlen(driver);
2365
2366 for (i = 0; wpa_drivers[i]; i++) {
2367 if (os_strlen(wpa_drivers[i]->name) == len &&
2368 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002369 0) {
2370 /* First driver that succeeds wins */
2371 if (select_driver(wpa_s, i) == 0)
2372 return 0;
2373 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 }
2375
2376 driver = pos + 1;
2377 } while (pos);
2378
2379 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2380 return -1;
2381}
2382
2383
2384/**
2385 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2386 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2387 * with struct wpa_driver_ops::init()
2388 * @src_addr: Source address of the EAPOL frame
2389 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2390 * @len: Length of the EAPOL data
2391 *
2392 * This function is called for each received EAPOL frame. Most driver
2393 * interfaces rely on more generic OS mechanism for receiving frames through
2394 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2395 * take care of received EAPOL frames and deliver them to the core supplicant
2396 * code by calling this function.
2397 */
2398void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2399 const u8 *buf, size_t len)
2400{
2401 struct wpa_supplicant *wpa_s = ctx;
2402
2403 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2404 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2405
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002406#ifdef CONFIG_PEERKEY
2407 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2408 wpa_s->current_ssid->peerkey &&
2409 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2410 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2411 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2412 return;
2413 }
2414#endif /* CONFIG_PEERKEY */
2415
Jouni Malinena05074c2012-12-21 21:35:35 +02002416 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2417 (wpa_s->last_eapol_matches_bssid &&
2418#ifdef CONFIG_AP
2419 !wpa_s->ap_iface &&
2420#endif /* CONFIG_AP */
2421 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002422 /*
2423 * There is possible race condition between receiving the
2424 * association event and the EAPOL frame since they are coming
2425 * through different paths from the driver. In order to avoid
2426 * issues in trying to process the EAPOL frame before receiving
2427 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002428 * the association event is received. This may also be needed in
2429 * driver-based roaming case, so also use src_addr != BSSID as a
2430 * trigger if we have previously confirmed that the
2431 * Authenticator uses BSSID as the src_addr (which is not the
2432 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 */
2434 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002435 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2436 wpa_supplicant_state_txt(wpa_s->wpa_state),
2437 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 wpabuf_free(wpa_s->pending_eapol_rx);
2439 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2440 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002441 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2443 ETH_ALEN);
2444 }
2445 return;
2446 }
2447
Jouni Malinena05074c2012-12-21 21:35:35 +02002448 wpa_s->last_eapol_matches_bssid =
2449 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2450
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002451#ifdef CONFIG_AP
2452 if (wpa_s->ap_iface) {
2453 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2454 return;
2455 }
2456#endif /* CONFIG_AP */
2457
2458 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2459 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2460 "no key management is configured");
2461 return;
2462 }
2463
2464 if (wpa_s->eapol_received == 0 &&
2465 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2466 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2467 wpa_s->wpa_state != WPA_COMPLETED) &&
2468 (wpa_s->current_ssid == NULL ||
2469 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2470 /* Timeout for completing IEEE 802.1X and WPA authentication */
2471 wpa_supplicant_req_auth_timeout(
2472 wpa_s,
2473 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2474 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2475 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2476 70 : 10, 0);
2477 }
2478 wpa_s->eapol_received++;
2479
2480 if (wpa_s->countermeasures) {
2481 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2482 "EAPOL packet");
2483 return;
2484 }
2485
2486#ifdef CONFIG_IBSS_RSN
2487 if (wpa_s->current_ssid &&
2488 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2489 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2490 return;
2491 }
2492#endif /* CONFIG_IBSS_RSN */
2493
2494 /* Source address of the incoming EAPOL frame could be compared to the
2495 * current BSSID. However, it is possible that a centralized
2496 * Authenticator could be using another MAC address than the BSSID of
2497 * an AP, so just allow any address to be used for now. The replies are
2498 * still sent to the current BSSID (if available), though. */
2499
2500 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2501 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2502 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2503 return;
2504 wpa_drv_poll(wpa_s);
2505 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2506 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2507 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2508 /*
2509 * Set portValid = TRUE here since we are going to skip 4-way
2510 * handshake processing which would normally set portValid. We
2511 * need this to allow the EAPOL state machines to be completed
2512 * without going through EAPOL-Key handshake.
2513 */
2514 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2515 }
2516}
2517
2518
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002519int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 if (wpa_s->driver->send_eapol) {
2522 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2523 if (addr)
2524 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002525 } else if ((!wpa_s->p2p_mgmt ||
2526 !(wpa_s->drv_flags &
2527 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2528 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002530 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2532 wpa_drv_get_mac_addr(wpa_s),
2533 ETH_P_EAPOL,
2534 wpa_supplicant_rx_eapol, wpa_s, 0);
2535 if (wpa_s->l2 == NULL)
2536 return -1;
2537 } else {
2538 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2539 if (addr)
2540 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2541 }
2542
2543 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2544 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2545 return -1;
2546 }
2547
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002548 return 0;
2549}
2550
2551
Dmitry Shmidt04949592012-07-19 12:16:46 -07002552static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2553 const u8 *buf, size_t len)
2554{
2555 struct wpa_supplicant *wpa_s = ctx;
2556 const struct l2_ethhdr *eth;
2557
2558 if (len < sizeof(*eth))
2559 return;
2560 eth = (const struct l2_ethhdr *) buf;
2561
2562 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2563 !(eth->h_dest[0] & 0x01)) {
2564 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2565 " (bridge - not for this interface - ignore)",
2566 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2567 return;
2568 }
2569
2570 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2571 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2572 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2573 len - sizeof(*eth));
2574}
2575
2576
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002577/**
2578 * wpa_supplicant_driver_init - Initialize driver interface parameters
2579 * @wpa_s: Pointer to wpa_supplicant data
2580 * Returns: 0 on success, -1 on failure
2581 *
2582 * This function is called to initialize driver interface parameters.
2583 * wpa_drv_init() must have been called before this function to initialize the
2584 * driver interface.
2585 */
2586int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2587{
2588 static int interface_count = 0;
2589
2590 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2591 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002593 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2594 MAC2STR(wpa_s->own_addr));
2595 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2596
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 if (wpa_s->bridge_ifname[0]) {
2598 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2599 "interface '%s'", wpa_s->bridge_ifname);
2600 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2601 wpa_s->own_addr,
2602 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002603 wpa_supplicant_rx_eapol_bridge,
2604 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 if (wpa_s->l2_br == NULL) {
2606 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2607 "connection for the bridge interface '%s'",
2608 wpa_s->bridge_ifname);
2609 return -1;
2610 }
2611 }
2612
2613 wpa_clear_keys(wpa_s, NULL);
2614
2615 /* Make sure that TKIP countermeasures are not left enabled (could
2616 * happen if wpa_supplicant is killed during countermeasures. */
2617 wpa_drv_set_countermeasures(wpa_s, 0);
2618
2619 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2620 wpa_drv_flush_pmkid(wpa_s);
2621
2622 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002623 wpa_s->prev_scan_wildcard = 0;
2624
Dmitry Shmidt04949592012-07-19 12:16:46 -07002625 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002626 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2627 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2628 interface_count = 0;
2629 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002630 if (wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
2631 100000))
2632 wpa_supplicant_req_scan(wpa_s, interface_count,
2633 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 interface_count++;
2635 } else
2636 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2637
2638 return 0;
2639}
2640
2641
2642static int wpa_supplicant_daemon(const char *pid_file)
2643{
2644 wpa_printf(MSG_DEBUG, "Daemonize..");
2645 return os_daemonize(pid_file);
2646}
2647
2648
2649static struct wpa_supplicant * wpa_supplicant_alloc(void)
2650{
2651 struct wpa_supplicant *wpa_s;
2652
2653 wpa_s = os_zalloc(sizeof(*wpa_s));
2654 if (wpa_s == NULL)
2655 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002656 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 wpa_s->scan_interval = 5;
2658 wpa_s->new_connection = 1;
2659 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002660 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661
2662 return wpa_s;
2663}
2664
2665
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002666#ifdef CONFIG_HT_OVERRIDES
2667
2668static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2669 struct ieee80211_ht_capabilities *htcaps,
2670 struct ieee80211_ht_capabilities *htcaps_mask,
2671 const char *ht_mcs)
2672{
2673 /* parse ht_mcs into hex array */
2674 int i;
2675 const char *tmp = ht_mcs;
2676 char *end = NULL;
2677
2678 /* If ht_mcs is null, do not set anything */
2679 if (!ht_mcs)
2680 return 0;
2681
2682 /* This is what we are setting in the kernel */
2683 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2684
2685 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2686
2687 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2688 errno = 0;
2689 long v = strtol(tmp, &end, 16);
2690 if (errno == 0) {
2691 wpa_msg(wpa_s, MSG_DEBUG,
2692 "htcap value[%i]: %ld end: %p tmp: %p",
2693 i, v, end, tmp);
2694 if (end == tmp)
2695 break;
2696
2697 htcaps->supported_mcs_set[i] = v;
2698 tmp = end;
2699 } else {
2700 wpa_msg(wpa_s, MSG_ERROR,
2701 "Failed to parse ht-mcs: %s, error: %s\n",
2702 ht_mcs, strerror(errno));
2703 return -1;
2704 }
2705 }
2706
2707 /*
2708 * If we were able to parse any values, then set mask for the MCS set.
2709 */
2710 if (i) {
2711 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2712 IEEE80211_HT_MCS_MASK_LEN - 1);
2713 /* skip the 3 reserved bits */
2714 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2715 0x1f;
2716 }
2717
2718 return 0;
2719}
2720
2721
2722static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2723 struct ieee80211_ht_capabilities *htcaps,
2724 struct ieee80211_ht_capabilities *htcaps_mask,
2725 int disabled)
2726{
2727 u16 msk;
2728
2729 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2730
2731 if (disabled == -1)
2732 return 0;
2733
2734 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2735 htcaps_mask->ht_capabilities_info |= msk;
2736 if (disabled)
2737 htcaps->ht_capabilities_info &= msk;
2738 else
2739 htcaps->ht_capabilities_info |= msk;
2740
2741 return 0;
2742}
2743
2744
2745static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2746 struct ieee80211_ht_capabilities *htcaps,
2747 struct ieee80211_ht_capabilities *htcaps_mask,
2748 int factor)
2749{
2750 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2751
2752 if (factor == -1)
2753 return 0;
2754
2755 if (factor < 0 || factor > 3) {
2756 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2757 "Must be 0-3 or -1", factor);
2758 return -EINVAL;
2759 }
2760
2761 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2762 htcaps->a_mpdu_params &= ~0x3;
2763 htcaps->a_mpdu_params |= factor & 0x3;
2764
2765 return 0;
2766}
2767
2768
2769static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2770 struct ieee80211_ht_capabilities *htcaps,
2771 struct ieee80211_ht_capabilities *htcaps_mask,
2772 int density)
2773{
2774 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2775
2776 if (density == -1)
2777 return 0;
2778
2779 if (density < 0 || density > 7) {
2780 wpa_msg(wpa_s, MSG_ERROR,
2781 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2782 density);
2783 return -EINVAL;
2784 }
2785
2786 htcaps_mask->a_mpdu_params |= 0x1C;
2787 htcaps->a_mpdu_params &= ~(0x1C);
2788 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2789
2790 return 0;
2791}
2792
2793
2794static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2795 struct ieee80211_ht_capabilities *htcaps,
2796 struct ieee80211_ht_capabilities *htcaps_mask,
2797 int disabled)
2798{
2799 /* Masking these out disables HT40 */
2800 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2801 HT_CAP_INFO_SHORT_GI40MHZ);
2802
2803 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2804
2805 if (disabled)
2806 htcaps->ht_capabilities_info &= ~msk;
2807 else
2808 htcaps->ht_capabilities_info |= msk;
2809
2810 htcaps_mask->ht_capabilities_info |= msk;
2811
2812 return 0;
2813}
2814
2815
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002816static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2817 struct ieee80211_ht_capabilities *htcaps,
2818 struct ieee80211_ht_capabilities *htcaps_mask,
2819 int disabled)
2820{
2821 /* Masking these out disables SGI */
2822 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2823 HT_CAP_INFO_SHORT_GI40MHZ);
2824
2825 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2826
2827 if (disabled)
2828 htcaps->ht_capabilities_info &= ~msk;
2829 else
2830 htcaps->ht_capabilities_info |= msk;
2831
2832 htcaps_mask->ht_capabilities_info |= msk;
2833
2834 return 0;
2835}
2836
2837
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002838void wpa_supplicant_apply_ht_overrides(
2839 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2840 struct wpa_driver_associate_params *params)
2841{
2842 struct ieee80211_ht_capabilities *htcaps;
2843 struct ieee80211_ht_capabilities *htcaps_mask;
2844
2845 if (!ssid)
2846 return;
2847
2848 params->disable_ht = ssid->disable_ht;
2849 if (!params->htcaps || !params->htcaps_mask)
2850 return;
2851
2852 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2853 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2854 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2855 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2856 ssid->disable_max_amsdu);
2857 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2858 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2859 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002860 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002861}
2862
2863#endif /* CONFIG_HT_OVERRIDES */
2864
2865
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002866#ifdef CONFIG_VHT_OVERRIDES
2867void wpa_supplicant_apply_vht_overrides(
2868 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2869 struct wpa_driver_associate_params *params)
2870{
2871 struct ieee80211_vht_capabilities *vhtcaps;
2872 struct ieee80211_vht_capabilities *vhtcaps_mask;
2873
2874 if (!ssid)
2875 return;
2876
2877 params->disable_vht = ssid->disable_vht;
2878
2879 vhtcaps = (void *) params->vhtcaps;
2880 vhtcaps_mask = (void *) params->vhtcaps_mask;
2881
2882 if (!vhtcaps || !vhtcaps_mask)
2883 return;
2884
2885 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2886 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2887
2888#define OVERRIDE_MCS(i) \
2889 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2890 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2891 3 << 2 * (i - 1); \
2892 vhtcaps->vht_supported_mcs_set.tx_map |= \
2893 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2894 } \
2895 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2896 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2897 3 << 2 * (i - 1); \
2898 vhtcaps->vht_supported_mcs_set.rx_map |= \
2899 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2900 }
2901
2902 OVERRIDE_MCS(1);
2903 OVERRIDE_MCS(2);
2904 OVERRIDE_MCS(3);
2905 OVERRIDE_MCS(4);
2906 OVERRIDE_MCS(5);
2907 OVERRIDE_MCS(6);
2908 OVERRIDE_MCS(7);
2909 OVERRIDE_MCS(8);
2910}
2911#endif /* CONFIG_VHT_OVERRIDES */
2912
2913
Dmitry Shmidt04949592012-07-19 12:16:46 -07002914static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2915{
2916#ifdef PCSC_FUNCS
2917 size_t len;
2918
2919 if (!wpa_s->conf->pcsc_reader)
2920 return 0;
2921
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002922 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002923 if (!wpa_s->scard)
2924 return 1;
2925
2926 if (wpa_s->conf->pcsc_pin &&
2927 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2928 scard_deinit(wpa_s->scard);
2929 wpa_s->scard = NULL;
2930 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2931 return -1;
2932 }
2933
2934 len = sizeof(wpa_s->imsi) - 1;
2935 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2936 scard_deinit(wpa_s->scard);
2937 wpa_s->scard = NULL;
2938 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2939 return -1;
2940 }
2941 wpa_s->imsi[len] = '\0';
2942
2943 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2944
2945 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2946 wpa_s->imsi, wpa_s->mnc_len);
2947
2948 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2949 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2950#endif /* PCSC_FUNCS */
2951
2952 return 0;
2953}
2954
2955
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002956int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
2957{
2958 char *val, *pos;
2959
2960 ext_password_deinit(wpa_s->ext_pw);
2961 wpa_s->ext_pw = NULL;
2962 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
2963
2964 if (!wpa_s->conf->ext_password_backend)
2965 return 0;
2966
2967 val = os_strdup(wpa_s->conf->ext_password_backend);
2968 if (val == NULL)
2969 return -1;
2970 pos = os_strchr(val, ':');
2971 if (pos)
2972 *pos++ = '\0';
2973
2974 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
2975
2976 wpa_s->ext_pw = ext_password_init(val, pos);
2977 os_free(val);
2978 if (wpa_s->ext_pw == NULL) {
2979 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
2980 return -1;
2981 }
2982 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
2983
2984 return 0;
2985}
2986
2987
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002988static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
2989 const char *rn)
2990{
2991 struct wpa_supplicant *iface = wpa_s->global->ifaces;
2992 struct wpa_radio *radio;
2993
2994 while (rn && iface) {
2995 radio = iface->radio;
2996 if (radio && os_strcmp(rn, radio->name) == 0) {
2997 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
2998 wpa_s->ifname, rn);
2999 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3000 return radio;
3001 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003002
3003 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003004 }
3005
3006 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3007 wpa_s->ifname, rn ? rn : "N/A");
3008 radio = os_zalloc(sizeof(*radio));
3009 if (radio == NULL)
3010 return NULL;
3011
3012 if (rn)
3013 os_strlcpy(radio->name, rn, sizeof(radio->name));
3014 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003015 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003016 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3017
3018 return radio;
3019}
3020
3021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003022static void radio_work_free(struct wpa_radio_work *work)
3023{
3024 if (work->wpa_s->scan_work == work) {
3025 /* This should not really happen. */
3026 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3027 work->type, work, work->started);
3028 work->wpa_s->scan_work = NULL;
3029 }
3030
3031#ifdef CONFIG_P2P
3032 if (work->wpa_s->p2p_scan_work == work) {
3033 /* This should not really happen. */
3034 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3035 work->type, work, work->started);
3036 work->wpa_s->p2p_scan_work = NULL;
3037 }
3038#endif /* CONFIG_P2P */
3039
3040 dl_list_del(&work->list);
3041 os_free(work);
3042}
3043
3044
3045static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3046{
3047 struct wpa_radio *radio = eloop_ctx;
3048 struct wpa_radio_work *work;
3049 struct os_reltime now, diff;
3050 struct wpa_supplicant *wpa_s;
3051
3052 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3053 if (work == NULL)
3054 return;
3055
3056 if (work->started)
3057 return; /* already started and still in progress */
3058
3059 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3060 radio_list);
3061 if (wpa_s && wpa_s->external_scan_running) {
3062 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3063 return;
3064 }
3065
3066 os_get_reltime(&now);
3067 os_reltime_sub(&now, &work->time, &diff);
3068 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3069 work->type, work, diff.sec, diff.usec);
3070 work->started = 1;
3071 work->time = now;
3072 work->cb(work, 0);
3073}
3074
3075
3076void radio_remove_unstarted_work(struct wpa_supplicant *wpa_s, const char *type)
3077{
3078 struct wpa_radio_work *work, *tmp;
3079 struct wpa_radio *radio = wpa_s->radio;
3080
3081 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3082 list) {
3083 if (type && (work->started || os_strcmp(type, work->type) != 0))
3084 continue;
3085 if (work->started) {
3086 wpa_dbg(wpa_s, MSG_DEBUG, "Leaving started radio work '%s'@%p in the list",
3087 work->type, work);
3088 continue;
3089 }
3090 wpa_dbg(wpa_s, MSG_DEBUG, "Remove unstarted radio work '%s'@%p",
3091 work->type, work);
3092 work->cb(work, 1);
3093 radio_work_free(work);
3094 }
3095}
3096
3097
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003098static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3099{
3100 struct wpa_radio *radio = wpa_s->radio;
3101
3102 if (!radio)
3103 return;
3104
3105 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3106 wpa_s->ifname, radio->name);
3107 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003108 if (!dl_list_empty(&radio->ifaces)) {
3109 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003110 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003111 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003112
3113 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003114 radio_remove_unstarted_work(wpa_s, NULL);
3115 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3116 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003117 os_free(radio);
3118}
3119
3120
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003121void radio_work_check_next(struct wpa_supplicant *wpa_s)
3122{
3123 struct wpa_radio *radio = wpa_s->radio;
3124
3125 if (dl_list_empty(&radio->work))
3126 return;
3127 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3128 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3129}
3130
3131
3132/**
3133 * radio_add_work - Add a radio work item
3134 * @wpa_s: Pointer to wpa_supplicant data
3135 * @freq: Frequency of the offchannel operation in MHz or 0
3136 * @type: Unique identifier for each type of work
3137 * @next: Force as the next work to be executed
3138 * @cb: Callback function for indicating when radio is available
3139 * @ctx: Context pointer for the work (work->ctx in cb())
3140 * Returns: 0 on success, -1 on failure
3141 *
3142 * This function is used to request time for an operation that requires
3143 * exclusive radio control. Once the radio is available, the registered callback
3144 * function will be called. radio_work_done() must be called once the exclusive
3145 * radio operation has been completed, so that the radio is freed for other
3146 * operations. The special case of deinit=1 is used to free the context data
3147 * during interface removal. That does not allow the callback function to start
3148 * the radio operation, i.e., it must free any resources allocated for the radio
3149 * work and return.
3150 *
3151 * The @freq parameter can be used to indicate a single channel on which the
3152 * offchannel operation will occur. This may allow multiple radio work
3153 * operations to be performed in parallel if they apply for the same channel.
3154 * Setting this to 0 indicates that the work item may use multiple channels or
3155 * requires exclusive control of the radio.
3156 */
3157int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3158 const char *type, int next,
3159 void (*cb)(struct wpa_radio_work *work, int deinit),
3160 void *ctx)
3161{
3162 struct wpa_radio_work *work;
3163 int was_empty;
3164
3165 work = os_zalloc(sizeof(*work));
3166 if (work == NULL)
3167 return -1;
3168 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3169 os_get_reltime(&work->time);
3170 work->freq = freq;
3171 work->type = type;
3172 work->wpa_s = wpa_s;
3173 work->cb = cb;
3174 work->ctx = ctx;
3175
3176 was_empty = dl_list_empty(&wpa_s->radio->work);
3177 if (next)
3178 dl_list_add(&wpa_s->radio->work, &work->list);
3179 else
3180 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3181 if (was_empty) {
3182 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3183 radio_work_check_next(wpa_s);
3184 }
3185
3186 return 0;
3187}
3188
3189
3190/**
3191 * radio_work_done - Indicate that a radio work item has been completed
3192 * @work: Completed work
3193 *
3194 * This function is called once the callback function registered with
3195 * radio_add_work() has completed its work.
3196 */
3197void radio_work_done(struct wpa_radio_work *work)
3198{
3199 struct wpa_supplicant *wpa_s = work->wpa_s;
3200 struct os_reltime now, diff;
3201 unsigned int started = work->started;
3202
3203 os_get_reltime(&now);
3204 os_reltime_sub(&now, &work->time, &diff);
3205 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3206 work->type, work, started ? "done" : "canceled",
3207 diff.sec, diff.usec);
3208 radio_work_free(work);
3209 if (started)
3210 radio_work_check_next(wpa_s);
3211}
3212
3213
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003214static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3215 struct wpa_interface *iface)
3216{
3217 const char *ifname, *driver, *rn;
3218
3219 driver = iface->driver;
3220next_driver:
3221 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3222 return -1;
3223
3224 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3225 if (wpa_s->drv_priv == NULL) {
3226 const char *pos;
3227 pos = driver ? os_strchr(driver, ',') : NULL;
3228 if (pos) {
3229 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3230 "driver interface - try next driver wrapper");
3231 driver = pos + 1;
3232 goto next_driver;
3233 }
3234 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3235 "interface");
3236 return -1;
3237 }
3238 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3239 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3240 "driver_param '%s'", wpa_s->conf->driver_param);
3241 return -1;
3242 }
3243
3244 ifname = wpa_drv_get_ifname(wpa_s);
3245 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3246 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3247 "interface name with '%s'", ifname);
3248 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3249 }
3250
3251 if (wpa_s->driver->get_radio_name)
3252 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3253 else
3254 rn = NULL;
3255 if (rn && rn[0] == '\0')
3256 rn = NULL;
3257
3258 wpa_s->radio = radio_add_interface(wpa_s, rn);
3259 if (wpa_s->radio == NULL)
3260 return -1;
3261
3262 return 0;
3263}
3264
3265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3267 struct wpa_interface *iface)
3268{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003269 struct wpa_driver_capa capa;
3270
3271 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3272 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3273 iface->confname ? iface->confname : "N/A",
3274 iface->driver ? iface->driver : "default",
3275 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3276 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3277
3278 if (iface->confname) {
3279#ifdef CONFIG_BACKEND_FILE
3280 wpa_s->confname = os_rel2abs_path(iface->confname);
3281 if (wpa_s->confname == NULL) {
3282 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3283 "for configuration file '%s'.",
3284 iface->confname);
3285 return -1;
3286 }
3287 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3288 iface->confname, wpa_s->confname);
3289#else /* CONFIG_BACKEND_FILE */
3290 wpa_s->confname = os_strdup(iface->confname);
3291#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003292 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003293 if (wpa_s->conf == NULL) {
3294 wpa_printf(MSG_ERROR, "Failed to read or parse "
3295 "configuration '%s'.", wpa_s->confname);
3296 return -1;
3297 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003298 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3299 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003300
3301 /*
3302 * Override ctrl_interface and driver_param if set on command
3303 * line.
3304 */
3305 if (iface->ctrl_interface) {
3306 os_free(wpa_s->conf->ctrl_interface);
3307 wpa_s->conf->ctrl_interface =
3308 os_strdup(iface->ctrl_interface);
3309 }
3310
3311 if (iface->driver_param) {
3312 os_free(wpa_s->conf->driver_param);
3313 wpa_s->conf->driver_param =
3314 os_strdup(iface->driver_param);
3315 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003316
3317 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3318 os_free(wpa_s->conf->ctrl_interface);
3319 wpa_s->conf->ctrl_interface = NULL;
3320 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003321 } else
3322 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3323 iface->driver_param);
3324
3325 if (wpa_s->conf == NULL) {
3326 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3327 return -1;
3328 }
3329
3330 if (iface->ifname == NULL) {
3331 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3332 return -1;
3333 }
3334 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3335 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3336 iface->ifname);
3337 return -1;
3338 }
3339 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3340
3341 if (iface->bridge_ifname) {
3342 if (os_strlen(iface->bridge_ifname) >=
3343 sizeof(wpa_s->bridge_ifname)) {
3344 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3345 "name '%s'.", iface->bridge_ifname);
3346 return -1;
3347 }
3348 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3349 sizeof(wpa_s->bridge_ifname));
3350 }
3351
3352 /* RSNA Supplicant Key Management - INITIALIZE */
3353 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3354 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3355
3356 /* Initialize driver interface and register driver event handler before
3357 * L2 receive handler so that association events are processed before
3358 * EAPOL-Key packets if both become available for the same select()
3359 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003360 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003361 return -1;
3362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003363 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3364 return -1;
3365
3366 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3367 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3368 NULL);
3369 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3370
3371 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3372 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3373 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3374 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3375 "dot11RSNAConfigPMKLifetime");
3376 return -1;
3377 }
3378
3379 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3380 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3381 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3382 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3383 "dot11RSNAConfigPMKReauthThreshold");
3384 return -1;
3385 }
3386
3387 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3388 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3389 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3390 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3391 "dot11RSNAConfigSATimeout");
3392 return -1;
3393 }
3394
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003395 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3396 &wpa_s->hw.num_modes,
3397 &wpa_s->hw.flags);
3398
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003399 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003400 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003402 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003403 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003405 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3406 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3407 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003408 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3409 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003410 wpa_s->extended_capa = capa.extended_capa;
3411 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3412 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003413 wpa_s->num_multichan_concurrent =
3414 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415 }
3416 if (wpa_s->max_remain_on_chan == 0)
3417 wpa_s->max_remain_on_chan = 1000;
3418
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003419 /*
3420 * Only take p2p_mgmt parameters when P2P Device is supported.
3421 * Doing it here as it determines whether l2_packet_init() will be done
3422 * during wpa_supplicant_driver_init().
3423 */
3424 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3425 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3426 else
3427 iface->p2p_mgmt = 1;
3428
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003429 if (wpa_s->num_multichan_concurrent == 0)
3430 wpa_s->num_multichan_concurrent = 1;
3431
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432 if (wpa_supplicant_driver_init(wpa_s) < 0)
3433 return -1;
3434
3435#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003436 if ((!iface->p2p_mgmt ||
3437 !(wpa_s->drv_flags &
3438 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3439 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003440 return -1;
3441#endif /* CONFIG_TDLS */
3442
3443 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3444 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3445 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3446 return -1;
3447 }
3448
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003449 if (wpas_wps_init(wpa_s))
3450 return -1;
3451
3452 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3453 return -1;
3454 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3455
3456 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3457 if (wpa_s->ctrl_iface == NULL) {
3458 wpa_printf(MSG_ERROR,
3459 "Failed to initialize control interface '%s'.\n"
3460 "You may have another wpa_supplicant process "
3461 "already running or the file was\n"
3462 "left by an unclean termination of wpa_supplicant "
3463 "in which case you will need\n"
3464 "to manually remove this file before starting "
3465 "wpa_supplicant again.\n",
3466 wpa_s->conf->ctrl_interface);
3467 return -1;
3468 }
3469
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003470 wpa_s->gas = gas_query_init(wpa_s);
3471 if (wpa_s->gas == NULL) {
3472 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3473 return -1;
3474 }
3475
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003477 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003478 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3479 return -1;
3480 }
3481#endif /* CONFIG_P2P */
3482
3483 if (wpa_bss_init(wpa_s) < 0)
3484 return -1;
3485
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003486#ifdef CONFIG_EAP_PROXY
3487{
3488 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003489 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3490 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003491 if (wpa_s->mnc_len > 0) {
3492 wpa_s->imsi[len] = '\0';
3493 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3494 wpa_s->imsi, wpa_s->mnc_len);
3495 } else {
3496 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3497 }
3498}
3499#endif /* CONFIG_EAP_PROXY */
3500
Dmitry Shmidt04949592012-07-19 12:16:46 -07003501 if (pcsc_reader_init(wpa_s) < 0)
3502 return -1;
3503
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003504 if (wpas_init_ext_pw(wpa_s) < 0)
3505 return -1;
3506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003507 return 0;
3508}
3509
3510
3511static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003512 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003513{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003514 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003515 if (wpa_s->drv_priv) {
3516 wpa_supplicant_deauthenticate(wpa_s,
3517 WLAN_REASON_DEAUTH_LEAVING);
3518
3519 wpa_drv_set_countermeasures(wpa_s, 0);
3520 wpa_clear_keys(wpa_s, NULL);
3521 }
3522
3523 wpa_supplicant_cleanup(wpa_s);
3524
Dmitry Shmidt04949592012-07-19 12:16:46 -07003525#ifdef CONFIG_P2P
3526 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3527 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3528 "the management interface is being removed");
3529 wpas_p2p_deinit_global(wpa_s->global);
3530 }
3531#endif /* CONFIG_P2P */
3532
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003533 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003534 radio_remove_interface(wpa_s);
3535
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 if (wpa_s->drv_priv)
3537 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003538
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003539 if (notify)
3540 wpas_notify_iface_removed(wpa_s);
3541
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003542 if (terminate)
3543 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003544
3545 if (wpa_s->ctrl_iface) {
3546 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3547 wpa_s->ctrl_iface = NULL;
3548 }
3549
3550 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003551 wpa_config_free(wpa_s->conf);
3552 wpa_s->conf = NULL;
3553 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003554
3555 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003556}
3557
3558
3559/**
3560 * wpa_supplicant_add_iface - Add a new network interface
3561 * @global: Pointer to global data from wpa_supplicant_init()
3562 * @iface: Interface configuration options
3563 * Returns: Pointer to the created interface or %NULL on failure
3564 *
3565 * This function is used to add new network interfaces for %wpa_supplicant.
3566 * This can be called before wpa_supplicant_run() to add interfaces before the
3567 * main event loop has been started. In addition, new interfaces can be added
3568 * dynamically while %wpa_supplicant is already running. This could happen,
3569 * e.g., when a hotplug network adapter is inserted.
3570 */
3571struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3572 struct wpa_interface *iface)
3573{
3574 struct wpa_supplicant *wpa_s;
3575 struct wpa_interface t_iface;
3576 struct wpa_ssid *ssid;
3577
3578 if (global == NULL || iface == NULL)
3579 return NULL;
3580
3581 wpa_s = wpa_supplicant_alloc();
3582 if (wpa_s == NULL)
3583 return NULL;
3584
3585 wpa_s->global = global;
3586
3587 t_iface = *iface;
3588 if (global->params.override_driver) {
3589 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3590 "('%s' -> '%s')",
3591 iface->driver, global->params.override_driver);
3592 t_iface.driver = global->params.override_driver;
3593 }
3594 if (global->params.override_ctrl_interface) {
3595 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3596 "ctrl_interface ('%s' -> '%s')",
3597 iface->ctrl_interface,
3598 global->params.override_ctrl_interface);
3599 t_iface.ctrl_interface =
3600 global->params.override_ctrl_interface;
3601 }
3602 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3603 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3604 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003605 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003606 return NULL;
3607 }
3608
3609 /* Notify the control interfaces about new iface */
3610 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003611 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612 return NULL;
3613 }
3614
3615 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3616 wpas_notify_network_added(wpa_s, ssid);
3617
3618 wpa_s->next = global->ifaces;
3619 global->ifaces = wpa_s;
3620
3621 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003622 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623
3624 return wpa_s;
3625}
3626
3627
3628/**
3629 * wpa_supplicant_remove_iface - Remove a network interface
3630 * @global: Pointer to global data from wpa_supplicant_init()
3631 * @wpa_s: Pointer to the network interface to be removed
3632 * Returns: 0 if interface was removed, -1 if interface was not found
3633 *
3634 * This function can be used to dynamically remove network interfaces from
3635 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3636 * addition, this function is used to remove all remaining interfaces when
3637 * %wpa_supplicant is terminated.
3638 */
3639int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003640 struct wpa_supplicant *wpa_s,
3641 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003642{
3643 struct wpa_supplicant *prev;
3644
3645 /* Remove interface from the global list of interfaces */
3646 prev = global->ifaces;
3647 if (prev == wpa_s) {
3648 global->ifaces = wpa_s->next;
3649 } else {
3650 while (prev && prev->next != wpa_s)
3651 prev = prev->next;
3652 if (prev == NULL)
3653 return -1;
3654 prev->next = wpa_s->next;
3655 }
3656
3657 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3658
3659 if (global->p2p_group_formation == wpa_s)
3660 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003661 if (global->p2p_invite_group == wpa_s)
3662 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003663 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003664
3665 return 0;
3666}
3667
3668
3669/**
3670 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3671 * @wpa_s: Pointer to the network interface
3672 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3673 */
3674const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3675{
3676 const char *eapol_method;
3677
3678 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3679 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3680 return "NO-EAP";
3681 }
3682
3683 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3684 if (eapol_method == NULL)
3685 return "UNKNOWN-EAP";
3686
3687 return eapol_method;
3688}
3689
3690
3691/**
3692 * wpa_supplicant_get_iface - Get a new network interface
3693 * @global: Pointer to global data from wpa_supplicant_init()
3694 * @ifname: Interface name
3695 * Returns: Pointer to the interface or %NULL if not found
3696 */
3697struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3698 const char *ifname)
3699{
3700 struct wpa_supplicant *wpa_s;
3701
3702 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3703 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3704 return wpa_s;
3705 }
3706 return NULL;
3707}
3708
3709
3710#ifndef CONFIG_NO_WPA_MSG
3711static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3712{
3713 struct wpa_supplicant *wpa_s = ctx;
3714 if (wpa_s == NULL)
3715 return NULL;
3716 return wpa_s->ifname;
3717}
3718#endif /* CONFIG_NO_WPA_MSG */
3719
3720
3721/**
3722 * wpa_supplicant_init - Initialize %wpa_supplicant
3723 * @params: Parameters for %wpa_supplicant
3724 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3725 *
3726 * This function is used to initialize %wpa_supplicant. After successful
3727 * initialization, the returned data pointer can be used to add and remove
3728 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3729 */
3730struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3731{
3732 struct wpa_global *global;
3733 int ret, i;
3734
3735 if (params == NULL)
3736 return NULL;
3737
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003738#ifdef CONFIG_DRIVER_NDIS
3739 {
3740 void driver_ndis_init_ops(void);
3741 driver_ndis_init_ops();
3742 }
3743#endif /* CONFIG_DRIVER_NDIS */
3744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003745#ifndef CONFIG_NO_WPA_MSG
3746 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3747#endif /* CONFIG_NO_WPA_MSG */
3748
3749 wpa_debug_open_file(params->wpa_debug_file_path);
3750 if (params->wpa_debug_syslog)
3751 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003752 if (params->wpa_debug_tracing) {
3753 ret = wpa_debug_open_linux_tracing();
3754 if (ret) {
3755 wpa_printf(MSG_ERROR,
3756 "Failed to enable trace logging");
3757 return NULL;
3758 }
3759 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003760
3761 ret = eap_register_methods();
3762 if (ret) {
3763 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3764 if (ret == -2)
3765 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3766 "the same EAP type.");
3767 return NULL;
3768 }
3769
3770 global = os_zalloc(sizeof(*global));
3771 if (global == NULL)
3772 return NULL;
3773 dl_list_init(&global->p2p_srv_bonjour);
3774 dl_list_init(&global->p2p_srv_upnp);
3775 global->params.daemonize = params->daemonize;
3776 global->params.wait_for_monitor = params->wait_for_monitor;
3777 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3778 if (params->pid_file)
3779 global->params.pid_file = os_strdup(params->pid_file);
3780 if (params->ctrl_interface)
3781 global->params.ctrl_interface =
3782 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003783 if (params->ctrl_interface_group)
3784 global->params.ctrl_interface_group =
3785 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786 if (params->override_driver)
3787 global->params.override_driver =
3788 os_strdup(params->override_driver);
3789 if (params->override_ctrl_interface)
3790 global->params.override_ctrl_interface =
3791 os_strdup(params->override_ctrl_interface);
3792 wpa_debug_level = global->params.wpa_debug_level =
3793 params->wpa_debug_level;
3794 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3795 params->wpa_debug_show_keys;
3796 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3797 params->wpa_debug_timestamp;
3798
3799 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3800
3801 if (eloop_init()) {
3802 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3803 wpa_supplicant_deinit(global);
3804 return NULL;
3805 }
3806
Jouni Malinen75ecf522011-06-27 15:19:46 -07003807 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808
3809 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3810 if (global->ctrl_iface == NULL) {
3811 wpa_supplicant_deinit(global);
3812 return NULL;
3813 }
3814
3815 if (wpas_notify_supplicant_initialized(global)) {
3816 wpa_supplicant_deinit(global);
3817 return NULL;
3818 }
3819
3820 for (i = 0; wpa_drivers[i]; i++)
3821 global->drv_count++;
3822 if (global->drv_count == 0) {
3823 wpa_printf(MSG_ERROR, "No drivers enabled");
3824 wpa_supplicant_deinit(global);
3825 return NULL;
3826 }
3827 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3828 if (global->drv_priv == NULL) {
3829 wpa_supplicant_deinit(global);
3830 return NULL;
3831 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003833#ifdef CONFIG_WIFI_DISPLAY
3834 if (wifi_display_init(global) < 0) {
3835 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3836 wpa_supplicant_deinit(global);
3837 return NULL;
3838 }
3839#endif /* CONFIG_WIFI_DISPLAY */
3840
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 return global;
3842}
3843
3844
3845/**
3846 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3847 * @global: Pointer to global data from wpa_supplicant_init()
3848 * Returns: 0 after successful event loop run, -1 on failure
3849 *
3850 * This function starts the main event loop and continues running as long as
3851 * there are any remaining events. In most cases, this function is running as
3852 * long as the %wpa_supplicant process in still in use.
3853 */
3854int wpa_supplicant_run(struct wpa_global *global)
3855{
3856 struct wpa_supplicant *wpa_s;
3857
3858 if (global->params.daemonize &&
3859 wpa_supplicant_daemon(global->params.pid_file))
3860 return -1;
3861
3862 if (global->params.wait_for_monitor) {
3863 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3864 if (wpa_s->ctrl_iface)
3865 wpa_supplicant_ctrl_iface_wait(
3866 wpa_s->ctrl_iface);
3867 }
3868
3869 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3870 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3871
3872 eloop_run();
3873
3874 return 0;
3875}
3876
3877
3878/**
3879 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3880 * @global: Pointer to global data from wpa_supplicant_init()
3881 *
3882 * This function is called to deinitialize %wpa_supplicant and to free all
3883 * allocated resources. Remaining network interfaces will also be removed.
3884 */
3885void wpa_supplicant_deinit(struct wpa_global *global)
3886{
3887 int i;
3888
3889 if (global == NULL)
3890 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003891
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003892#ifdef CONFIG_WIFI_DISPLAY
3893 wifi_display_deinit(global);
3894#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003895
3896 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003897 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003898
3899 if (global->ctrl_iface)
3900 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3901
3902 wpas_notify_supplicant_deinitialized(global);
3903
3904 eap_peer_unregister_methods();
3905#ifdef CONFIG_AP
3906 eap_server_unregister_methods();
3907#endif /* CONFIG_AP */
3908
3909 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3910 if (!global->drv_priv[i])
3911 continue;
3912 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3913 }
3914 os_free(global->drv_priv);
3915
3916 random_deinit();
3917
3918 eloop_destroy();
3919
3920 if (global->params.pid_file) {
3921 os_daemonize_terminate(global->params.pid_file);
3922 os_free(global->params.pid_file);
3923 }
3924 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003925 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003926 os_free(global->params.override_driver);
3927 os_free(global->params.override_ctrl_interface);
3928
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003929 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003930 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003931
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932 os_free(global);
3933 wpa_debug_close_syslog();
3934 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003935 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003936}
3937
3938
3939void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
3940{
3941 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
3942 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
3943 char country[3];
3944 country[0] = wpa_s->conf->country[0];
3945 country[1] = wpa_s->conf->country[1];
3946 country[2] = '\0';
3947 if (wpa_drv_set_country(wpa_s, country) < 0) {
3948 wpa_printf(MSG_ERROR, "Failed to set country code "
3949 "'%s'", country);
3950 }
3951 }
3952
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003953 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
3954 wpas_init_ext_pw(wpa_s);
3955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956#ifdef CONFIG_WPS
3957 wpas_wps_update_config(wpa_s);
3958#endif /* CONFIG_WPS */
3959
3960#ifdef CONFIG_P2P
3961 wpas_p2p_update_config(wpa_s);
3962#endif /* CONFIG_P2P */
3963
3964 wpa_s->conf->changed_parameters = 0;
3965}
3966
3967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003968static void add_freq(int *freqs, int *num_freqs, int freq)
3969{
3970 int i;
3971
3972 for (i = 0; i < *num_freqs; i++) {
3973 if (freqs[i] == freq)
3974 return;
3975 }
3976
3977 freqs[*num_freqs] = freq;
3978 (*num_freqs)++;
3979}
3980
3981
3982static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
3983{
3984 struct wpa_bss *bss, *cbss;
3985 const int max_freqs = 10;
3986 int *freqs;
3987 int num_freqs = 0;
3988
3989 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
3990 if (freqs == NULL)
3991 return NULL;
3992
3993 cbss = wpa_s->current_bss;
3994
3995 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3996 if (bss == cbss)
3997 continue;
3998 if (bss->ssid_len == cbss->ssid_len &&
3999 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4000 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4001 add_freq(freqs, &num_freqs, bss->freq);
4002 if (num_freqs == max_freqs)
4003 break;
4004 }
4005 }
4006
4007 if (num_freqs == 0) {
4008 os_free(freqs);
4009 freqs = NULL;
4010 }
4011
4012 return freqs;
4013}
4014
4015
4016void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4017{
4018 int timeout;
4019 int count;
4020 int *freqs = NULL;
4021
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004022 wpas_connect_work_done(wpa_s);
4023
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004024 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004025 * Remove possible authentication timeout since the connection failed.
4026 */
4027 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4028
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004029 if (wpa_s->disconnected) {
4030 /*
4031 * There is no point in blacklisting the AP if this event is
4032 * generated based on local request to disconnect.
4033 */
4034 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4035 "indication since interface has been put into "
4036 "disconnected state");
4037 return;
4038 }
4039
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004040 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004041 * Add the failed BSSID into the blacklist and speed up next scan
4042 * attempt if there could be other APs that could accept association.
4043 * The current blacklist count indicates how many times we have tried
4044 * connecting to this AP and multiple attempts mean that other APs are
4045 * either not available or has already been tried, so that we can start
4046 * increasing the delay here to avoid constant scanning.
4047 */
4048 count = wpa_blacklist_add(wpa_s, bssid);
4049 if (count == 1 && wpa_s->current_bss) {
4050 /*
4051 * This BSS was not in the blacklist before. If there is
4052 * another BSS available for the same ESS, we should try that
4053 * next. Otherwise, we may as well try this one once more
4054 * before allowing other, likely worse, ESSes to be considered.
4055 */
4056 freqs = get_bss_freqs_in_ess(wpa_s);
4057 if (freqs) {
4058 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4059 "has been seen; try it next");
4060 wpa_blacklist_add(wpa_s, bssid);
4061 /*
4062 * On the next scan, go through only the known channels
4063 * used in this ESS based on previous scans to speed up
4064 * common load balancing use case.
4065 */
4066 os_free(wpa_s->next_scan_freqs);
4067 wpa_s->next_scan_freqs = freqs;
4068 }
4069 }
4070
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004071 /*
4072 * Add previous failure count in case the temporary blacklist was
4073 * cleared due to no other BSSes being available.
4074 */
4075 count += wpa_s->extra_blacklist_count;
4076
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004077 if (count > 3 && wpa_s->current_ssid) {
4078 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4079 "consider temporary network disabling");
4080 wpas_auth_failed(wpa_s);
4081 }
4082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004083 switch (count) {
4084 case 1:
4085 timeout = 100;
4086 break;
4087 case 2:
4088 timeout = 500;
4089 break;
4090 case 3:
4091 timeout = 1000;
4092 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004093 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004094 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004095 break;
4096 default:
4097 timeout = 10000;
4098 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004099 }
4100
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004101 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4102 "ms", count, timeout);
4103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004104 /*
4105 * TODO: if more than one possible AP is available in scan results,
4106 * could try the other ones before requesting a new scan.
4107 */
4108 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4109 1000 * (timeout % 1000));
4110}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004111
4112
4113int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4114{
4115 return wpa_s->conf->ap_scan == 2 ||
4116 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4117}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004118
Dmitry Shmidt04949592012-07-19 12:16:46 -07004119
4120#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4121int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4122 struct wpa_ssid *ssid,
4123 const char *field,
4124 const char *value)
4125{
4126#ifdef IEEE8021X_EAPOL
4127 struct eap_peer_config *eap = &ssid->eap;
4128
4129 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4130 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4131 (const u8 *) value, os_strlen(value));
4132
4133 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4134 case WPA_CTRL_REQ_EAP_IDENTITY:
4135 os_free(eap->identity);
4136 eap->identity = (u8 *) os_strdup(value);
4137 eap->identity_len = os_strlen(value);
4138 eap->pending_req_identity = 0;
4139 if (ssid == wpa_s->current_ssid)
4140 wpa_s->reassociate = 1;
4141 break;
4142 case WPA_CTRL_REQ_EAP_PASSWORD:
4143 os_free(eap->password);
4144 eap->password = (u8 *) os_strdup(value);
4145 eap->password_len = os_strlen(value);
4146 eap->pending_req_password = 0;
4147 if (ssid == wpa_s->current_ssid)
4148 wpa_s->reassociate = 1;
4149 break;
4150 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4151 os_free(eap->new_password);
4152 eap->new_password = (u8 *) os_strdup(value);
4153 eap->new_password_len = os_strlen(value);
4154 eap->pending_req_new_password = 0;
4155 if (ssid == wpa_s->current_ssid)
4156 wpa_s->reassociate = 1;
4157 break;
4158 case WPA_CTRL_REQ_EAP_PIN:
4159 os_free(eap->pin);
4160 eap->pin = os_strdup(value);
4161 eap->pending_req_pin = 0;
4162 if (ssid == wpa_s->current_ssid)
4163 wpa_s->reassociate = 1;
4164 break;
4165 case WPA_CTRL_REQ_EAP_OTP:
4166 os_free(eap->otp);
4167 eap->otp = (u8 *) os_strdup(value);
4168 eap->otp_len = os_strlen(value);
4169 os_free(eap->pending_req_otp);
4170 eap->pending_req_otp = NULL;
4171 eap->pending_req_otp_len = 0;
4172 break;
4173 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4174 os_free(eap->private_key_passwd);
4175 eap->private_key_passwd = (u8 *) os_strdup(value);
4176 eap->pending_req_passphrase = 0;
4177 if (ssid == wpa_s->current_ssid)
4178 wpa_s->reassociate = 1;
4179 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004180 case WPA_CTRL_REQ_SIM:
4181 os_free(eap->external_sim_resp);
4182 eap->external_sim_resp = os_strdup(value);
4183 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004184 default:
4185 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4186 return -1;
4187 }
4188
4189 return 0;
4190#else /* IEEE8021X_EAPOL */
4191 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4192 return -1;
4193#endif /* IEEE8021X_EAPOL */
4194}
4195#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4196
4197
4198int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4199{
4200 int i;
4201 unsigned int drv_enc;
4202
4203 if (ssid == NULL)
4204 return 1;
4205
4206 if (ssid->disabled)
4207 return 1;
4208
4209 if (wpa_s && wpa_s->drv_capa_known)
4210 drv_enc = wpa_s->drv_enc;
4211 else
4212 drv_enc = (unsigned int) -1;
4213
4214 for (i = 0; i < NUM_WEP_KEYS; i++) {
4215 size_t len = ssid->wep_key_len[i];
4216 if (len == 0)
4217 continue;
4218 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4219 continue;
4220 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4221 continue;
4222 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4223 continue;
4224 return 1; /* invalid WEP key */
4225 }
4226
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004227 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4228 !ssid->ext_psk)
4229 return 1;
4230
Dmitry Shmidt04949592012-07-19 12:16:46 -07004231 return 0;
4232}
4233
4234
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004235int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004236{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004237 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004238 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004239 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004240 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004241 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004242}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004243
4244
4245void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4246{
4247 struct wpa_ssid *ssid = wpa_s->current_ssid;
4248 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004249 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004250
4251 if (ssid == NULL) {
4252 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4253 "SSID block");
4254 return;
4255 }
4256
4257 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4258 return;
4259
4260 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004261
4262#ifdef CONFIG_P2P
4263 if (ssid->p2p_group &&
4264 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4265 /*
4266 * Skip the wait time since there is a short timeout on the
4267 * connection to a P2P group.
4268 */
4269 return;
4270 }
4271#endif /* CONFIG_P2P */
4272
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004273 if (ssid->auth_failures > 50)
4274 dur = 300;
4275 else if (ssid->auth_failures > 20)
4276 dur = 120;
4277 else if (ssid->auth_failures > 10)
4278 dur = 60;
4279 else if (ssid->auth_failures > 5)
4280 dur = 30;
4281 else if (ssid->auth_failures > 1)
4282 dur = 20;
4283 else
4284 dur = 10;
4285
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004286 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004287 if (now.sec + dur <= ssid->disabled_until.sec)
4288 return;
4289
4290 ssid->disabled_until.sec = now.sec + dur;
4291
4292 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4293 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4294 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4295 ssid->auth_failures, dur);
4296}
4297
4298
4299void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4300 struct wpa_ssid *ssid, int clear_failures)
4301{
4302 if (ssid == NULL)
4303 return;
4304
4305 if (ssid->disabled_until.sec) {
4306 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4307 "id=%d ssid=\"%s\"",
4308 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4309 }
4310 ssid->disabled_until.sec = 0;
4311 ssid->disabled_until.usec = 0;
4312 if (clear_failures)
4313 ssid->auth_failures = 0;
4314}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004315
4316
4317int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4318{
4319 size_t i;
4320
4321 if (wpa_s->disallow_aps_bssid == NULL)
4322 return 0;
4323
4324 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4325 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4326 bssid, ETH_ALEN) == 0)
4327 return 1;
4328 }
4329
4330 return 0;
4331}
4332
4333
4334int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4335 size_t ssid_len)
4336{
4337 size_t i;
4338
4339 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4340 return 0;
4341
4342 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4343 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4344 if (ssid_len == s->ssid_len &&
4345 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4346 return 1;
4347 }
4348
4349 return 0;
4350}
4351
4352
4353/**
4354 * wpas_request_connection - Request a new connection
4355 * @wpa_s: Pointer to the network interface
4356 *
4357 * This function is used to request a new connection to be found. It will mark
4358 * the interface to allow reassociation and request a new scan to find a
4359 * suitable network to connect to.
4360 */
4361void wpas_request_connection(struct wpa_supplicant *wpa_s)
4362{
4363 wpa_s->normal_scans = 0;
4364 wpa_supplicant_reinit_autoscan(wpa_s);
4365 wpa_s->extra_blacklist_count = 0;
4366 wpa_s->disconnected = 0;
4367 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004368
4369 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4370 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004371}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004372
4373
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004374void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4375 int *freq_array, unsigned int len)
4376{
4377 unsigned int i;
4378
4379 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4380 len, title);
4381 for (i = 0; i < len; i++)
4382 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4383}
4384
4385
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004386/*
4387 * Find the operating frequencies of any of the virtual interfaces that
4388 * are using the same radio as the current interface.
4389 */
4390int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4391 int *freq_array, unsigned int len)
4392{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004393 struct wpa_supplicant *ifs;
4394 u8 bssid[ETH_ALEN];
4395 int freq;
4396 unsigned int idx = 0, i;
4397
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004398 wpa_dbg(wpa_s, MSG_DEBUG,
4399 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004400 os_memset(freq_array, 0, sizeof(int) * len);
4401
4402 /* First add the frequency of the local interface */
4403 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4404 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4405 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4406 freq_array[idx++] = wpa_s->current_ssid->frequency;
4407 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4408 freq_array[idx++] = wpa_s->assoc_freq;
4409 }
4410
4411 /* If get_radio_name is not supported, use only the local freq */
4412 if (!wpa_s->driver->get_radio_name) {
4413 freq = wpa_drv_shared_freq(wpa_s);
4414 if (freq > 0 && idx < len &&
4415 (idx == 0 || freq_array[0] != freq))
4416 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004417 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004418 return idx;
4419 }
4420
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004421 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4422 radio_list) {
4423 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004424 continue;
4425
4426 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4427 continue;
4428
4429 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4430 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4431 freq = ifs->current_ssid->frequency;
4432 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4433 freq = ifs->assoc_freq;
4434 else
4435 continue;
4436
4437 /* Hold only distinct freqs */
4438 for (i = 0; i < idx; i++)
4439 if (freq_array[i] == freq)
4440 break;
4441
4442 if (i == idx)
4443 freq_array[idx++] = freq;
4444 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004445
4446 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004447 return idx;
4448}