blob: 46195b158546c81e620238d44454633e193a9c35 [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 Shmidtf21452a2014-02-26 10:55:25 -0800486
487#ifdef CONFIG_HS20
488 hs20_free_osu_prov(wpa_s);
489#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700490}
491
492
493/**
494 * wpa_clear_keys - Clear keys configured for the driver
495 * @wpa_s: Pointer to wpa_supplicant data
496 * @addr: Previously used BSSID or %NULL if not available
497 *
498 * This function clears the encryption keys that has been previously configured
499 * for the driver.
500 */
501void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr)
502{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800503 int i, max;
504
505#ifdef CONFIG_IEEE80211W
506 max = 6;
507#else /* CONFIG_IEEE80211W */
508 max = 4;
509#endif /* CONFIG_IEEE80211W */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510
511 /* MLME-DELETEKEYS.request */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800512 for (i = 0; i < max; i++) {
513 if (wpa_s->keys_cleared & BIT(i))
514 continue;
515 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0,
516 NULL, 0);
517 }
518 if (!(wpa_s->keys_cleared & BIT(0)) && addr &&
519 !is_zero_ether_addr(addr)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520 wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL,
521 0);
522 /* MLME-SETPROTECTION.request(None) */
523 wpa_drv_mlme_setprotection(
524 wpa_s, addr,
525 MLME_SETPROTECTION_PROTECT_TYPE_NONE,
526 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
527 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800528 wpa_s->keys_cleared = (u32) -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700529}
530
531
532/**
533 * wpa_supplicant_state_txt - Get the connection state name as a text string
534 * @state: State (wpa_state; WPA_*)
535 * Returns: The state name as a printable text string
536 */
537const char * wpa_supplicant_state_txt(enum wpa_states state)
538{
539 switch (state) {
540 case WPA_DISCONNECTED:
541 return "DISCONNECTED";
542 case WPA_INACTIVE:
543 return "INACTIVE";
544 case WPA_INTERFACE_DISABLED:
545 return "INTERFACE_DISABLED";
546 case WPA_SCANNING:
547 return "SCANNING";
548 case WPA_AUTHENTICATING:
549 return "AUTHENTICATING";
550 case WPA_ASSOCIATING:
551 return "ASSOCIATING";
552 case WPA_ASSOCIATED:
553 return "ASSOCIATED";
554 case WPA_4WAY_HANDSHAKE:
555 return "4WAY_HANDSHAKE";
556 case WPA_GROUP_HANDSHAKE:
557 return "GROUP_HANDSHAKE";
558 case WPA_COMPLETED:
559 return "COMPLETED";
560 default:
561 return "UNKNOWN";
562 }
563}
564
565
566#ifdef CONFIG_BGSCAN
567
568static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s)
569{
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800570 const char *name;
571
572 if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan)
573 name = wpa_s->current_ssid->bgscan;
574 else
575 name = wpa_s->conf->bgscan;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800576 if (name == NULL || name[0] == '\0')
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800577 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800578 if (wpas_driver_bss_selection(wpa_s))
579 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580 if (wpa_s->current_ssid == wpa_s->bgscan_ssid)
581 return;
Dmitry Shmidta38abf92014-03-06 13:38:44 -0800582#ifdef CONFIG_P2P
583 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)
584 return;
585#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700586
587 bgscan_deinit(wpa_s);
Dmitry Shmidtb96dad42013-11-05 10:07:29 -0800588 if (wpa_s->current_ssid) {
589 if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
591 "bgscan");
592 /*
593 * Live without bgscan; it is only used as a roaming
594 * optimization, so the initial connection is not
595 * affected.
596 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700597 } else {
598 struct wpa_scan_results *scan_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 wpa_s->bgscan_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700600 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL,
601 0);
602 if (scan_res) {
603 bgscan_notify_scan(wpa_s, scan_res);
604 wpa_scan_results_free(scan_res);
605 }
606 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700607 } else
608 wpa_s->bgscan_ssid = NULL;
609}
610
611
612static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
613{
614 if (wpa_s->bgscan_ssid != NULL) {
615 bgscan_deinit(wpa_s);
616 wpa_s->bgscan_ssid = NULL;
617 }
618}
619
620#endif /* CONFIG_BGSCAN */
621
622
Dmitry Shmidt04949592012-07-19 12:16:46 -0700623static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s)
624{
625 if (autoscan_init(wpa_s, 0))
626 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan");
627}
628
629
630static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s)
631{
632 autoscan_deinit(wpa_s);
633}
634
635
636void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s)
637{
638 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
639 wpa_s->wpa_state == WPA_SCANNING) {
640 autoscan_deinit(wpa_s);
641 wpa_supplicant_start_autoscan(wpa_s);
642 }
643}
644
645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646/**
647 * wpa_supplicant_set_state - Set current connection state
648 * @wpa_s: Pointer to wpa_supplicant data
649 * @state: The new connection state
650 *
651 * This function is called whenever the connection state changes, e.g.,
652 * association is completed for WPA/WPA2 4-Way Handshake is started.
653 */
654void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
655 enum wpa_states state)
656{
657 enum wpa_states old_state = wpa_s->wpa_state;
658
659 wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
660 wpa_supplicant_state_txt(wpa_s->wpa_state),
661 wpa_supplicant_state_txt(state));
662
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -0800663 if (state == WPA_INTERFACE_DISABLED) {
664 /* Assure normal scan when interface is restored */
665 wpa_s->normal_scans = 0;
666 }
667
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800668 if (state == WPA_COMPLETED)
669 wpas_connect_work_done(wpa_s);
670
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671 if (state != WPA_SCANNING)
672 wpa_supplicant_notify_scanning(wpa_s, 0);
673
674 if (state == WPA_COMPLETED && wpa_s->new_connection) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700675 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt700a1372013-03-15 14:14:44 -0700676#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to "
Dmitry Shmidt8f0dbf42013-11-08 13:35:41 -0800678 MACSTR " completed [id=%d id_str=%s]",
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800679 MAC2STR(wpa_s->bssid),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680 ssid ? ssid->id : -1,
681 ssid && ssid->id_str ? ssid->id_str : "");
682#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700683 wpas_clear_temp_disabled(wpa_s, ssid, 1);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800684 wpa_s->extra_blacklist_count = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 wpa_s->new_connection = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686 wpa_drv_set_operstate(wpa_s, 1);
687#ifndef IEEE8021X_EAPOL
688 wpa_drv_set_supp_port(wpa_s, 1);
689#endif /* IEEE8021X_EAPOL */
690 wpa_s->after_wps = 0;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700691 wpa_s->known_wps_freq = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692#ifdef CONFIG_P2P
693 wpas_p2p_completed(wpa_s);
694#endif /* CONFIG_P2P */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700695
696 sme_sched_obss_scan(wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700697 } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
698 state == WPA_ASSOCIATED) {
699 wpa_s->new_connection = 1;
700 wpa_drv_set_operstate(wpa_s, 0);
701#ifndef IEEE8021X_EAPOL
702 wpa_drv_set_supp_port(wpa_s, 0);
703#endif /* IEEE8021X_EAPOL */
Dmitry Shmidt04949592012-07-19 12:16:46 -0700704 sme_sched_obss_scan(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 }
706 wpa_s->wpa_state = state;
707
708#ifdef CONFIG_BGSCAN
709 if (state == WPA_COMPLETED)
710 wpa_supplicant_start_bgscan(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800711 else if (state < WPA_ASSOCIATED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700712 wpa_supplicant_stop_bgscan(wpa_s);
713#endif /* CONFIG_BGSCAN */
714
Dmitry Shmidt04949592012-07-19 12:16:46 -0700715 if (state == WPA_AUTHENTICATING)
716 wpa_supplicant_stop_autoscan(wpa_s);
717
718 if (state == WPA_DISCONNECTED || state == WPA_INACTIVE)
719 wpa_supplicant_start_autoscan(wpa_s);
720
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721 if (wpa_s->wpa_state != old_state) {
722 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
723
724 if (wpa_s->wpa_state == WPA_COMPLETED ||
725 old_state == WPA_COMPLETED)
726 wpas_notify_auth_changed(wpa_s);
727 }
728}
729
730
731void wpa_supplicant_terminate_proc(struct wpa_global *global)
732{
733 int pending = 0;
734#ifdef CONFIG_WPS
735 struct wpa_supplicant *wpa_s = global->ifaces;
736 while (wpa_s) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800737 struct wpa_supplicant *next = wpa_s->next;
Dmitry Shmidt56052862013-10-04 10:23:25 -0700738#ifdef CONFIG_P2P
739 if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE ||
740 (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group))
741 wpas_p2p_disconnect(wpa_s);
742#endif /* CONFIG_P2P */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 if (wpas_wps_terminate_pending(wpa_s) == 1)
744 pending = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800745 wpa_s = next;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746 }
747#endif /* CONFIG_WPS */
748 if (pending)
749 return;
750 eloop_terminate();
751}
752
753
754static void wpa_supplicant_terminate(int sig, void *signal_ctx)
755{
756 struct wpa_global *global = signal_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 wpa_supplicant_terminate_proc(global);
758}
759
760
761void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
762{
763 enum wpa_states old_state = wpa_s->wpa_state;
764
765 wpa_s->pairwise_cipher = 0;
766 wpa_s->group_cipher = 0;
767 wpa_s->mgmt_group_cipher = 0;
768 wpa_s->key_mgmt = 0;
769 if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
Dmitry Shmidt04949592012-07-19 12:16:46 -0700770 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771
772 if (wpa_s->wpa_state != old_state)
773 wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
774}
775
776
777/**
778 * wpa_supplicant_reload_configuration - Reload configuration data
779 * @wpa_s: Pointer to wpa_supplicant data
780 * Returns: 0 on success or -1 if configuration parsing failed
781 *
782 * This function can be used to request that the configuration data is reloaded
783 * (e.g., after configuration file change). This function is reloading
784 * configuration only for one interface, so this may need to be called multiple
785 * times if %wpa_supplicant is controlling multiple interfaces and all
786 * interfaces need reconfiguration.
787 */
788int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
789{
790 struct wpa_config *conf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700791 int reconf_ctrl;
792 int old_ap_scan;
793
794 if (wpa_s->confname == NULL)
795 return -1;
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700796 conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 if (conf == NULL) {
798 wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration "
799 "file '%s' - exiting", wpa_s->confname);
800 return -1;
801 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -0700802 wpa_config_read(wpa_s->confanother, conf);
803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 conf->changed_parameters = (unsigned int) -1;
805
806 reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface
807 || (conf->ctrl_interface && wpa_s->conf->ctrl_interface &&
808 os_strcmp(conf->ctrl_interface,
809 wpa_s->conf->ctrl_interface) != 0);
810
811 if (reconf_ctrl && wpa_s->ctrl_iface) {
812 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
813 wpa_s->ctrl_iface = NULL;
814 }
815
816 eapol_sm_invalidate_cached_session(wpa_s->eapol);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800817 if (wpa_s->current_ssid) {
818 wpa_supplicant_deauthenticate(wpa_s,
819 WLAN_REASON_DEAUTH_LEAVING);
820 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821
822 /*
823 * TODO: should notify EAPOL SM about changes in opensc_engine_path,
824 * pkcs11_engine_path, pkcs11_module_path.
825 */
826 if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) {
827 /*
828 * Clear forced success to clear EAP state for next
829 * authentication.
830 */
831 eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
832 }
833 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
834 wpa_sm_set_config(wpa_s->wpa, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800835 wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700836 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
837 rsn_preauth_deinit(wpa_s->wpa);
838
839 old_ap_scan = wpa_s->conf->ap_scan;
840 wpa_config_free(wpa_s->conf);
841 wpa_s->conf = conf;
842 if (old_ap_scan != wpa_s->conf->ap_scan)
843 wpas_notify_ap_scan_changed(wpa_s);
844
845 if (reconf_ctrl)
846 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
847
848 wpa_supplicant_update_config(wpa_s);
849
850 wpa_supplicant_clear_status(wpa_s);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700851 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 wpa_s->reassociate = 1;
853 wpa_supplicant_req_scan(wpa_s, 0, 0);
854 }
855 wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
856 return 0;
857}
858
859
860static void wpa_supplicant_reconfig(int sig, void *signal_ctx)
861{
862 struct wpa_global *global = signal_ctx;
863 struct wpa_supplicant *wpa_s;
864 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
865 wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring",
866 sig);
867 if (wpa_supplicant_reload_configuration(wpa_s) < 0) {
868 wpa_supplicant_terminate_proc(global);
869 }
870 }
871}
872
873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s,
875 struct wpa_ssid *ssid,
876 struct wpa_ie_data *ie)
877{
878 int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie);
879 if (ret) {
880 if (ret == -2) {
881 wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE "
882 "from association info");
883 }
884 return -1;
885 }
886
887 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set "
888 "cipher suites");
889 if (!(ie->group_cipher & ssid->group_cipher)) {
890 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group "
891 "cipher 0x%x (mask 0x%x) - reject",
892 ie->group_cipher, ssid->group_cipher);
893 return -1;
894 }
895 if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) {
896 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise "
897 "cipher 0x%x (mask 0x%x) - reject",
898 ie->pairwise_cipher, ssid->pairwise_cipher);
899 return -1;
900 }
901 if (!(ie->key_mgmt & ssid->key_mgmt)) {
902 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key "
903 "management 0x%x (mask 0x%x) - reject",
904 ie->key_mgmt, ssid->key_mgmt);
905 return -1;
906 }
907
908#ifdef CONFIG_IEEE80211W
909 if (!(ie->capabilities & WPA_CAPABILITY_MFPC) &&
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800910 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
911 wpa_s->conf->pmf : ssid->ieee80211w) ==
912 MGMT_FRAME_PROTECTION_REQUIRED) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700913 wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP "
914 "that does not support management frame protection - "
915 "reject");
916 return -1;
917 }
918#endif /* CONFIG_IEEE80211W */
919
920 return 0;
921}
922
923
924/**
925 * wpa_supplicant_set_suites - Set authentication and encryption parameters
926 * @wpa_s: Pointer to wpa_supplicant data
927 * @bss: Scan results for the selected BSS, or %NULL if not available
928 * @ssid: Configuration data for the selected network
929 * @wpa_ie: Buffer for the WPA/RSN IE
930 * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the
931 * used buffer length in case the functions returns success.
932 * Returns: 0 on success or -1 on failure
933 *
934 * This function is used to configure authentication and encryption parameters
935 * based on the network configuration and scan result for the selected BSS (if
936 * available).
937 */
938int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
939 struct wpa_bss *bss, struct wpa_ssid *ssid,
940 u8 *wpa_ie, size_t *wpa_ie_len)
941{
942 struct wpa_ie_data ie;
943 int sel, proto;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800944 const u8 *bss_wpa, *bss_rsn, *bss_osen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700945
946 if (bss) {
947 bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
948 bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800949 bss_osen = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700950 } else
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800951 bss_wpa = bss_rsn = bss_osen = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700952
953 if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) &&
954 wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
955 (ie.group_cipher & ssid->group_cipher) &&
956 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
957 (ie.key_mgmt & ssid->key_mgmt)) {
958 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0");
959 proto = WPA_PROTO_RSN;
960 } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) &&
961 wpa_parse_wpa_ie(bss_wpa, 2 +bss_wpa[1], &ie) == 0 &&
962 (ie.group_cipher & ssid->group_cipher) &&
963 (ie.pairwise_cipher & ssid->pairwise_cipher) &&
964 (ie.key_mgmt & ssid->key_mgmt)) {
965 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
966 proto = WPA_PROTO_WPA;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800967#ifdef CONFIG_HS20
968 } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
969 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
970 /* TODO: parse OSEN element */
971 ie.group_cipher = WPA_CIPHER_CCMP;
972 ie.pairwise_cipher = WPA_CIPHER_CCMP;
973 ie.key_mgmt = WPA_KEY_MGMT_OSEN;
974 proto = WPA_PROTO_OSEN;
975#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976 } else if (bss) {
977 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN");
978 return -1;
979 } else {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800980 if (ssid->proto & WPA_PROTO_OSEN)
981 proto = WPA_PROTO_OSEN;
982 else if (ssid->proto & WPA_PROTO_RSN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983 proto = WPA_PROTO_RSN;
984 else
985 proto = WPA_PROTO_WPA;
986 if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) {
987 os_memset(&ie, 0, sizeof(ie));
988 ie.group_cipher = ssid->group_cipher;
989 ie.pairwise_cipher = ssid->pairwise_cipher;
990 ie.key_mgmt = ssid->key_mgmt;
991#ifdef CONFIG_IEEE80211W
992 ie.mgmt_group_cipher =
993 ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ?
994 WPA_CIPHER_AES_128_CMAC : 0;
995#endif /* CONFIG_IEEE80211W */
996 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
997 "based on configuration");
998 } else
999 proto = ie.proto;
1000 }
1001
1002 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d "
1003 "pairwise %d key_mgmt %d proto %d",
1004 ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto);
1005#ifdef CONFIG_IEEE80211W
1006 if (ssid->ieee80211w) {
1007 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d",
1008 ie.mgmt_group_cipher);
1009 }
1010#endif /* CONFIG_IEEE80211W */
1011
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001012 wpa_s->wpa_proto = proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto);
1014 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001015 !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016
1017 if (bss || !wpa_s->ap_ies_from_associnfo) {
1018 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa,
1019 bss_wpa ? 2 + bss_wpa[1] : 0) ||
1020 wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn,
1021 bss_rsn ? 2 + bss_rsn[1] : 0))
1022 return -1;
1023 }
1024
1025 sel = ie.group_cipher & ssid->group_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001026 wpa_s->group_cipher = wpa_pick_group_cipher(sel);
1027 if (wpa_s->group_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001028 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group "
1029 "cipher");
1030 return -1;
1031 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001032 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
1033 wpa_cipher_txt(wpa_s->group_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034
1035 sel = ie.pairwise_cipher & ssid->pairwise_cipher;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001036 wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
1037 if (wpa_s->pairwise_cipher < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001038 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise "
1039 "cipher");
1040 return -1;
1041 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001042 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
1043 wpa_cipher_txt(wpa_s->pairwise_cipher));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001044
1045 sel = ie.key_mgmt & ssid->key_mgmt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001046#ifdef CONFIG_SAE
1047 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE))
1048 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE);
1049#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050 if (0) {
1051#ifdef CONFIG_IEEE80211R
1052 } else if (sel & WPA_KEY_MGMT_FT_IEEE8021X) {
1053 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
1054 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/802.1X");
1055 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
1056 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_PSK;
1057 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT FT/PSK");
1058#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001059#ifdef CONFIG_SAE
1060 } else if (sel & WPA_KEY_MGMT_SAE) {
1061 wpa_s->key_mgmt = WPA_KEY_MGMT_SAE;
1062 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE");
1063 } else if (sel & WPA_KEY_MGMT_FT_SAE) {
1064 wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE;
1065 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE");
1066#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001067#ifdef CONFIG_IEEE80211W
1068 } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) {
1069 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
1070 wpa_dbg(wpa_s, MSG_DEBUG,
1071 "WPA: using KEY_MGMT 802.1X with SHA256");
1072 } else if (sel & WPA_KEY_MGMT_PSK_SHA256) {
1073 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
1074 wpa_dbg(wpa_s, MSG_DEBUG,
1075 "WPA: using KEY_MGMT PSK with SHA256");
1076#endif /* CONFIG_IEEE80211W */
1077 } else if (sel & WPA_KEY_MGMT_IEEE8021X) {
1078 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X;
1079 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X");
1080 } else if (sel & WPA_KEY_MGMT_PSK) {
1081 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK;
1082 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK");
1083 } else if (sel & WPA_KEY_MGMT_WPA_NONE) {
1084 wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE;
1085 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE");
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001086#ifdef CONFIG_HS20
1087 } else if (sel & WPA_KEY_MGMT_OSEN) {
1088 wpa_s->key_mgmt = WPA_KEY_MGMT_OSEN;
1089 wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using KEY_MGMT OSEN");
1090#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091 } else {
1092 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select "
1093 "authenticated key management type");
1094 return -1;
1095 }
1096
1097 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
1098 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
1099 wpa_s->pairwise_cipher);
1100 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
1101
1102#ifdef CONFIG_IEEE80211W
1103 sel = ie.mgmt_group_cipher;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001104 if ((ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1105 wpa_s->conf->pmf : ssid->ieee80211w) == NO_MGMT_FRAME_PROTECTION ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001106 !(ie.capabilities & WPA_CAPABILITY_MFPC))
1107 sel = 0;
1108 if (sel & WPA_CIPHER_AES_128_CMAC) {
1109 wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
1110 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
1111 "AES-128-CMAC");
1112 } else {
1113 wpa_s->mgmt_group_cipher = 0;
1114 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
1115 }
1116 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
1117 wpa_s->mgmt_group_cipher);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001118 wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
1119 (ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1120 wpa_s->conf->pmf : ssid->ieee80211w));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001121#endif /* CONFIG_IEEE80211W */
1122
1123 if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) {
1124 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE");
1125 return -1;
1126 }
1127
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001128 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001129 wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001130#ifndef CONFIG_NO_PBKDF2
1131 if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
1132 ssid->passphrase) {
1133 u8 psk[PMK_LEN];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001134 pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len,
1135 4096, psk, PMK_LEN);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001136 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
1137 psk, PMK_LEN);
1138 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1139 }
1140#endif /* CONFIG_NO_PBKDF2 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001141#ifdef CONFIG_EXT_PASSWORD
1142 if (ssid->ext_psk) {
1143 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
1144 ssid->ext_psk);
1145 char pw_str[64 + 1];
1146 u8 psk[PMK_LEN];
1147
1148 if (pw == NULL) {
1149 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No PSK "
1150 "found from external storage");
1151 return -1;
1152 }
1153
1154 if (wpabuf_len(pw) < 8 || wpabuf_len(pw) > 64) {
1155 wpa_msg(wpa_s, MSG_INFO, "EXT PW: Unexpected "
1156 "PSK length %d in external storage",
1157 (int) wpabuf_len(pw));
1158 ext_password_free(pw);
1159 return -1;
1160 }
1161
1162 os_memcpy(pw_str, wpabuf_head(pw), wpabuf_len(pw));
1163 pw_str[wpabuf_len(pw)] = '\0';
1164
1165#ifndef CONFIG_NO_PBKDF2
1166 if (wpabuf_len(pw) >= 8 && wpabuf_len(pw) < 64 && bss)
1167 {
1168 pbkdf2_sha1(pw_str, bss->ssid, bss->ssid_len,
1169 4096, psk, PMK_LEN);
1170 os_memset(pw_str, 0, sizeof(pw_str));
1171 wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
1172 "external passphrase)",
1173 psk, PMK_LEN);
1174 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1175 } else
1176#endif /* CONFIG_NO_PBKDF2 */
1177 if (wpabuf_len(pw) == 2 * PMK_LEN) {
1178 if (hexstr2bin(pw_str, psk, PMK_LEN) < 0) {
1179 wpa_msg(wpa_s, MSG_INFO, "EXT PW: "
1180 "Invalid PSK hex string");
1181 os_memset(pw_str, 0, sizeof(pw_str));
1182 ext_password_free(pw);
1183 return -1;
1184 }
1185 wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
1186 } else {
1187 wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
1188 "PSK available");
1189 os_memset(pw_str, 0, sizeof(pw_str));
1190 ext_password_free(pw);
1191 return -1;
1192 }
1193
1194 os_memset(pw_str, 0, sizeof(pw_str));
1195 ext_password_free(pw);
1196 }
1197#endif /* CONFIG_EXT_PASSWORD */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001198 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1200
1201 return 0;
1202}
1203
1204
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001205static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
1206{
1207 *pos = 0x00;
1208
1209 switch (idx) {
1210 case 0: /* Bits 0-7 */
1211 break;
1212 case 1: /* Bits 8-15 */
1213 break;
1214 case 2: /* Bits 16-23 */
1215#ifdef CONFIG_WNM
1216 *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
1217 *pos |= 0x08; /* Bit 19 - BSS Transition */
1218#endif /* CONFIG_WNM */
1219 break;
1220 case 3: /* Bits 24-31 */
1221#ifdef CONFIG_WNM
1222 *pos |= 0x02; /* Bit 25 - SSID List */
1223#endif /* CONFIG_WNM */
1224#ifdef CONFIG_INTERWORKING
1225 if (wpa_s->conf->interworking)
1226 *pos |= 0x80; /* Bit 31 - Interworking */
1227#endif /* CONFIG_INTERWORKING */
1228 break;
1229 case 4: /* Bits 32-39 */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001230#ifdef CONFIG_INTERWORKING
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001231 if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING)
1232 *pos |= 0x01; /* Bit 32 - QoS Map */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001233#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001234 break;
1235 case 5: /* Bits 40-47 */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001236#ifdef CONFIG_HS20
1237 if (wpa_s->conf->hs20)
1238 *pos |= 0x40; /* Bit 46 - WNM-Notification */
1239#endif /* CONFIG_HS20 */
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001240 break;
1241 case 6: /* Bits 48-55 */
1242 break;
1243 }
1244}
1245
1246
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001247int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf)
1248{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001249 u8 *pos = buf;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001250 u8 len = 6, i;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001251
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001252 if (len < wpa_s->extended_capa_len)
1253 len = wpa_s->extended_capa_len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001254
1255 *pos++ = WLAN_EID_EXT_CAPAB;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001256 *pos++ = len;
1257 for (i = 0; i < len; i++, pos++) {
1258 wpas_ext_capab_byte(wpa_s, pos, i);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001259
Dmitry Shmidt444d5672013-04-01 13:08:44 -07001260 if (i < wpa_s->extended_capa_len) {
1261 *pos &= ~wpa_s->extended_capa_mask[i];
1262 *pos |= wpa_s->extended_capa[i];
1263 }
1264 }
1265
1266 while (len > 0 && buf[1 + len] == 0) {
1267 len--;
1268 buf[1] = len;
1269 }
1270 if (len == 0)
1271 return 0;
1272
1273 return 2 + len;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001274}
1275
1276
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001277static int wpas_valid_bss(struct wpa_supplicant *wpa_s,
1278 struct wpa_bss *test_bss)
1279{
1280 struct wpa_bss *bss;
1281
1282 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1283 if (bss == test_bss)
1284 return 1;
1285 }
1286
1287 return 0;
1288}
1289
1290
1291static int wpas_valid_ssid(struct wpa_supplicant *wpa_s,
1292 struct wpa_ssid *test_ssid)
1293{
1294 struct wpa_ssid *ssid;
1295
1296 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1297 if (ssid == test_ssid)
1298 return 1;
1299 }
1300
1301 return 0;
1302}
1303
1304
1305int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss,
1306 struct wpa_ssid *test_ssid)
1307{
1308 if (test_bss && !wpas_valid_bss(wpa_s, test_bss))
1309 return 0;
1310
1311 return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid);
1312}
1313
1314
1315void wpas_connect_work_free(struct wpa_connect_work *cwork)
1316{
1317 if (cwork == NULL)
1318 return;
1319 os_free(cwork);
1320}
1321
1322
1323void wpas_connect_work_done(struct wpa_supplicant *wpa_s)
1324{
1325 struct wpa_connect_work *cwork;
1326 struct wpa_radio_work *work = wpa_s->connect_work;
1327
1328 if (!work)
1329 return;
1330
1331 wpa_s->connect_work = NULL;
1332 cwork = work->ctx;
1333 work->ctx = NULL;
1334 wpas_connect_work_free(cwork);
1335 radio_work_done(work);
1336}
1337
1338
1339static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
1340
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341/**
1342 * wpa_supplicant_associate - Request association
1343 * @wpa_s: Pointer to wpa_supplicant data
1344 * @bss: Scan results for the selected BSS, or %NULL if not available
1345 * @ssid: Configuration data for the selected network
1346 *
1347 * This function is used to request %wpa_supplicant to associate with a BSS.
1348 */
1349void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
1350 struct wpa_bss *bss, struct wpa_ssid *ssid)
1351{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001352 struct wpa_connect_work *cwork;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353
1354#ifdef CONFIG_IBSS_RSN
1355 ibss_rsn_deinit(wpa_s->ibss_rsn);
1356 wpa_s->ibss_rsn = NULL;
1357#endif /* CONFIG_IBSS_RSN */
1358
1359 if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO ||
1360 ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
1361#ifdef CONFIG_AP
1362 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) {
1363 wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP "
1364 "mode");
1365 return;
1366 }
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001367 if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) {
1368 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001369 if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION)
1370 wpas_p2p_ap_setup_failed(wpa_s);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07001371 return;
1372 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373 wpa_s->current_bss = bss;
1374#else /* CONFIG_AP */
1375 wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in "
1376 "the build");
1377#endif /* CONFIG_AP */
1378 return;
1379 }
1380
1381#ifdef CONFIG_TDLS
1382 if (bss)
1383 wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1),
1384 bss->ie_len);
1385#endif /* CONFIG_TDLS */
1386
1387 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
1388 ssid->mode == IEEE80211_MODE_INFRA) {
1389 sme_authenticate(wpa_s, bss, ssid);
1390 return;
1391 }
1392
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001393 if (wpa_s->connect_work) {
1394 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist");
1395 return;
1396 }
1397
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001398 if (radio_work_pending(wpa_s, "connect")) {
1399 wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist");
1400 return;
1401 }
1402
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001403 cwork = os_zalloc(sizeof(*cwork));
1404 if (cwork == NULL)
1405 return;
1406
1407 cwork->bss = bss;
1408 cwork->ssid = ssid;
1409
1410 if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1,
1411 wpas_start_assoc_cb, cwork) < 0) {
1412 os_free(cwork);
1413 }
1414}
1415
1416
1417static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
1418{
1419 struct wpa_connect_work *cwork = work->ctx;
1420 struct wpa_bss *bss = cwork->bss;
1421 struct wpa_ssid *ssid = cwork->ssid;
1422 struct wpa_supplicant *wpa_s = work->wpa_s;
1423 u8 wpa_ie[200];
1424 size_t wpa_ie_len;
1425 int use_crypt, ret, i, bssid_changed;
1426 int algs = WPA_AUTH_ALG_OPEN;
1427 unsigned int cipher_pairwise, cipher_group;
1428 struct wpa_driver_associate_params params;
1429 int wep_keys_set = 0;
1430 int assoc_failed = 0;
1431 struct wpa_ssid *old_ssid;
1432#ifdef CONFIG_HT_OVERRIDES
1433 struct ieee80211_ht_capabilities htcaps;
1434 struct ieee80211_ht_capabilities htcaps_mask;
1435#endif /* CONFIG_HT_OVERRIDES */
1436
1437 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001438 if (work->started) {
1439 wpa_s->connect_work = NULL;
1440
1441 /* cancel possible auth. timeout */
1442 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s,
1443 NULL);
1444 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001445 wpas_connect_work_free(cwork);
1446 return;
1447 }
1448
1449 wpa_s->connect_work = work;
1450
1451 if (!wpas_valid_bss_ssid(wpa_s, bss, ssid)) {
1452 wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt");
1453 wpas_connect_work_done(wpa_s);
1454 return;
1455 }
1456
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001457 os_memset(&params, 0, sizeof(params));
1458 wpa_s->reassociate = 0;
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001459 wpa_s->eap_expected_failure = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001460 if (bss && !wpas_driver_bss_selection(wpa_s)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461#ifdef CONFIG_IEEE80211R
1462 const u8 *ie, *md = NULL;
1463#endif /* CONFIG_IEEE80211R */
1464 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1465 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid),
1466 wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq);
1467 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1468 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1469 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1470 if (bssid_changed)
1471 wpas_notify_bssid_changed(wpa_s);
1472#ifdef CONFIG_IEEE80211R
1473 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
1474 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
1475 md = ie + 2;
1476 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
1477 if (md) {
1478 /* Prepare for the next transition */
1479 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
1480 }
1481#endif /* CONFIG_IEEE80211R */
1482#ifdef CONFIG_WPS
1483 } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) &&
1484 wpa_s->conf->ap_scan == 2 &&
1485 (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) {
1486 /* Use ap_scan==1 style network selection to find the network
1487 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001488 wpa_s->scan_req = MANUAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001489 wpa_s->reassociate = 1;
1490 wpa_supplicant_req_scan(wpa_s, 0, 0);
1491 return;
1492#endif /* CONFIG_WPS */
1493 } else {
1494 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'",
1495 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
1496 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1497 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001498 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001499 wpa_supplicant_cancel_scan(wpa_s);
1500
1501 /* Starting new association, so clear the possibly used WPA IE from the
1502 * previous association. */
1503 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1504
1505#ifdef IEEE8021X_EAPOL
1506 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1507 if (ssid->leap) {
1508 if (ssid->non_leap == 0)
1509 algs = WPA_AUTH_ALG_LEAP;
1510 else
1511 algs |= WPA_AUTH_ALG_LEAP;
1512 }
1513 }
1514#endif /* IEEE8021X_EAPOL */
1515 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
1516 if (ssid->auth_alg) {
1517 algs = ssid->auth_alg;
1518 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
1519 "0x%x", algs);
1520 }
1521
1522 if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
1523 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001524 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525 int try_opportunistic;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001526 try_opportunistic = (ssid->proactive_key_caching < 0 ?
1527 wpa_s->conf->okc :
1528 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529 (ssid->proto & WPA_PROTO_RSN);
1530 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07001531 ssid, try_opportunistic) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001532 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1);
1533 wpa_ie_len = sizeof(wpa_ie);
1534 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
1535 wpa_ie, &wpa_ie_len)) {
1536 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1537 "key management and encryption suites");
1538 return;
1539 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001540 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
1541 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
1542 /*
1543 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
1544 * use non-WPA since the scan results did not indicate that the
1545 * AP is using WPA or WPA2.
1546 */
1547 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1548 wpa_ie_len = 0;
1549 wpa_s->wpa_proto = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001550 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001551 wpa_ie_len = sizeof(wpa_ie);
1552 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
1553 wpa_ie, &wpa_ie_len)) {
1554 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
1555 "key management and encryption suites (no "
1556 "scan results)");
1557 return;
1558 }
1559#ifdef CONFIG_WPS
1560 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
1561 struct wpabuf *wps_ie;
1562 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
1563 if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) {
1564 wpa_ie_len = wpabuf_len(wps_ie);
1565 os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len);
1566 } else
1567 wpa_ie_len = 0;
1568 wpabuf_free(wps_ie);
1569 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1570 if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY))
1571 params.wps = WPS_MODE_PRIVACY;
1572 else
1573 params.wps = WPS_MODE_OPEN;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001574 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575#endif /* CONFIG_WPS */
1576 } else {
1577 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
1578 wpa_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001579 wpa_s->wpa_proto = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580 }
1581
1582#ifdef CONFIG_P2P
1583 if (wpa_s->global->p2p) {
1584 u8 *pos;
1585 size_t len;
1586 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001587 pos = wpa_ie + wpa_ie_len;
1588 len = sizeof(wpa_ie) - wpa_ie_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001589 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
1590 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001591 if (res >= 0)
1592 wpa_ie_len += res;
1593 }
1594
1595 wpa_s->cross_connect_disallowed = 0;
1596 if (bss) {
1597 struct wpabuf *p2p;
1598 p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE);
1599 if (p2p) {
1600 wpa_s->cross_connect_disallowed =
1601 p2p_get_cross_connect_disallowed(p2p);
1602 wpabuf_free(p2p);
1603 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross "
1604 "connection",
1605 wpa_s->cross_connect_disallowed ?
1606 "disallows" : "allows");
1607 }
1608 }
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001609
1610 os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611#endif /* CONFIG_P2P */
1612
Dmitry Shmidt04949592012-07-19 12:16:46 -07001613#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001614 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001615 struct wpabuf *hs20;
1616 hs20 = wpabuf_alloc(20);
1617 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001618 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
1619 wpas_hs20_add_indication(hs20, pps_mo_id);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001620 os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20),
1621 wpabuf_len(hs20));
1622 wpa_ie_len += wpabuf_len(hs20);
1623 wpabuf_free(hs20);
1624 }
1625 }
1626#endif /* CONFIG_HS20 */
1627
Dmitry Shmidt56052862013-10-04 10:23:25 -07001628 /*
1629 * Workaround: Add Extended Capabilities element only if the AP
1630 * included this element in Beacon/Probe Response frames. Some older
1631 * APs seem to have interoperability issues if this element is
1632 * included, so while the standard may require us to include the
1633 * element in all cases, it is justifiable to skip it to avoid
1634 * interoperability issues.
1635 */
1636 if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) {
1637 u8 ext_capab[10];
1638 int ext_capab_len;
1639 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab);
1640 if (ext_capab_len > 0) {
1641 u8 *pos = wpa_ie;
1642 if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN)
1643 pos += 2 + pos[1];
1644 os_memmove(pos + ext_capab_len, pos,
1645 wpa_ie_len - (pos - wpa_ie));
1646 wpa_ie_len += ext_capab_len;
1647 os_memcpy(pos, ext_capab, ext_capab_len);
1648 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001649 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001650
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001651 wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
1652 use_crypt = 1;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001653 cipher_pairwise = wpa_s->pairwise_cipher;
1654 cipher_group = wpa_s->group_cipher;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE ||
1656 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1657 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE)
1658 use_crypt = 0;
1659 if (wpa_set_wep_keys(wpa_s, ssid)) {
1660 use_crypt = 1;
1661 wep_keys_set = 1;
1662 }
1663 }
1664 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)
1665 use_crypt = 0;
1666
1667#ifdef IEEE8021X_EAPOL
1668 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
1669 if ((ssid->eapol_flags &
1670 (EAPOL_FLAG_REQUIRE_KEY_UNICAST |
1671 EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 &&
1672 !wep_keys_set) {
1673 use_crypt = 0;
1674 } else {
1675 /* Assume that dynamic WEP-104 keys will be used and
1676 * set cipher suites in order for drivers to expect
1677 * encryption. */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001678 cipher_pairwise = cipher_group = WPA_CIPHER_WEP104;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679 }
1680 }
1681#endif /* IEEE8021X_EAPOL */
1682
1683 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1684 /* Set the key before (and later after) association */
1685 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1686 }
1687
1688 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1689 if (bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 params.ssid = bss->ssid;
1691 params.ssid_len = bss->ssid_len;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001692 if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) {
1693 wpa_printf(MSG_DEBUG, "Limit connection to BSSID "
1694 MACSTR " freq=%u MHz based on scan results "
1695 "(bssid_set=%d)",
1696 MAC2STR(bss->bssid), bss->freq,
1697 ssid->bssid_set);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001698 params.bssid = bss->bssid;
1699 params.freq = bss->freq;
1700 }
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001701 params.bssid_hint = bss->bssid;
1702 params.freq_hint = bss->freq;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703 } else {
1704 params.ssid = ssid->ssid;
1705 params.ssid_len = ssid->ssid_len;
1706 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001707
1708 if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set &&
1709 wpa_s->conf->ap_scan == 2) {
1710 params.bssid = ssid->bssid;
1711 params.fixed_bssid = 1;
1712 }
1713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714 if (ssid->mode == WPAS_MODE_IBSS && ssid->frequency > 0 &&
1715 params.freq == 0)
1716 params.freq = ssid->frequency; /* Initial channel for IBSS */
1717 params.wpa_ie = wpa_ie;
1718 params.wpa_ie_len = wpa_ie_len;
1719 params.pairwise_suite = cipher_pairwise;
1720 params.group_suite = cipher_group;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001721 params.key_mgmt_suite = wpa_s->key_mgmt;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001722 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723 params.auth_alg = algs;
1724 params.mode = ssid->mode;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001725 params.bg_scan_period = ssid->bg_scan_period;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726 for (i = 0; i < NUM_WEP_KEYS; i++) {
1727 if (ssid->wep_key_len[i])
1728 params.wep_key[i] = ssid->wep_key[i];
1729 params.wep_key_len[i] = ssid->wep_key_len[i];
1730 }
1731 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
1732
1733 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001734 (params.key_mgmt_suite == WPA_KEY_MGMT_PSK ||
1735 params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736 params.passphrase = ssid->passphrase;
1737 if (ssid->psk_set)
1738 params.psk = ssid->psk;
1739 }
1740
1741 params.drop_unencrypted = use_crypt;
1742
1743#ifdef CONFIG_IEEE80211W
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001744 params.mgmt_frame_protection =
1745 ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ?
1746 wpa_s->conf->pmf : ssid->ieee80211w;
1747 if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001748 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1749 struct wpa_ie_data ie;
1750 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 &&
1751 ie.capabilities &
1752 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
1753 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports "
1754 "MFP: require MFP");
1755 params.mgmt_frame_protection =
1756 MGMT_FRAME_PROTECTION_REQUIRED;
1757 }
1758 }
1759#endif /* CONFIG_IEEE80211W */
1760
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001761 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762
1763 if (wpa_s->parent->set_sta_uapsd)
1764 params.uapsd = wpa_s->parent->sta_uapsd;
1765 else
1766 params.uapsd = -1;
1767
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001768#ifdef CONFIG_HT_OVERRIDES
1769 os_memset(&htcaps, 0, sizeof(htcaps));
1770 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1771 params.htcaps = (u8 *) &htcaps;
1772 params.htcaps_mask = (u8 *) &htcaps_mask;
1773 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
1774#endif /* CONFIG_HT_OVERRIDES */
1775
Dmitry Shmidt04f534e2013-12-09 15:50:16 -08001776#ifdef CONFIG_P2P
1777 /*
1778 * If multi-channel concurrency is not supported, check for any
1779 * frequency conflict. In case of any frequency conflict, remove the
1780 * least prioritized connection.
1781 */
1782 if (wpa_s->num_multichan_concurrent < 2) {
1783 int freq = wpa_drv_shared_freq(wpa_s);
1784 if (freq > 0 && freq != params.freq) {
1785 wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)",
1786 freq, params.freq);
1787 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1788 params.freq,
1789 ssid) < 0)
1790 return;
1791 }
1792 }
1793#endif /* CONFIG_P2P */
1794
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001795 ret = wpa_drv_associate(wpa_s, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796 if (ret < 0) {
1797 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
1798 "failed");
1799 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) {
1800 /*
1801 * The driver is known to mean what is saying, so we
1802 * can stop right here; the association will not
1803 * succeed.
1804 */
1805 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001806 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1808 return;
1809 }
1810 /* try to continue anyway; new association will be tried again
1811 * after timeout */
1812 assoc_failed = 1;
1813 }
1814
1815 if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) {
1816 /* Set the key after the association just in case association
1817 * cleared the previously configured key. */
1818 wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
1819 /* No need to timeout authentication since there is no key
1820 * management. */
1821 wpa_supplicant_cancel_auth_timeout(wpa_s);
1822 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
1823#ifdef CONFIG_IBSS_RSN
1824 } else if (ssid->mode == WPAS_MODE_IBSS &&
1825 wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
1826 wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) {
1827 /*
1828 * RSN IBSS authentication is per-STA and we can disable the
1829 * per-BSSID authentication.
1830 */
1831 wpa_supplicant_cancel_auth_timeout(wpa_s);
1832#endif /* CONFIG_IBSS_RSN */
1833 } else {
1834 /* Timeout for IEEE 802.11 authentication and association */
1835 int timeout = 60;
1836
1837 if (assoc_failed) {
1838 /* give IBSS a bit more time */
1839 timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5;
1840 } else if (wpa_s->conf->ap_scan == 1) {
1841 /* give IBSS a bit more time */
1842 timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10;
1843 }
1844 wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
1845 }
1846
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001847 if (wep_keys_set &&
1848 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849 /* Set static WEP keys again */
1850 wpa_set_wep_keys(wpa_s, ssid);
1851 }
1852
1853 if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) {
1854 /*
1855 * Do not allow EAP session resumption between different
1856 * network configurations.
1857 */
1858 eapol_sm_invalidate_cached_session(wpa_s->eapol);
1859 }
1860 old_ssid = wpa_s->current_ssid;
1861 wpa_s->current_ssid = ssid;
1862 wpa_s->current_bss = bss;
1863 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1864 wpa_supplicant_initiate_eapol(wpa_s);
1865 if (old_ssid != wpa_s->current_ssid)
1866 wpas_notify_network_changed(wpa_s);
1867}
1868
1869
1870static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
1871 const u8 *addr)
1872{
1873 struct wpa_ssid *old_ssid;
1874
1875 wpa_clear_keys(wpa_s, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 old_ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001877 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878 wpa_sm_set_config(wpa_s->wpa, NULL);
1879 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
1880 if (old_ssid != wpa_s->current_ssid)
1881 wpas_notify_network_changed(wpa_s);
1882 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
1883}
1884
1885
1886/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001887 * wpa_supplicant_deauthenticate - Deauthenticate the current connection
1888 * @wpa_s: Pointer to wpa_supplicant data
1889 * @reason_code: IEEE 802.11 reason code for the deauthenticate frame
1890 *
1891 * This function is used to request %wpa_supplicant to deauthenticate from the
1892 * current AP.
1893 */
1894void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
1895 int reason_code)
1896{
1897 u8 *addr = NULL;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001898 union wpa_event_data event;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001899 int zero_addr = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001901 wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR
1902 " pending_bssid=" MACSTR " reason=%d state=%s",
1903 MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid),
1904 reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state));
1905
1906 if (!is_zero_ether_addr(wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907 addr = wpa_s->bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001908 else if (!is_zero_ether_addr(wpa_s->pending_bssid) &&
1909 (wpa_s->wpa_state == WPA_AUTHENTICATING ||
1910 wpa_s->wpa_state == WPA_ASSOCIATING))
1911 addr = wpa_s->pending_bssid;
1912 else if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1913 /*
1914 * When using driver-based BSS selection, we may not know the
1915 * BSSID with which we are currently trying to associate. We
1916 * need to notify the driver of this disconnection even in such
1917 * a case, so use the all zeros address here.
1918 */
1919 addr = wpa_s->bssid;
1920 zero_addr = 1;
1921 }
1922
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001923#ifdef CONFIG_TDLS
1924 wpa_tdls_teardown_peers(wpa_s->wpa);
1925#endif /* CONFIG_TDLS */
1926
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001927 if (addr) {
1928 wpa_drv_deauthenticate(wpa_s, addr, reason_code);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001929 os_memset(&event, 0, sizeof(event));
1930 event.deauth_info.reason_code = (u16) reason_code;
1931 event.deauth_info.locally_generated = 1;
1932 wpa_supplicant_event(wpa_s, EVENT_DEAUTH, &event);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001933 if (zero_addr)
1934 addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001935 }
1936
1937 wpa_supplicant_clear_connection(wpa_s, addr);
1938}
1939
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001940static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
1941 struct wpa_ssid *ssid)
1942{
1943 if (!ssid || !ssid->disabled || ssid->disabled == 2)
1944 return;
1945
1946 ssid->disabled = 0;
1947 wpas_clear_temp_disabled(wpa_s, ssid, 1);
1948 wpas_notify_network_enabled_changed(wpa_s, ssid);
1949
1950 /*
1951 * Try to reassociate since there is no current configuration and a new
1952 * network was made available.
1953 */
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001954 if (!wpa_s->current_ssid && !wpa_s->disconnected)
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001955 wpa_s->reassociate = 1;
1956}
1957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958
1959/**
1960 * wpa_supplicant_enable_network - Mark a configured network as enabled
1961 * @wpa_s: wpa_supplicant structure for a network interface
1962 * @ssid: wpa_ssid structure for a configured network or %NULL
1963 *
1964 * Enables the specified network or all networks if no network specified.
1965 */
1966void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s,
1967 struct wpa_ssid *ssid)
1968{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001970 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
1971 wpa_supplicant_enable_one_network(wpa_s, ssid);
1972 } else
1973 wpa_supplicant_enable_one_network(wpa_s, ssid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07001975 if (wpa_s->reassociate && !wpa_s->disconnected) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001976 if (wpa_s->sched_scanning) {
1977 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add "
1978 "new network to scan filters");
1979 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980 }
1981
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001982 if (wpa_supplicant_fast_associate(wpa_s) != 1)
1983 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 }
1985}
1986
1987
1988/**
1989 * wpa_supplicant_disable_network - Mark a configured network as disabled
1990 * @wpa_s: wpa_supplicant structure for a network interface
1991 * @ssid: wpa_ssid structure for a configured network or %NULL
1992 *
1993 * Disables the specified network or all networks if no network specified.
1994 */
1995void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s,
1996 struct wpa_ssid *ssid)
1997{
1998 struct wpa_ssid *other_ssid;
1999 int was_disabled;
2000
2001 if (ssid == NULL) {
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002002 if (wpa_s->sched_scanning)
2003 wpa_supplicant_cancel_sched_scan(wpa_s);
2004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2006 other_ssid = other_ssid->next) {
2007 was_disabled = other_ssid->disabled;
2008 if (was_disabled == 2)
2009 continue; /* do not change persistent P2P group
2010 * data */
2011
2012 other_ssid->disabled = 1;
2013
2014 if (was_disabled != other_ssid->disabled)
2015 wpas_notify_network_enabled_changed(
2016 wpa_s, other_ssid);
2017 }
2018 if (wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002019 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2021 } else if (ssid->disabled != 2) {
2022 if (ssid == wpa_s->current_ssid)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002023 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
2025
2026 was_disabled = ssid->disabled;
2027
2028 ssid->disabled = 1;
2029
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002030 if (was_disabled != ssid->disabled) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031 wpas_notify_network_enabled_changed(wpa_s, ssid);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002032 if (wpa_s->sched_scanning) {
2033 wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan "
2034 "to remove network from filters");
2035 wpa_supplicant_cancel_sched_scan(wpa_s);
2036 wpa_supplicant_req_scan(wpa_s, 0, 0);
2037 }
2038 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039 }
2040}
2041
2042
2043/**
2044 * wpa_supplicant_select_network - Attempt association with a network
2045 * @wpa_s: wpa_supplicant structure for a network interface
2046 * @ssid: wpa_ssid structure for a configured network or %NULL for any network
2047 */
2048void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
2049 struct wpa_ssid *ssid)
2050{
2051
2052 struct wpa_ssid *other_ssid;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002053 int disconnected = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002055 if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002056 wpa_supplicant_deauthenticate(
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002058 disconnected = 1;
2059 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002061 if (ssid)
2062 wpas_clear_temp_disabled(wpa_s, ssid, 1);
2063
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 /*
2065 * Mark all other networks disabled or mark all networks enabled if no
2066 * network specified.
2067 */
2068 for (other_ssid = wpa_s->conf->ssid; other_ssid;
2069 other_ssid = other_ssid->next) {
2070 int was_disabled = other_ssid->disabled;
2071 if (was_disabled == 2)
2072 continue; /* do not change persistent P2P group data */
2073
2074 other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002075 if (was_disabled && !other_ssid->disabled)
2076 wpas_clear_temp_disabled(wpa_s, other_ssid, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077
2078 if (was_disabled != other_ssid->disabled)
2079 wpas_notify_network_enabled_changed(wpa_s, other_ssid);
2080 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002081
2082 if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) {
2083 /* We are already associated with the selected network */
2084 wpa_printf(MSG_DEBUG, "Already associated with the "
2085 "selected network - do nothing");
2086 return;
2087 }
2088
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002089 if (ssid) {
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002090 wpa_s->current_ssid = ssid;
Dmitry Shmidtb7b4d0e2013-08-26 12:09:05 -07002091 eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
2092 }
Jouni Malinen75ecf522011-06-27 15:19:46 -07002093 wpa_s->connect_without_scan = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094 wpa_s->disconnected = 0;
2095 wpa_s->reassociate = 1;
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002096
2097 if (wpa_supplicant_fast_associate(wpa_s) != 1)
2098 wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099
2100 if (ssid)
2101 wpas_notify_network_selected(wpa_s, ssid);
2102}
2103
2104
2105/**
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002106 * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path
2107 * @wpa_s: wpa_supplicant structure for a network interface
2108 * @pkcs11_engine_path: PKCS #11 engine path or NULL
2109 * @pkcs11_module_path: PKCS #11 module path or NULL
2110 * Returns: 0 on success; -1 on failure
2111 *
2112 * Sets the PKCS #11 engine and module path. Both have to be NULL or a valid
2113 * path. If resetting the EAPOL state machine with the new PKCS #11 engine and
2114 * module path fails the paths will be reset to the default value (NULL).
2115 */
2116int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s,
2117 const char *pkcs11_engine_path,
2118 const char *pkcs11_module_path)
2119{
2120 char *pkcs11_engine_path_copy = NULL;
2121 char *pkcs11_module_path_copy = NULL;
2122
2123 if (pkcs11_engine_path != NULL) {
2124 pkcs11_engine_path_copy = os_strdup(pkcs11_engine_path);
2125 if (pkcs11_engine_path_copy == NULL)
2126 return -1;
2127 }
2128 if (pkcs11_module_path != NULL) {
2129 pkcs11_module_path_copy = os_strdup(pkcs11_module_path);
Dmitry Shmidt97672262014-02-03 13:02:54 -08002130 if (pkcs11_module_path_copy == NULL) {
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08002131 os_free(pkcs11_engine_path_copy);
2132 return -1;
2133 }
2134 }
2135
2136 os_free(wpa_s->conf->pkcs11_engine_path);
2137 os_free(wpa_s->conf->pkcs11_module_path);
2138 wpa_s->conf->pkcs11_engine_path = pkcs11_engine_path_copy;
2139 wpa_s->conf->pkcs11_module_path = pkcs11_module_path_copy;
2140
2141 wpa_sm_set_eapol(wpa_s->wpa, NULL);
2142 eapol_sm_deinit(wpa_s->eapol);
2143 wpa_s->eapol = NULL;
2144 if (wpa_supplicant_init_eapol(wpa_s)) {
2145 /* Error -> Reset paths to the default value (NULL) once. */
2146 if (pkcs11_engine_path != NULL && pkcs11_module_path != NULL)
2147 wpas_set_pkcs11_engine_and_module_path(wpa_s, NULL,
2148 NULL);
2149
2150 return -1;
2151 }
2152 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
2153
2154 return 0;
2155}
2156
2157
2158/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002159 * wpa_supplicant_set_ap_scan - Set AP scan mode for interface
2160 * @wpa_s: wpa_supplicant structure for a network interface
2161 * @ap_scan: AP scan mode
2162 * Returns: 0 if succeed or -1 if ap_scan has an invalid value
2163 *
2164 */
2165int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan)
2166{
2167
2168 int old_ap_scan;
2169
2170 if (ap_scan < 0 || ap_scan > 2)
2171 return -1;
2172
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002173#ifdef ANDROID
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002174 if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan &&
2175 wpa_s->wpa_state >= WPA_ASSOCIATING &&
2176 wpa_s->wpa_state < WPA_COMPLETED) {
2177 wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while "
2178 "associating", wpa_s->conf->ap_scan, ap_scan);
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002179 return 0;
2180 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002181#endif /* ANDROID */
Dmitry Shmidt114c3862011-08-16 11:52:06 -07002182
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002183 old_ap_scan = wpa_s->conf->ap_scan;
2184 wpa_s->conf->ap_scan = ap_scan;
2185
2186 if (old_ap_scan != wpa_s->conf->ap_scan)
2187 wpas_notify_ap_scan_changed(wpa_s);
2188
2189 return 0;
2190}
2191
2192
2193/**
2194 * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age
2195 * @wpa_s: wpa_supplicant structure for a network interface
2196 * @expire_age: Expiration age in seconds
2197 * Returns: 0 if succeed or -1 if expire_age has an invalid value
2198 *
2199 */
2200int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s,
2201 unsigned int bss_expire_age)
2202{
2203 if (bss_expire_age < 10) {
2204 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u",
2205 bss_expire_age);
2206 return -1;
2207 }
2208 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec",
2209 bss_expire_age);
2210 wpa_s->conf->bss_expiration_age = bss_expire_age;
2211
2212 return 0;
2213}
2214
2215
2216/**
2217 * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count
2218 * @wpa_s: wpa_supplicant structure for a network interface
2219 * @expire_count: number of scans after which an unseen BSS is reclaimed
2220 * Returns: 0 if succeed or -1 if expire_count has an invalid value
2221 *
2222 */
2223int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s,
2224 unsigned int bss_expire_count)
2225{
2226 if (bss_expire_count < 1) {
2227 wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u",
2228 bss_expire_count);
2229 return -1;
2230 }
2231 wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u",
2232 bss_expire_count);
2233 wpa_s->conf->bss_expiration_scan_count = bss_expire_count;
2234
2235 return 0;
2236}
2237
2238
2239/**
Dmitry Shmidt04949592012-07-19 12:16:46 -07002240 * wpa_supplicant_set_scan_interval - Set scan interval
2241 * @wpa_s: wpa_supplicant structure for a network interface
2242 * @scan_interval: scan interval in seconds
2243 * Returns: 0 if succeed or -1 if scan_interval has an invalid value
2244 *
2245 */
2246int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s,
2247 int scan_interval)
2248{
2249 if (scan_interval < 0) {
2250 wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d",
2251 scan_interval);
2252 return -1;
2253 }
2254 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec",
2255 scan_interval);
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002256 wpa_supplicant_update_scan_int(wpa_s, scan_interval);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002257
2258 return 0;
2259}
2260
2261
2262/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002263 * wpa_supplicant_set_debug_params - Set global debug params
2264 * @global: wpa_global structure
2265 * @debug_level: debug level
2266 * @debug_timestamp: determines if show timestamp in debug data
2267 * @debug_show_keys: determines if show keys in debug data
2268 * Returns: 0 if succeed or -1 if debug_level has wrong value
2269 */
2270int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level,
2271 int debug_timestamp, int debug_show_keys)
2272{
2273
2274 int old_level, old_timestamp, old_show_keys;
2275
2276 /* check for allowed debuglevels */
2277 if (debug_level != MSG_EXCESSIVE &&
2278 debug_level != MSG_MSGDUMP &&
2279 debug_level != MSG_DEBUG &&
2280 debug_level != MSG_INFO &&
2281 debug_level != MSG_WARNING &&
2282 debug_level != MSG_ERROR)
2283 return -1;
2284
2285 old_level = wpa_debug_level;
2286 old_timestamp = wpa_debug_timestamp;
2287 old_show_keys = wpa_debug_show_keys;
2288
2289 wpa_debug_level = debug_level;
2290 wpa_debug_timestamp = debug_timestamp ? 1 : 0;
2291 wpa_debug_show_keys = debug_show_keys ? 1 : 0;
2292
2293 if (wpa_debug_level != old_level)
2294 wpas_notify_debug_level_changed(global);
2295 if (wpa_debug_timestamp != old_timestamp)
2296 wpas_notify_debug_timestamp_changed(global);
2297 if (wpa_debug_show_keys != old_show_keys)
2298 wpas_notify_debug_show_keys_changed(global);
2299
2300 return 0;
2301}
2302
2303
2304/**
2305 * wpa_supplicant_get_ssid - Get a pointer to the current network structure
2306 * @wpa_s: Pointer to wpa_supplicant data
2307 * Returns: A pointer to the current network structure or %NULL on failure
2308 */
2309struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s)
2310{
2311 struct wpa_ssid *entry;
2312 u8 ssid[MAX_SSID_LEN];
2313 int res;
2314 size_t ssid_len;
2315 u8 bssid[ETH_ALEN];
2316 int wired;
2317
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002318 res = wpa_drv_get_ssid(wpa_s, ssid);
2319 if (res < 0) {
2320 wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from "
2321 "driver");
2322 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002323 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002324 ssid_len = res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002326 if (wpa_drv_get_bssid(wpa_s, bssid) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from "
2328 "driver");
2329 return NULL;
2330 }
2331
2332 wired = wpa_s->conf->ap_scan == 0 &&
2333 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED);
2334
2335 entry = wpa_s->conf->ssid;
2336 while (entry) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07002337 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338 ((ssid_len == entry->ssid_len &&
2339 os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) &&
2340 (!entry->bssid_set ||
2341 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2342 return entry;
2343#ifdef CONFIG_WPS
Dmitry Shmidt04949592012-07-19 12:16:46 -07002344 if (!wpas_network_disabled(wpa_s, entry) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 (entry->key_mgmt & WPA_KEY_MGMT_WPS) &&
2346 (entry->ssid == NULL || entry->ssid_len == 0) &&
2347 (!entry->bssid_set ||
2348 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0))
2349 return entry;
2350#endif /* CONFIG_WPS */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002351
Dmitry Shmidt04949592012-07-19 12:16:46 -07002352 if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002353 entry->ssid_len == 0 &&
2354 os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)
2355 return entry;
2356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 entry = entry->next;
2358 }
2359
2360 return NULL;
2361}
2362
2363
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002364static int select_driver(struct wpa_supplicant *wpa_s, int i)
2365{
2366 struct wpa_global *global = wpa_s->global;
2367
2368 if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) {
2369 global->drv_priv[i] = wpa_drivers[i]->global_init();
2370 if (global->drv_priv[i] == NULL) {
2371 wpa_printf(MSG_ERROR, "Failed to initialize driver "
2372 "'%s'", wpa_drivers[i]->name);
2373 return -1;
2374 }
2375 }
2376
2377 wpa_s->driver = wpa_drivers[i];
2378 wpa_s->global_drv_priv = global->drv_priv[i];
2379
2380 return 0;
2381}
2382
2383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s,
2385 const char *name)
2386{
2387 int i;
2388 size_t len;
2389 const char *pos, *driver = name;
2390
2391 if (wpa_s == NULL)
2392 return -1;
2393
2394 if (wpa_drivers[0] == NULL) {
2395 wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into "
2396 "wpa_supplicant");
2397 return -1;
2398 }
2399
2400 if (name == NULL) {
2401 /* default to first driver in the list */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002402 return select_driver(wpa_s, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 }
2404
2405 do {
2406 pos = os_strchr(driver, ',');
2407 if (pos)
2408 len = pos - driver;
2409 else
2410 len = os_strlen(driver);
2411
2412 for (i = 0; wpa_drivers[i]; i++) {
2413 if (os_strlen(wpa_drivers[i]->name) == len &&
2414 os_strncmp(driver, wpa_drivers[i]->name, len) ==
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002415 0) {
2416 /* First driver that succeeds wins */
2417 if (select_driver(wpa_s, i) == 0)
2418 return 0;
2419 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 }
2421
2422 driver = pos + 1;
2423 } while (pos);
2424
2425 wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name);
2426 return -1;
2427}
2428
2429
2430/**
2431 * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant
2432 * @ctx: Context pointer (wpa_s); this is the ctx variable registered
2433 * with struct wpa_driver_ops::init()
2434 * @src_addr: Source address of the EAPOL frame
2435 * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header)
2436 * @len: Length of the EAPOL data
2437 *
2438 * This function is called for each received EAPOL frame. Most driver
2439 * interfaces rely on more generic OS mechanism for receiving frames through
2440 * l2_packet, but if such a mechanism is not available, the driver wrapper may
2441 * take care of received EAPOL frames and deliver them to the core supplicant
2442 * code by calling this function.
2443 */
2444void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr,
2445 const u8 *buf, size_t len)
2446{
2447 struct wpa_supplicant *wpa_s = ctx;
2448
2449 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr));
2450 wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len);
2451
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002452#ifdef CONFIG_PEERKEY
2453 if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid &&
2454 wpa_s->current_ssid->peerkey &&
2455 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
2456 wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) {
2457 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key");
2458 return;
2459 }
2460#endif /* CONFIG_PEERKEY */
2461
Jouni Malinena05074c2012-12-21 21:35:35 +02002462 if (wpa_s->wpa_state < WPA_ASSOCIATED ||
2463 (wpa_s->last_eapol_matches_bssid &&
2464#ifdef CONFIG_AP
2465 !wpa_s->ap_iface &&
2466#endif /* CONFIG_AP */
2467 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 /*
2469 * There is possible race condition between receiving the
2470 * association event and the EAPOL frame since they are coming
2471 * through different paths from the driver. In order to avoid
2472 * issues in trying to process the EAPOL frame before receiving
2473 * association information, lets queue it for processing until
Jouni Malinena05074c2012-12-21 21:35:35 +02002474 * the association event is received. This may also be needed in
2475 * driver-based roaming case, so also use src_addr != BSSID as a
2476 * trigger if we have previously confirmed that the
2477 * Authenticator uses BSSID as the src_addr (which is not the
2478 * case with wired IEEE 802.1X).
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 */
2480 wpa_dbg(wpa_s, MSG_DEBUG, "Not associated - Delay processing "
Jouni Malinena05074c2012-12-21 21:35:35 +02002481 "of received EAPOL frame (state=%s bssid=" MACSTR ")",
2482 wpa_supplicant_state_txt(wpa_s->wpa_state),
2483 MAC2STR(wpa_s->bssid));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 wpabuf_free(wpa_s->pending_eapol_rx);
2485 wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len);
2486 if (wpa_s->pending_eapol_rx) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002487 os_get_reltime(&wpa_s->pending_eapol_rx_time);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 os_memcpy(wpa_s->pending_eapol_rx_src, src_addr,
2489 ETH_ALEN);
2490 }
2491 return;
2492 }
2493
Jouni Malinena05074c2012-12-21 21:35:35 +02002494 wpa_s->last_eapol_matches_bssid =
2495 os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0;
2496
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497#ifdef CONFIG_AP
2498 if (wpa_s->ap_iface) {
2499 wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len);
2500 return;
2501 }
2502#endif /* CONFIG_AP */
2503
2504 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
2505 wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since "
2506 "no key management is configured");
2507 return;
2508 }
2509
2510 if (wpa_s->eapol_received == 0 &&
2511 (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) ||
2512 !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
2513 wpa_s->wpa_state != WPA_COMPLETED) &&
2514 (wpa_s->current_ssid == NULL ||
2515 wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) {
2516 /* Timeout for completing IEEE 802.1X and WPA authentication */
2517 wpa_supplicant_req_auth_timeout(
2518 wpa_s,
2519 (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) ||
2520 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA ||
2521 wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) ?
2522 70 : 10, 0);
2523 }
2524 wpa_s->eapol_received++;
2525
2526 if (wpa_s->countermeasures) {
2527 wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped "
2528 "EAPOL packet");
2529 return;
2530 }
2531
2532#ifdef CONFIG_IBSS_RSN
2533 if (wpa_s->current_ssid &&
2534 wpa_s->current_ssid->mode == WPAS_MODE_IBSS) {
2535 ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len);
2536 return;
2537 }
2538#endif /* CONFIG_IBSS_RSN */
2539
2540 /* Source address of the incoming EAPOL frame could be compared to the
2541 * current BSSID. However, it is possible that a centralized
2542 * Authenticator could be using another MAC address than the BSSID of
2543 * an AP, so just allow any address to be used for now. The replies are
2544 * still sent to the current BSSID (if available), though. */
2545
2546 os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN);
2547 if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) &&
2548 eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0)
2549 return;
2550 wpa_drv_poll(wpa_s);
2551 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
2552 wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len);
2553 else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
2554 /*
2555 * Set portValid = TRUE here since we are going to skip 4-way
2556 * handshake processing which would normally set portValid. We
2557 * need this to allow the EAPOL state machines to be completed
2558 * without going through EAPOL-Key handshake.
2559 */
2560 eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
2561 }
2562}
2563
2564
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002565int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 if (wpa_s->driver->send_eapol) {
2568 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2569 if (addr)
2570 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002571 } else if ((!wpa_s->p2p_mgmt ||
2572 !(wpa_s->drv_flags &
2573 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
2574 !(wpa_s->drv_flags &
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002576 l2_packet_deinit(wpa_s->l2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 wpa_s->l2 = l2_packet_init(wpa_s->ifname,
2578 wpa_drv_get_mac_addr(wpa_s),
2579 ETH_P_EAPOL,
2580 wpa_supplicant_rx_eapol, wpa_s, 0);
2581 if (wpa_s->l2 == NULL)
2582 return -1;
2583 } else {
2584 const u8 *addr = wpa_drv_get_mac_addr(wpa_s);
2585 if (addr)
2586 os_memcpy(wpa_s->own_addr, addr, ETH_ALEN);
2587 }
2588
2589 if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) {
2590 wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address");
2591 return -1;
2592 }
2593
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002594 return 0;
2595}
2596
2597
Dmitry Shmidt04949592012-07-19 12:16:46 -07002598static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr,
2599 const u8 *buf, size_t len)
2600{
2601 struct wpa_supplicant *wpa_s = ctx;
2602 const struct l2_ethhdr *eth;
2603
2604 if (len < sizeof(*eth))
2605 return;
2606 eth = (const struct l2_ethhdr *) buf;
2607
2608 if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 &&
2609 !(eth->h_dest[0] & 0x01)) {
2610 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2611 " (bridge - not for this interface - ignore)",
2612 MAC2STR(src_addr), MAC2STR(eth->h_dest));
2613 return;
2614 }
2615
2616 wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR
2617 " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest));
2618 wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth),
2619 len - sizeof(*eth));
2620}
2621
2622
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002623/**
2624 * wpa_supplicant_driver_init - Initialize driver interface parameters
2625 * @wpa_s: Pointer to wpa_supplicant data
2626 * Returns: 0 on success, -1 on failure
2627 *
2628 * This function is called to initialize driver interface parameters.
2629 * wpa_drv_init() must have been called before this function to initialize the
2630 * driver interface.
2631 */
2632int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
2633{
2634 static int interface_count = 0;
2635
2636 if (wpa_supplicant_update_mac_addr(wpa_s) < 0)
2637 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002639 wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR,
2640 MAC2STR(wpa_s->own_addr));
2641 wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
2642
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 if (wpa_s->bridge_ifname[0]) {
2644 wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge "
2645 "interface '%s'", wpa_s->bridge_ifname);
2646 wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname,
2647 wpa_s->own_addr,
2648 ETH_P_EAPOL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002649 wpa_supplicant_rx_eapol_bridge,
2650 wpa_s, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 if (wpa_s->l2_br == NULL) {
2652 wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet "
2653 "connection for the bridge interface '%s'",
2654 wpa_s->bridge_ifname);
2655 return -1;
2656 }
2657 }
2658
2659 wpa_clear_keys(wpa_s, NULL);
2660
2661 /* Make sure that TKIP countermeasures are not left enabled (could
2662 * happen if wpa_supplicant is killed during countermeasures. */
2663 wpa_drv_set_countermeasures(wpa_s, 0);
2664
2665 wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
2666 wpa_drv_flush_pmkid(wpa_s);
2667
2668 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002669 wpa_s->prev_scan_wildcard = 0;
2670
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671 if (wpa_supplicant_enabled_networks(wpa_s)) {
Dmitry Shmidt9e3f8ee2014-01-17 10:52:01 -08002672 if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
2673 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2674 interface_count = 0;
2675 }
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002676 if (!wpa_s->p2p_mgmt &&
2677 wpa_supplicant_delayed_sched_scan(wpa_s, interface_count,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002678 100000))
2679 wpa_supplicant_req_scan(wpa_s, interface_count,
2680 100000);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 interface_count++;
2682 } else
2683 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
2684
2685 return 0;
2686}
2687
2688
2689static int wpa_supplicant_daemon(const char *pid_file)
2690{
2691 wpa_printf(MSG_DEBUG, "Daemonize..");
2692 return os_daemonize(pid_file);
2693}
2694
2695
2696static struct wpa_supplicant * wpa_supplicant_alloc(void)
2697{
2698 struct wpa_supplicant *wpa_s;
2699
2700 wpa_s = os_zalloc(sizeof(*wpa_s));
2701 if (wpa_s == NULL)
2702 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002703 wpa_s->scan_req = INITIAL_SCAN_REQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 wpa_s->scan_interval = 5;
2705 wpa_s->new_connection = 1;
2706 wpa_s->parent = wpa_s;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002707 wpa_s->sched_scanning = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708
2709 return wpa_s;
2710}
2711
2712
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002713#ifdef CONFIG_HT_OVERRIDES
2714
2715static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s,
2716 struct ieee80211_ht_capabilities *htcaps,
2717 struct ieee80211_ht_capabilities *htcaps_mask,
2718 const char *ht_mcs)
2719{
2720 /* parse ht_mcs into hex array */
2721 int i;
2722 const char *tmp = ht_mcs;
2723 char *end = NULL;
2724
2725 /* If ht_mcs is null, do not set anything */
2726 if (!ht_mcs)
2727 return 0;
2728
2729 /* This is what we are setting in the kernel */
2730 os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN);
2731
2732 wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs);
2733
2734 for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
2735 errno = 0;
2736 long v = strtol(tmp, &end, 16);
2737 if (errno == 0) {
2738 wpa_msg(wpa_s, MSG_DEBUG,
2739 "htcap value[%i]: %ld end: %p tmp: %p",
2740 i, v, end, tmp);
2741 if (end == tmp)
2742 break;
2743
2744 htcaps->supported_mcs_set[i] = v;
2745 tmp = end;
2746 } else {
2747 wpa_msg(wpa_s, MSG_ERROR,
2748 "Failed to parse ht-mcs: %s, error: %s\n",
2749 ht_mcs, strerror(errno));
2750 return -1;
2751 }
2752 }
2753
2754 /*
2755 * If we were able to parse any values, then set mask for the MCS set.
2756 */
2757 if (i) {
2758 os_memset(&htcaps_mask->supported_mcs_set, 0xff,
2759 IEEE80211_HT_MCS_MASK_LEN - 1);
2760 /* skip the 3 reserved bits */
2761 htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] =
2762 0x1f;
2763 }
2764
2765 return 0;
2766}
2767
2768
2769static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s,
2770 struct ieee80211_ht_capabilities *htcaps,
2771 struct ieee80211_ht_capabilities *htcaps_mask,
2772 int disabled)
2773{
2774 u16 msk;
2775
2776 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled);
2777
2778 if (disabled == -1)
2779 return 0;
2780
2781 msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE);
2782 htcaps_mask->ht_capabilities_info |= msk;
2783 if (disabled)
2784 htcaps->ht_capabilities_info &= msk;
2785 else
2786 htcaps->ht_capabilities_info |= msk;
2787
2788 return 0;
2789}
2790
2791
2792static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s,
2793 struct ieee80211_ht_capabilities *htcaps,
2794 struct ieee80211_ht_capabilities *htcaps_mask,
2795 int factor)
2796{
2797 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor);
2798
2799 if (factor == -1)
2800 return 0;
2801
2802 if (factor < 0 || factor > 3) {
2803 wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. "
2804 "Must be 0-3 or -1", factor);
2805 return -EINVAL;
2806 }
2807
2808 htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */
2809 htcaps->a_mpdu_params &= ~0x3;
2810 htcaps->a_mpdu_params |= factor & 0x3;
2811
2812 return 0;
2813}
2814
2815
2816static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s,
2817 struct ieee80211_ht_capabilities *htcaps,
2818 struct ieee80211_ht_capabilities *htcaps_mask,
2819 int density)
2820{
2821 wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density);
2822
2823 if (density == -1)
2824 return 0;
2825
2826 if (density < 0 || density > 7) {
2827 wpa_msg(wpa_s, MSG_ERROR,
2828 "ampdu_density: %d out of range. Must be 0-7 or -1.",
2829 density);
2830 return -EINVAL;
2831 }
2832
2833 htcaps_mask->a_mpdu_params |= 0x1C;
2834 htcaps->a_mpdu_params &= ~(0x1C);
2835 htcaps->a_mpdu_params |= (density << 2) & 0x1C;
2836
2837 return 0;
2838}
2839
2840
2841static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s,
2842 struct ieee80211_ht_capabilities *htcaps,
2843 struct ieee80211_ht_capabilities *htcaps_mask,
2844 int disabled)
2845{
2846 /* Masking these out disables HT40 */
2847 u16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET |
2848 HT_CAP_INFO_SHORT_GI40MHZ);
2849
2850 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled);
2851
2852 if (disabled)
2853 htcaps->ht_capabilities_info &= ~msk;
2854 else
2855 htcaps->ht_capabilities_info |= msk;
2856
2857 htcaps_mask->ht_capabilities_info |= msk;
2858
2859 return 0;
2860}
2861
2862
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002863static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s,
2864 struct ieee80211_ht_capabilities *htcaps,
2865 struct ieee80211_ht_capabilities *htcaps_mask,
2866 int disabled)
2867{
2868 /* Masking these out disables SGI */
2869 u16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ |
2870 HT_CAP_INFO_SHORT_GI40MHZ);
2871
2872 wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled);
2873
2874 if (disabled)
2875 htcaps->ht_capabilities_info &= ~msk;
2876 else
2877 htcaps->ht_capabilities_info |= msk;
2878
2879 htcaps_mask->ht_capabilities_info |= msk;
2880
2881 return 0;
2882}
2883
2884
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002885void wpa_supplicant_apply_ht_overrides(
2886 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2887 struct wpa_driver_associate_params *params)
2888{
2889 struct ieee80211_ht_capabilities *htcaps;
2890 struct ieee80211_ht_capabilities *htcaps_mask;
2891
2892 if (!ssid)
2893 return;
2894
2895 params->disable_ht = ssid->disable_ht;
2896 if (!params->htcaps || !params->htcaps_mask)
2897 return;
2898
2899 htcaps = (struct ieee80211_ht_capabilities *) params->htcaps;
2900 htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask;
2901 wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs);
2902 wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask,
2903 ssid->disable_max_amsdu);
2904 wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor);
2905 wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density);
2906 wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002907 wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002908}
2909
2910#endif /* CONFIG_HT_OVERRIDES */
2911
2912
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002913#ifdef CONFIG_VHT_OVERRIDES
2914void wpa_supplicant_apply_vht_overrides(
2915 struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
2916 struct wpa_driver_associate_params *params)
2917{
2918 struct ieee80211_vht_capabilities *vhtcaps;
2919 struct ieee80211_vht_capabilities *vhtcaps_mask;
2920
2921 if (!ssid)
2922 return;
2923
2924 params->disable_vht = ssid->disable_vht;
2925
2926 vhtcaps = (void *) params->vhtcaps;
2927 vhtcaps_mask = (void *) params->vhtcaps_mask;
2928
2929 if (!vhtcaps || !vhtcaps_mask)
2930 return;
2931
2932 vhtcaps->vht_capabilities_info = ssid->vht_capa;
2933 vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask;
2934
2935#define OVERRIDE_MCS(i) \
2936 if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \
2937 vhtcaps_mask->vht_supported_mcs_set.tx_map |= \
2938 3 << 2 * (i - 1); \
2939 vhtcaps->vht_supported_mcs_set.tx_map |= \
2940 ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \
2941 } \
2942 if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \
2943 vhtcaps_mask->vht_supported_mcs_set.rx_map |= \
2944 3 << 2 * (i - 1); \
2945 vhtcaps->vht_supported_mcs_set.rx_map |= \
2946 ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \
2947 }
2948
2949 OVERRIDE_MCS(1);
2950 OVERRIDE_MCS(2);
2951 OVERRIDE_MCS(3);
2952 OVERRIDE_MCS(4);
2953 OVERRIDE_MCS(5);
2954 OVERRIDE_MCS(6);
2955 OVERRIDE_MCS(7);
2956 OVERRIDE_MCS(8);
2957}
2958#endif /* CONFIG_VHT_OVERRIDES */
2959
2960
Dmitry Shmidt04949592012-07-19 12:16:46 -07002961static int pcsc_reader_init(struct wpa_supplicant *wpa_s)
2962{
2963#ifdef PCSC_FUNCS
2964 size_t len;
2965
2966 if (!wpa_s->conf->pcsc_reader)
2967 return 0;
2968
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002969 wpa_s->scard = scard_init(wpa_s->conf->pcsc_reader);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002970 if (!wpa_s->scard)
2971 return 1;
2972
2973 if (wpa_s->conf->pcsc_pin &&
2974 scard_set_pin(wpa_s->scard, wpa_s->conf->pcsc_pin) < 0) {
2975 scard_deinit(wpa_s->scard);
2976 wpa_s->scard = NULL;
2977 wpa_msg(wpa_s, MSG_ERROR, "PC/SC PIN validation failed");
2978 return -1;
2979 }
2980
2981 len = sizeof(wpa_s->imsi) - 1;
2982 if (scard_get_imsi(wpa_s->scard, wpa_s->imsi, &len)) {
2983 scard_deinit(wpa_s->scard);
2984 wpa_s->scard = NULL;
2985 wpa_msg(wpa_s, MSG_ERROR, "Could not read IMSI");
2986 return -1;
2987 }
2988 wpa_s->imsi[len] = '\0';
2989
2990 wpa_s->mnc_len = scard_get_mnc_len(wpa_s->scard);
2991
2992 wpa_printf(MSG_DEBUG, "SCARD: IMSI %s (MNC length %d)",
2993 wpa_s->imsi, wpa_s->mnc_len);
2994
2995 wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard);
2996 eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard);
2997#endif /* PCSC_FUNCS */
2998
2999 return 0;
3000}
3001
3002
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003003int wpas_init_ext_pw(struct wpa_supplicant *wpa_s)
3004{
3005 char *val, *pos;
3006
3007 ext_password_deinit(wpa_s->ext_pw);
3008 wpa_s->ext_pw = NULL;
3009 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, NULL);
3010
3011 if (!wpa_s->conf->ext_password_backend)
3012 return 0;
3013
3014 val = os_strdup(wpa_s->conf->ext_password_backend);
3015 if (val == NULL)
3016 return -1;
3017 pos = os_strchr(val, ':');
3018 if (pos)
3019 *pos++ = '\0';
3020
3021 wpa_printf(MSG_DEBUG, "EXT PW: Initialize backend '%s'", val);
3022
3023 wpa_s->ext_pw = ext_password_init(val, pos);
3024 os_free(val);
3025 if (wpa_s->ext_pw == NULL) {
3026 wpa_printf(MSG_DEBUG, "EXT PW: Failed to initialize backend");
3027 return -1;
3028 }
3029 eapol_sm_set_ext_pw_ctx(wpa_s->eapol, wpa_s->ext_pw);
3030
3031 return 0;
3032}
3033
3034
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003035static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s,
3036 const char *rn)
3037{
3038 struct wpa_supplicant *iface = wpa_s->global->ifaces;
3039 struct wpa_radio *radio;
3040
3041 while (rn && iface) {
3042 radio = iface->radio;
3043 if (radio && os_strcmp(rn, radio->name) == 0) {
3044 wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s",
3045 wpa_s->ifname, rn);
3046 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3047 return radio;
3048 }
Dmitry Shmidt3cf6f792013-12-18 13:12:19 -08003049
3050 iface = iface->next;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003051 }
3052
3053 wpa_printf(MSG_DEBUG, "Add interface %s to a new radio %s",
3054 wpa_s->ifname, rn ? rn : "N/A");
3055 radio = os_zalloc(sizeof(*radio));
3056 if (radio == NULL)
3057 return NULL;
3058
3059 if (rn)
3060 os_strlcpy(radio->name, rn, sizeof(radio->name));
3061 dl_list_init(&radio->ifaces);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003062 dl_list_init(&radio->work);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003063 dl_list_add(&radio->ifaces, &wpa_s->radio_list);
3064
3065 return radio;
3066}
3067
3068
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003069static void radio_work_free(struct wpa_radio_work *work)
3070{
3071 if (work->wpa_s->scan_work == work) {
3072 /* This should not really happen. */
3073 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work",
3074 work->type, work, work->started);
3075 work->wpa_s->scan_work = NULL;
3076 }
3077
3078#ifdef CONFIG_P2P
3079 if (work->wpa_s->p2p_scan_work == work) {
3080 /* This should not really happen. */
3081 wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work",
3082 work->type, work, work->started);
3083 work->wpa_s->p2p_scan_work = NULL;
3084 }
3085#endif /* CONFIG_P2P */
3086
3087 dl_list_del(&work->list);
3088 os_free(work);
3089}
3090
3091
3092static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
3093{
3094 struct wpa_radio *radio = eloop_ctx;
3095 struct wpa_radio_work *work;
3096 struct os_reltime now, diff;
3097 struct wpa_supplicant *wpa_s;
3098
3099 work = dl_list_first(&radio->work, struct wpa_radio_work, list);
3100 if (work == NULL)
3101 return;
3102
3103 if (work->started)
3104 return; /* already started and still in progress */
3105
3106 wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant,
3107 radio_list);
3108 if (wpa_s && wpa_s->external_scan_running) {
3109 wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
3110 return;
3111 }
3112
3113 os_get_reltime(&now);
3114 os_reltime_sub(&now, &work->time, &diff);
3115 wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait",
3116 work->type, work, diff.sec, diff.usec);
3117 work->started = 1;
3118 work->time = now;
3119 work->cb(work, 0);
3120}
3121
3122
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003123/*
3124 * This function removes both started and pending radio works running on
3125 * the provided interface's radio.
3126 * Prior to the removal of the radio work, its callback (cb) is called with
3127 * deinit set to be 1. Each work's callback is responsible for clearing its
3128 * internal data and restoring to a correct state.
3129 * @wpa_s: wpa_supplicant data
3130 * @type: type of works to be removed
3131 * @remove_all: 1 to remove all the works on this radio, 0 to remove only
3132 * this interface's works.
3133 */
3134void radio_remove_works(struct wpa_supplicant *wpa_s,
3135 const char *type, int remove_all)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003136{
3137 struct wpa_radio_work *work, *tmp;
3138 struct wpa_radio *radio = wpa_s->radio;
3139
3140 dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work,
3141 list) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003142 if (type && os_strcmp(type, work->type) != 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003143 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003144
3145 /* skip other ifaces' works */
3146 if (!remove_all && work->wpa_s != wpa_s)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003147 continue;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003148
3149 wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s",
3150 work->type, work, work->started ? " (started)" : "");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003151 work->cb(work, 1);
3152 radio_work_free(work);
3153 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003154
3155 /* in case we removed the started work */
3156 radio_work_check_next(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003157}
3158
3159
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003160static void radio_remove_interface(struct wpa_supplicant *wpa_s)
3161{
3162 struct wpa_radio *radio = wpa_s->radio;
3163
3164 if (!radio)
3165 return;
3166
3167 wpa_printf(MSG_DEBUG, "Remove interface %s from radio %s",
3168 wpa_s->ifname, radio->name);
3169 dl_list_del(&wpa_s->radio_list);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003170 if (!dl_list_empty(&radio->ifaces)) {
3171 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003172 return; /* Interfaces remain for this radio */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003173 }
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003174
3175 wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name);
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003176 radio_remove_works(wpa_s, NULL, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003177 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3178 wpa_s->radio = NULL;
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003179 os_free(radio);
3180}
3181
3182
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003183void radio_work_check_next(struct wpa_supplicant *wpa_s)
3184{
3185 struct wpa_radio *radio = wpa_s->radio;
3186
3187 if (dl_list_empty(&radio->work))
3188 return;
3189 eloop_cancel_timeout(radio_start_next_work, radio, NULL);
3190 eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL);
3191}
3192
3193
3194/**
3195 * radio_add_work - Add a radio work item
3196 * @wpa_s: Pointer to wpa_supplicant data
3197 * @freq: Frequency of the offchannel operation in MHz or 0
3198 * @type: Unique identifier for each type of work
3199 * @next: Force as the next work to be executed
3200 * @cb: Callback function for indicating when radio is available
3201 * @ctx: Context pointer for the work (work->ctx in cb())
3202 * Returns: 0 on success, -1 on failure
3203 *
3204 * This function is used to request time for an operation that requires
3205 * exclusive radio control. Once the radio is available, the registered callback
3206 * function will be called. radio_work_done() must be called once the exclusive
3207 * radio operation has been completed, so that the radio is freed for other
3208 * operations. The special case of deinit=1 is used to free the context data
3209 * during interface removal. That does not allow the callback function to start
3210 * the radio operation, i.e., it must free any resources allocated for the radio
3211 * work and return.
3212 *
3213 * The @freq parameter can be used to indicate a single channel on which the
3214 * offchannel operation will occur. This may allow multiple radio work
3215 * operations to be performed in parallel if they apply for the same channel.
3216 * Setting this to 0 indicates that the work item may use multiple channels or
3217 * requires exclusive control of the radio.
3218 */
3219int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq,
3220 const char *type, int next,
3221 void (*cb)(struct wpa_radio_work *work, int deinit),
3222 void *ctx)
3223{
3224 struct wpa_radio_work *work;
3225 int was_empty;
3226
3227 work = os_zalloc(sizeof(*work));
3228 if (work == NULL)
3229 return -1;
3230 wpa_dbg(wpa_s, MSG_DEBUG, "Add radio work '%s'@%p", type, work);
3231 os_get_reltime(&work->time);
3232 work->freq = freq;
3233 work->type = type;
3234 work->wpa_s = wpa_s;
3235 work->cb = cb;
3236 work->ctx = ctx;
3237
3238 was_empty = dl_list_empty(&wpa_s->radio->work);
3239 if (next)
3240 dl_list_add(&wpa_s->radio->work, &work->list);
3241 else
3242 dl_list_add_tail(&wpa_s->radio->work, &work->list);
3243 if (was_empty) {
3244 wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately");
3245 radio_work_check_next(wpa_s);
3246 }
3247
3248 return 0;
3249}
3250
3251
3252/**
3253 * radio_work_done - Indicate that a radio work item has been completed
3254 * @work: Completed work
3255 *
3256 * This function is called once the callback function registered with
3257 * radio_add_work() has completed its work.
3258 */
3259void radio_work_done(struct wpa_radio_work *work)
3260{
3261 struct wpa_supplicant *wpa_s = work->wpa_s;
3262 struct os_reltime now, diff;
3263 unsigned int started = work->started;
3264
3265 os_get_reltime(&now);
3266 os_reltime_sub(&now, &work->time, &diff);
3267 wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds",
3268 work->type, work, started ? "done" : "canceled",
3269 diff.sec, diff.usec);
3270 radio_work_free(work);
3271 if (started)
3272 radio_work_check_next(wpa_s);
3273}
3274
3275
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003276int radio_work_pending(struct wpa_supplicant *wpa_s, const char *type)
3277{
3278 struct wpa_radio_work *work;
3279 struct wpa_radio *radio = wpa_s->radio;
3280
3281 dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) {
3282 if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0)
3283 return 1;
3284 }
3285
3286 return 0;
3287}
3288
3289
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003290static int wpas_init_driver(struct wpa_supplicant *wpa_s,
3291 struct wpa_interface *iface)
3292{
3293 const char *ifname, *driver, *rn;
3294
3295 driver = iface->driver;
3296next_driver:
3297 if (wpa_supplicant_set_driver(wpa_s, driver) < 0)
3298 return -1;
3299
3300 wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
3301 if (wpa_s->drv_priv == NULL) {
3302 const char *pos;
3303 pos = driver ? os_strchr(driver, ',') : NULL;
3304 if (pos) {
3305 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize "
3306 "driver interface - try next driver wrapper");
3307 driver = pos + 1;
3308 goto next_driver;
3309 }
3310 wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver "
3311 "interface");
3312 return -1;
3313 }
3314 if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) {
3315 wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected "
3316 "driver_param '%s'", wpa_s->conf->driver_param);
3317 return -1;
3318 }
3319
3320 ifname = wpa_drv_get_ifname(wpa_s);
3321 if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) {
3322 wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced "
3323 "interface name with '%s'", ifname);
3324 os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname));
3325 }
3326
3327 if (wpa_s->driver->get_radio_name)
3328 rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
3329 else
3330 rn = NULL;
3331 if (rn && rn[0] == '\0')
3332 rn = NULL;
3333
3334 wpa_s->radio = radio_add_interface(wpa_s, rn);
3335 if (wpa_s->radio == NULL)
3336 return -1;
3337
3338 return 0;
3339}
3340
3341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
3343 struct wpa_interface *iface)
3344{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 struct wpa_driver_capa capa;
3346
3347 wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
3348 "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
3349 iface->confname ? iface->confname : "N/A",
3350 iface->driver ? iface->driver : "default",
3351 iface->ctrl_interface ? iface->ctrl_interface : "N/A",
3352 iface->bridge_ifname ? iface->bridge_ifname : "N/A");
3353
3354 if (iface->confname) {
3355#ifdef CONFIG_BACKEND_FILE
3356 wpa_s->confname = os_rel2abs_path(iface->confname);
3357 if (wpa_s->confname == NULL) {
3358 wpa_printf(MSG_ERROR, "Failed to get absolute path "
3359 "for configuration file '%s'.",
3360 iface->confname);
3361 return -1;
3362 }
3363 wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
3364 iface->confname, wpa_s->confname);
3365#else /* CONFIG_BACKEND_FILE */
3366 wpa_s->confname = os_strdup(iface->confname);
3367#endif /* CONFIG_BACKEND_FILE */
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003368 wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369 if (wpa_s->conf == NULL) {
3370 wpa_printf(MSG_ERROR, "Failed to read or parse "
3371 "configuration '%s'.", wpa_s->confname);
3372 return -1;
3373 }
Dmitry Shmidt64f47c52013-04-16 10:41:54 -07003374 wpa_s->confanother = os_rel2abs_path(iface->confanother);
3375 wpa_config_read(wpa_s->confanother, wpa_s->conf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376
3377 /*
3378 * Override ctrl_interface and driver_param if set on command
3379 * line.
3380 */
3381 if (iface->ctrl_interface) {
3382 os_free(wpa_s->conf->ctrl_interface);
3383 wpa_s->conf->ctrl_interface =
3384 os_strdup(iface->ctrl_interface);
3385 }
3386
3387 if (iface->driver_param) {
3388 os_free(wpa_s->conf->driver_param);
3389 wpa_s->conf->driver_param =
3390 os_strdup(iface->driver_param);
3391 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003392
3393 if (iface->p2p_mgmt && !iface->ctrl_interface) {
3394 os_free(wpa_s->conf->ctrl_interface);
3395 wpa_s->conf->ctrl_interface = NULL;
3396 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397 } else
3398 wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface,
3399 iface->driver_param);
3400
3401 if (wpa_s->conf == NULL) {
3402 wpa_printf(MSG_ERROR, "\nNo configuration found.");
3403 return -1;
3404 }
3405
3406 if (iface->ifname == NULL) {
3407 wpa_printf(MSG_ERROR, "\nInterface name is required.");
3408 return -1;
3409 }
3410 if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) {
3411 wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.",
3412 iface->ifname);
3413 return -1;
3414 }
3415 os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname));
3416
3417 if (iface->bridge_ifname) {
3418 if (os_strlen(iface->bridge_ifname) >=
3419 sizeof(wpa_s->bridge_ifname)) {
3420 wpa_printf(MSG_ERROR, "\nToo long bridge interface "
3421 "name '%s'.", iface->bridge_ifname);
3422 return -1;
3423 }
3424 os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname,
3425 sizeof(wpa_s->bridge_ifname));
3426 }
3427
3428 /* RSNA Supplicant Key Management - INITIALIZE */
3429 eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE);
3430 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
3431
3432 /* Initialize driver interface and register driver event handler before
3433 * L2 receive handler so that association events are processed before
3434 * EAPOL-Key packets if both become available for the same select()
3435 * call. */
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003436 if (wpas_init_driver(wpa_s, iface) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003437 return -1;
3438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439 if (wpa_supplicant_init_wpa(wpa_s) < 0)
3440 return -1;
3441
3442 wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname,
3443 wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname :
3444 NULL);
3445 wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth);
3446
3447 if (wpa_s->conf->dot11RSNAConfigPMKLifetime &&
3448 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
3449 wpa_s->conf->dot11RSNAConfigPMKLifetime)) {
3450 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3451 "dot11RSNAConfigPMKLifetime");
3452 return -1;
3453 }
3454
3455 if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold &&
3456 wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
3457 wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) {
3458 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3459 "dot11RSNAConfigPMKReauthThreshold");
3460 return -1;
3461 }
3462
3463 if (wpa_s->conf->dot11RSNAConfigSATimeout &&
3464 wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT,
3465 wpa_s->conf->dot11RSNAConfigSATimeout)) {
3466 wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for "
3467 "dot11RSNAConfigSATimeout");
3468 return -1;
3469 }
3470
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003471 wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s,
3472 &wpa_s->hw.num_modes,
3473 &wpa_s->hw.flags);
3474
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003475 if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003476 wpa_s->drv_capa_known = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 wpa_s->drv_flags = capa.flags;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003478 wpa_s->drv_enc = capa.enc;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003479 wpa_s->probe_resp_offloads = capa.probe_resp_offloads;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480 wpa_s->max_scan_ssids = capa.max_scan_ssids;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003481 wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
3482 wpa_s->sched_scan_supported = capa.sched_scan_supported;
3483 wpa_s->max_match_sets = capa.max_match_sets;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003484 wpa_s->max_remain_on_chan = capa.max_remain_on_chan;
3485 wpa_s->max_stations = capa.max_stations;
Dmitry Shmidt444d5672013-04-01 13:08:44 -07003486 wpa_s->extended_capa = capa.extended_capa;
3487 wpa_s->extended_capa_mask = capa.extended_capa_mask;
3488 wpa_s->extended_capa_len = capa.extended_capa_len;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003489 wpa_s->num_multichan_concurrent =
3490 capa.num_multichan_concurrent;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 }
3492 if (wpa_s->max_remain_on_chan == 0)
3493 wpa_s->max_remain_on_chan = 1000;
3494
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003495 /*
3496 * Only take p2p_mgmt parameters when P2P Device is supported.
3497 * Doing it here as it determines whether l2_packet_init() will be done
3498 * during wpa_supplicant_driver_init().
3499 */
3500 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)
3501 wpa_s->p2p_mgmt = iface->p2p_mgmt;
3502 else
3503 iface->p2p_mgmt = 1;
3504
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003505 if (wpa_s->num_multichan_concurrent == 0)
3506 wpa_s->num_multichan_concurrent = 1;
3507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 if (wpa_supplicant_driver_init(wpa_s) < 0)
3509 return -1;
3510
3511#ifdef CONFIG_TDLS
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003512 if ((!iface->p2p_mgmt ||
3513 !(wpa_s->drv_flags &
3514 WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) &&
3515 wpa_tdls_init(wpa_s->wpa))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003516 return -1;
3517#endif /* CONFIG_TDLS */
3518
3519 if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
3520 wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
3521 wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
3522 return -1;
3523 }
3524
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003525 if (wpas_wps_init(wpa_s))
3526 return -1;
3527
3528 if (wpa_supplicant_init_eapol(wpa_s) < 0)
3529 return -1;
3530 wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
3531
3532 wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
3533 if (wpa_s->ctrl_iface == NULL) {
3534 wpa_printf(MSG_ERROR,
3535 "Failed to initialize control interface '%s'.\n"
3536 "You may have another wpa_supplicant process "
3537 "already running or the file was\n"
3538 "left by an unclean termination of wpa_supplicant "
3539 "in which case you will need\n"
3540 "to manually remove this file before starting "
3541 "wpa_supplicant again.\n",
3542 wpa_s->conf->ctrl_interface);
3543 return -1;
3544 }
3545
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003546 wpa_s->gas = gas_query_init(wpa_s);
3547 if (wpa_s->gas == NULL) {
3548 wpa_printf(MSG_ERROR, "Failed to initialize GAS query");
3549 return -1;
3550 }
3551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003552#ifdef CONFIG_P2P
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003553 if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P");
3555 return -1;
3556 }
3557#endif /* CONFIG_P2P */
3558
3559 if (wpa_bss_init(wpa_s) < 0)
3560 return -1;
3561
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003562#ifdef CONFIG_EAP_PROXY
3563{
3564 size_t len;
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07003565 wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, wpa_s->imsi,
3566 &len);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003567 if (wpa_s->mnc_len > 0) {
3568 wpa_s->imsi[len] = '\0';
3569 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)",
3570 wpa_s->imsi, wpa_s->mnc_len);
3571 } else {
3572 wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available");
3573 }
3574}
3575#endif /* CONFIG_EAP_PROXY */
3576
Dmitry Shmidt04949592012-07-19 12:16:46 -07003577 if (pcsc_reader_init(wpa_s) < 0)
3578 return -1;
3579
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003580 if (wpas_init_ext_pw(wpa_s) < 0)
3581 return -1;
3582
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003583 return 0;
3584}
3585
3586
3587static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003588 int notify, int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003589{
Dmitry Shmidtea69e842013-05-13 14:52:28 -07003590 wpa_s->disconnected = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003591 if (wpa_s->drv_priv) {
3592 wpa_supplicant_deauthenticate(wpa_s,
3593 WLAN_REASON_DEAUTH_LEAVING);
3594
3595 wpa_drv_set_countermeasures(wpa_s, 0);
3596 wpa_clear_keys(wpa_s, NULL);
3597 }
3598
3599 wpa_supplicant_cleanup(wpa_s);
3600
Dmitry Shmidt04949592012-07-19 12:16:46 -07003601#ifdef CONFIG_P2P
3602 if (wpa_s == wpa_s->global->p2p_init_wpa_s && wpa_s->global->p2p) {
3603 wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Disable P2P since removing "
3604 "the management interface is being removed");
3605 wpas_p2p_deinit_global(wpa_s->global);
3606 }
3607#endif /* CONFIG_P2P */
3608
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003609 wpas_ctrl_radio_work_flush(wpa_s);
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08003610 radio_remove_interface(wpa_s);
3611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612 if (wpa_s->drv_priv)
3613 wpa_drv_deinit(wpa_s);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003614
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003615 if (notify)
3616 wpas_notify_iface_removed(wpa_s);
3617
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003618 if (terminate)
3619 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003620
3621 if (wpa_s->ctrl_iface) {
3622 wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface);
3623 wpa_s->ctrl_iface = NULL;
3624 }
3625
3626 if (wpa_s->conf != NULL) {
Irfan Sheriff622b66d2011-08-03 09:11:49 -07003627 wpa_config_free(wpa_s->conf);
3628 wpa_s->conf = NULL;
3629 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003630
3631 os_free(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003632}
3633
3634
3635/**
3636 * wpa_supplicant_add_iface - Add a new network interface
3637 * @global: Pointer to global data from wpa_supplicant_init()
3638 * @iface: Interface configuration options
3639 * Returns: Pointer to the created interface or %NULL on failure
3640 *
3641 * This function is used to add new network interfaces for %wpa_supplicant.
3642 * This can be called before wpa_supplicant_run() to add interfaces before the
3643 * main event loop has been started. In addition, new interfaces can be added
3644 * dynamically while %wpa_supplicant is already running. This could happen,
3645 * e.g., when a hotplug network adapter is inserted.
3646 */
3647struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
3648 struct wpa_interface *iface)
3649{
3650 struct wpa_supplicant *wpa_s;
3651 struct wpa_interface t_iface;
3652 struct wpa_ssid *ssid;
3653
3654 if (global == NULL || iface == NULL)
3655 return NULL;
3656
3657 wpa_s = wpa_supplicant_alloc();
3658 if (wpa_s == NULL)
3659 return NULL;
3660
3661 wpa_s->global = global;
3662
3663 t_iface = *iface;
3664 if (global->params.override_driver) {
3665 wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
3666 "('%s' -> '%s')",
3667 iface->driver, global->params.override_driver);
3668 t_iface.driver = global->params.override_driver;
3669 }
3670 if (global->params.override_ctrl_interface) {
3671 wpa_printf(MSG_DEBUG, "Override interface parameter: "
3672 "ctrl_interface ('%s' -> '%s')",
3673 iface->ctrl_interface,
3674 global->params.override_ctrl_interface);
3675 t_iface.ctrl_interface =
3676 global->params.override_ctrl_interface;
3677 }
3678 if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
3679 wpa_printf(MSG_DEBUG, "Failed to add interface %s",
3680 iface->ifname);
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003681 wpa_supplicant_deinit_iface(wpa_s, 0, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003682 return NULL;
3683 }
3684
3685 /* Notify the control interfaces about new iface */
3686 if (wpas_notify_iface_added(wpa_s)) {
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003687 wpa_supplicant_deinit_iface(wpa_s, 1, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003688 return NULL;
3689 }
3690
3691 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
3692 wpas_notify_network_added(wpa_s, ssid);
3693
3694 wpa_s->next = global->ifaces;
3695 global->ifaces = wpa_s;
3696
3697 wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003698 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699
3700 return wpa_s;
3701}
3702
3703
3704/**
3705 * wpa_supplicant_remove_iface - Remove a network interface
3706 * @global: Pointer to global data from wpa_supplicant_init()
3707 * @wpa_s: Pointer to the network interface to be removed
3708 * Returns: 0 if interface was removed, -1 if interface was not found
3709 *
3710 * This function can be used to dynamically remove network interfaces from
3711 * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In
3712 * addition, this function is used to remove all remaining interfaces when
3713 * %wpa_supplicant is terminated.
3714 */
3715int wpa_supplicant_remove_iface(struct wpa_global *global,
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003716 struct wpa_supplicant *wpa_s,
3717 int terminate)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718{
3719 struct wpa_supplicant *prev;
3720
3721 /* Remove interface from the global list of interfaces */
3722 prev = global->ifaces;
3723 if (prev == wpa_s) {
3724 global->ifaces = wpa_s->next;
3725 } else {
3726 while (prev && prev->next != wpa_s)
3727 prev = prev->next;
3728 if (prev == NULL)
3729 return -1;
3730 prev->next = wpa_s->next;
3731 }
3732
3733 wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname);
3734
3735 if (global->p2p_group_formation == wpa_s)
3736 global->p2p_group_formation = NULL;
Dmitry Shmidt700a1372013-03-15 14:14:44 -07003737 if (global->p2p_invite_group == wpa_s)
3738 global->p2p_invite_group = NULL;
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003739 wpa_supplicant_deinit_iface(wpa_s, 1, terminate);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003740
3741 return 0;
3742}
3743
3744
3745/**
3746 * wpa_supplicant_get_eap_mode - Get the current EAP mode
3747 * @wpa_s: Pointer to the network interface
3748 * Returns: Pointer to the eap mode or the string "UNKNOWN" if not found
3749 */
3750const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s)
3751{
3752 const char *eapol_method;
3753
3754 if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) == 0 &&
3755 wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
3756 return "NO-EAP";
3757 }
3758
3759 eapol_method = eapol_sm_get_method_name(wpa_s->eapol);
3760 if (eapol_method == NULL)
3761 return "UNKNOWN-EAP";
3762
3763 return eapol_method;
3764}
3765
3766
3767/**
3768 * wpa_supplicant_get_iface - Get a new network interface
3769 * @global: Pointer to global data from wpa_supplicant_init()
3770 * @ifname: Interface name
3771 * Returns: Pointer to the interface or %NULL if not found
3772 */
3773struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global,
3774 const char *ifname)
3775{
3776 struct wpa_supplicant *wpa_s;
3777
3778 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
3779 if (os_strcmp(wpa_s->ifname, ifname) == 0)
3780 return wpa_s;
3781 }
3782 return NULL;
3783}
3784
3785
3786#ifndef CONFIG_NO_WPA_MSG
3787static const char * wpa_supplicant_msg_ifname_cb(void *ctx)
3788{
3789 struct wpa_supplicant *wpa_s = ctx;
3790 if (wpa_s == NULL)
3791 return NULL;
3792 return wpa_s->ifname;
3793}
3794#endif /* CONFIG_NO_WPA_MSG */
3795
3796
3797/**
3798 * wpa_supplicant_init - Initialize %wpa_supplicant
3799 * @params: Parameters for %wpa_supplicant
3800 * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure
3801 *
3802 * This function is used to initialize %wpa_supplicant. After successful
3803 * initialization, the returned data pointer can be used to add and remove
3804 * network interfaces, and eventually, to deinitialize %wpa_supplicant.
3805 */
3806struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
3807{
3808 struct wpa_global *global;
3809 int ret, i;
3810
3811 if (params == NULL)
3812 return NULL;
3813
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003814#ifdef CONFIG_DRIVER_NDIS
3815 {
3816 void driver_ndis_init_ops(void);
3817 driver_ndis_init_ops();
3818 }
3819#endif /* CONFIG_DRIVER_NDIS */
3820
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821#ifndef CONFIG_NO_WPA_MSG
3822 wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
3823#endif /* CONFIG_NO_WPA_MSG */
3824
3825 wpa_debug_open_file(params->wpa_debug_file_path);
3826 if (params->wpa_debug_syslog)
3827 wpa_debug_open_syslog();
Dmitry Shmidt04949592012-07-19 12:16:46 -07003828 if (params->wpa_debug_tracing) {
3829 ret = wpa_debug_open_linux_tracing();
3830 if (ret) {
3831 wpa_printf(MSG_ERROR,
3832 "Failed to enable trace logging");
3833 return NULL;
3834 }
3835 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836
3837 ret = eap_register_methods();
3838 if (ret) {
3839 wpa_printf(MSG_ERROR, "Failed to register EAP methods");
3840 if (ret == -2)
3841 wpa_printf(MSG_ERROR, "Two or more EAP methods used "
3842 "the same EAP type.");
3843 return NULL;
3844 }
3845
3846 global = os_zalloc(sizeof(*global));
3847 if (global == NULL)
3848 return NULL;
3849 dl_list_init(&global->p2p_srv_bonjour);
3850 dl_list_init(&global->p2p_srv_upnp);
3851 global->params.daemonize = params->daemonize;
3852 global->params.wait_for_monitor = params->wait_for_monitor;
3853 global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
3854 if (params->pid_file)
3855 global->params.pid_file = os_strdup(params->pid_file);
3856 if (params->ctrl_interface)
3857 global->params.ctrl_interface =
3858 os_strdup(params->ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003859 if (params->ctrl_interface_group)
3860 global->params.ctrl_interface_group =
3861 os_strdup(params->ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003862 if (params->override_driver)
3863 global->params.override_driver =
3864 os_strdup(params->override_driver);
3865 if (params->override_ctrl_interface)
3866 global->params.override_ctrl_interface =
3867 os_strdup(params->override_ctrl_interface);
3868 wpa_debug_level = global->params.wpa_debug_level =
3869 params->wpa_debug_level;
3870 wpa_debug_show_keys = global->params.wpa_debug_show_keys =
3871 params->wpa_debug_show_keys;
3872 wpa_debug_timestamp = global->params.wpa_debug_timestamp =
3873 params->wpa_debug_timestamp;
3874
3875 wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);
3876
3877 if (eloop_init()) {
3878 wpa_printf(MSG_ERROR, "Failed to initialize event loop");
3879 wpa_supplicant_deinit(global);
3880 return NULL;
3881 }
3882
Jouni Malinen75ecf522011-06-27 15:19:46 -07003883 random_init(params->entropy_file);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884
3885 global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
3886 if (global->ctrl_iface == NULL) {
3887 wpa_supplicant_deinit(global);
3888 return NULL;
3889 }
3890
3891 if (wpas_notify_supplicant_initialized(global)) {
3892 wpa_supplicant_deinit(global);
3893 return NULL;
3894 }
3895
3896 for (i = 0; wpa_drivers[i]; i++)
3897 global->drv_count++;
3898 if (global->drv_count == 0) {
3899 wpa_printf(MSG_ERROR, "No drivers enabled");
3900 wpa_supplicant_deinit(global);
3901 return NULL;
3902 }
3903 global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
3904 if (global->drv_priv == NULL) {
3905 wpa_supplicant_deinit(global);
3906 return NULL;
3907 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003908
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003909#ifdef CONFIG_WIFI_DISPLAY
3910 if (wifi_display_init(global) < 0) {
3911 wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
3912 wpa_supplicant_deinit(global);
3913 return NULL;
3914 }
3915#endif /* CONFIG_WIFI_DISPLAY */
3916
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003917 return global;
3918}
3919
3920
3921/**
3922 * wpa_supplicant_run - Run the %wpa_supplicant main event loop
3923 * @global: Pointer to global data from wpa_supplicant_init()
3924 * Returns: 0 after successful event loop run, -1 on failure
3925 *
3926 * This function starts the main event loop and continues running as long as
3927 * there are any remaining events. In most cases, this function is running as
3928 * long as the %wpa_supplicant process in still in use.
3929 */
3930int wpa_supplicant_run(struct wpa_global *global)
3931{
3932 struct wpa_supplicant *wpa_s;
3933
3934 if (global->params.daemonize &&
3935 wpa_supplicant_daemon(global->params.pid_file))
3936 return -1;
3937
3938 if (global->params.wait_for_monitor) {
3939 for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
3940 if (wpa_s->ctrl_iface)
3941 wpa_supplicant_ctrl_iface_wait(
3942 wpa_s->ctrl_iface);
3943 }
3944
3945 eloop_register_signal_terminate(wpa_supplicant_terminate, global);
3946 eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
3947
3948 eloop_run();
3949
3950 return 0;
3951}
3952
3953
3954/**
3955 * wpa_supplicant_deinit - Deinitialize %wpa_supplicant
3956 * @global: Pointer to global data from wpa_supplicant_init()
3957 *
3958 * This function is called to deinitialize %wpa_supplicant and to free all
3959 * allocated resources. Remaining network interfaces will also be removed.
3960 */
3961void wpa_supplicant_deinit(struct wpa_global *global)
3962{
3963 int i;
3964
3965 if (global == NULL)
3966 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003967
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003968#ifdef CONFIG_WIFI_DISPLAY
3969 wifi_display_deinit(global);
3970#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003971
3972 while (global->ifaces)
Dmitry Shmidte15c7b52011-08-03 15:04:35 -07003973 wpa_supplicant_remove_iface(global, global->ifaces, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974
3975 if (global->ctrl_iface)
3976 wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface);
3977
3978 wpas_notify_supplicant_deinitialized(global);
3979
3980 eap_peer_unregister_methods();
3981#ifdef CONFIG_AP
3982 eap_server_unregister_methods();
3983#endif /* CONFIG_AP */
3984
3985 for (i = 0; wpa_drivers[i] && global->drv_priv; i++) {
3986 if (!global->drv_priv[i])
3987 continue;
3988 wpa_drivers[i]->global_deinit(global->drv_priv[i]);
3989 }
3990 os_free(global->drv_priv);
3991
3992 random_deinit();
3993
3994 eloop_destroy();
3995
3996 if (global->params.pid_file) {
3997 os_daemonize_terminate(global->params.pid_file);
3998 os_free(global->params.pid_file);
3999 }
4000 os_free(global->params.ctrl_interface);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07004001 os_free(global->params.ctrl_interface_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002 os_free(global->params.override_driver);
4003 os_free(global->params.override_ctrl_interface);
4004
Dmitry Shmidt4ce9c872013-10-24 11:08:13 -07004005 os_free(global->p2p_disallow_freq.range);
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004006 os_free(global->p2p_go_avoid_freq.range);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07004007 os_free(global->add_psk);
Dmitry Shmidt04949592012-07-19 12:16:46 -07004008
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004009 os_free(global);
4010 wpa_debug_close_syslog();
4011 wpa_debug_close_file();
Dmitry Shmidt04949592012-07-19 12:16:46 -07004012 wpa_debug_close_linux_tracing();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004013}
4014
4015
4016void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s)
4017{
4018 if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) &&
4019 wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
4020 char country[3];
4021 country[0] = wpa_s->conf->country[0];
4022 country[1] = wpa_s->conf->country[1];
4023 country[2] = '\0';
4024 if (wpa_drv_set_country(wpa_s, country) < 0) {
4025 wpa_printf(MSG_ERROR, "Failed to set country code "
4026 "'%s'", country);
4027 }
4028 }
4029
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004030 if (wpa_s->conf->changed_parameters & CFG_CHANGED_EXT_PW_BACKEND)
4031 wpas_init_ext_pw(wpa_s);
4032
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004033#ifdef CONFIG_WPS
4034 wpas_wps_update_config(wpa_s);
4035#endif /* CONFIG_WPS */
4036
4037#ifdef CONFIG_P2P
4038 wpas_p2p_update_config(wpa_s);
4039#endif /* CONFIG_P2P */
4040
4041 wpa_s->conf->changed_parameters = 0;
4042}
4043
4044
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045static void add_freq(int *freqs, int *num_freqs, int freq)
4046{
4047 int i;
4048
4049 for (i = 0; i < *num_freqs; i++) {
4050 if (freqs[i] == freq)
4051 return;
4052 }
4053
4054 freqs[*num_freqs] = freq;
4055 (*num_freqs)++;
4056}
4057
4058
4059static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
4060{
4061 struct wpa_bss *bss, *cbss;
4062 const int max_freqs = 10;
4063 int *freqs;
4064 int num_freqs = 0;
4065
4066 freqs = os_zalloc(sizeof(int) * (max_freqs + 1));
4067 if (freqs == NULL)
4068 return NULL;
4069
4070 cbss = wpa_s->current_bss;
4071
4072 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
4073 if (bss == cbss)
4074 continue;
4075 if (bss->ssid_len == cbss->ssid_len &&
4076 os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
4077 wpa_blacklist_get(wpa_s, bss->bssid) == NULL) {
4078 add_freq(freqs, &num_freqs, bss->freq);
4079 if (num_freqs == max_freqs)
4080 break;
4081 }
4082 }
4083
4084 if (num_freqs == 0) {
4085 os_free(freqs);
4086 freqs = NULL;
4087 }
4088
4089 return freqs;
4090}
4091
4092
4093void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
4094{
4095 int timeout;
4096 int count;
4097 int *freqs = NULL;
4098
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004099 wpas_connect_work_done(wpa_s);
4100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101 /*
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004102 * Remove possible authentication timeout since the connection failed.
4103 */
4104 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
4105
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004106 if (wpa_s->disconnected) {
4107 /*
4108 * There is no point in blacklisting the AP if this event is
4109 * generated based on local request to disconnect.
4110 */
4111 wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure "
4112 "indication since interface has been put into "
4113 "disconnected state");
4114 return;
4115 }
4116
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004117 /*
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004118 * Add the failed BSSID into the blacklist and speed up next scan
4119 * attempt if there could be other APs that could accept association.
4120 * The current blacklist count indicates how many times we have tried
4121 * connecting to this AP and multiple attempts mean that other APs are
4122 * either not available or has already been tried, so that we can start
4123 * increasing the delay here to avoid constant scanning.
4124 */
4125 count = wpa_blacklist_add(wpa_s, bssid);
4126 if (count == 1 && wpa_s->current_bss) {
4127 /*
4128 * This BSS was not in the blacklist before. If there is
4129 * another BSS available for the same ESS, we should try that
4130 * next. Otherwise, we may as well try this one once more
4131 * before allowing other, likely worse, ESSes to be considered.
4132 */
4133 freqs = get_bss_freqs_in_ess(wpa_s);
4134 if (freqs) {
4135 wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
4136 "has been seen; try it next");
4137 wpa_blacklist_add(wpa_s, bssid);
4138 /*
4139 * On the next scan, go through only the known channels
4140 * used in this ESS based on previous scans to speed up
4141 * common load balancing use case.
4142 */
4143 os_free(wpa_s->next_scan_freqs);
4144 wpa_s->next_scan_freqs = freqs;
4145 }
4146 }
4147
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004148 /*
4149 * Add previous failure count in case the temporary blacklist was
4150 * cleared due to no other BSSes being available.
4151 */
4152 count += wpa_s->extra_blacklist_count;
4153
Dmitry Shmidt4b060592013-04-29 16:42:49 -07004154 if (count > 3 && wpa_s->current_ssid) {
4155 wpa_printf(MSG_DEBUG, "Continuous association failures - "
4156 "consider temporary network disabling");
4157 wpas_auth_failed(wpa_s);
4158 }
4159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 switch (count) {
4161 case 1:
4162 timeout = 100;
4163 break;
4164 case 2:
4165 timeout = 500;
4166 break;
4167 case 3:
4168 timeout = 1000;
4169 break;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004170 case 4:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 timeout = 5000;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004172 break;
4173 default:
4174 timeout = 10000;
4175 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004176 }
4177
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004178 wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d "
4179 "ms", count, timeout);
4180
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 /*
4182 * TODO: if more than one possible AP is available in scan results,
4183 * could try the other ones before requesting a new scan.
4184 */
4185 wpa_supplicant_req_scan(wpa_s, timeout / 1000,
4186 1000 * (timeout % 1000));
4187}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004188
4189
4190int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s)
4191{
4192 return wpa_s->conf->ap_scan == 2 ||
4193 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION);
4194}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004195
Dmitry Shmidt04949592012-07-19 12:16:46 -07004196
4197#if defined(CONFIG_CTRL_IFACE) || defined(CONFIG_CTRL_IFACE_DBUS_NEW)
4198int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
4199 struct wpa_ssid *ssid,
4200 const char *field,
4201 const char *value)
4202{
4203#ifdef IEEE8021X_EAPOL
4204 struct eap_peer_config *eap = &ssid->eap;
4205
4206 wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
4207 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
4208 (const u8 *) value, os_strlen(value));
4209
4210 switch (wpa_supplicant_ctrl_req_from_string(field)) {
4211 case WPA_CTRL_REQ_EAP_IDENTITY:
4212 os_free(eap->identity);
4213 eap->identity = (u8 *) os_strdup(value);
4214 eap->identity_len = os_strlen(value);
4215 eap->pending_req_identity = 0;
4216 if (ssid == wpa_s->current_ssid)
4217 wpa_s->reassociate = 1;
4218 break;
4219 case WPA_CTRL_REQ_EAP_PASSWORD:
4220 os_free(eap->password);
4221 eap->password = (u8 *) os_strdup(value);
4222 eap->password_len = os_strlen(value);
4223 eap->pending_req_password = 0;
4224 if (ssid == wpa_s->current_ssid)
4225 wpa_s->reassociate = 1;
4226 break;
4227 case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
4228 os_free(eap->new_password);
4229 eap->new_password = (u8 *) os_strdup(value);
4230 eap->new_password_len = os_strlen(value);
4231 eap->pending_req_new_password = 0;
4232 if (ssid == wpa_s->current_ssid)
4233 wpa_s->reassociate = 1;
4234 break;
4235 case WPA_CTRL_REQ_EAP_PIN:
4236 os_free(eap->pin);
4237 eap->pin = os_strdup(value);
4238 eap->pending_req_pin = 0;
4239 if (ssid == wpa_s->current_ssid)
4240 wpa_s->reassociate = 1;
4241 break;
4242 case WPA_CTRL_REQ_EAP_OTP:
4243 os_free(eap->otp);
4244 eap->otp = (u8 *) os_strdup(value);
4245 eap->otp_len = os_strlen(value);
4246 os_free(eap->pending_req_otp);
4247 eap->pending_req_otp = NULL;
4248 eap->pending_req_otp_len = 0;
4249 break;
4250 case WPA_CTRL_REQ_EAP_PASSPHRASE:
4251 os_free(eap->private_key_passwd);
4252 eap->private_key_passwd = (u8 *) os_strdup(value);
4253 eap->pending_req_passphrase = 0;
4254 if (ssid == wpa_s->current_ssid)
4255 wpa_s->reassociate = 1;
4256 break;
Dmitry Shmidt051af732013-10-22 13:52:46 -07004257 case WPA_CTRL_REQ_SIM:
4258 os_free(eap->external_sim_resp);
4259 eap->external_sim_resp = os_strdup(value);
4260 break;
Dmitry Shmidt04949592012-07-19 12:16:46 -07004261 default:
4262 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
4263 return -1;
4264 }
4265
4266 return 0;
4267#else /* IEEE8021X_EAPOL */
4268 wpa_printf(MSG_DEBUG, "CTRL_IFACE: IEEE 802.1X not included");
4269 return -1;
4270#endif /* IEEE8021X_EAPOL */
4271}
4272#endif /* CONFIG_CTRL_IFACE || CONFIG_CTRL_IFACE_DBUS_NEW */
4273
4274
4275int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
4276{
4277 int i;
4278 unsigned int drv_enc;
4279
4280 if (ssid == NULL)
4281 return 1;
4282
4283 if (ssid->disabled)
4284 return 1;
4285
4286 if (wpa_s && wpa_s->drv_capa_known)
4287 drv_enc = wpa_s->drv_enc;
4288 else
4289 drv_enc = (unsigned int) -1;
4290
4291 for (i = 0; i < NUM_WEP_KEYS; i++) {
4292 size_t len = ssid->wep_key_len[i];
4293 if (len == 0)
4294 continue;
4295 if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40))
4296 continue;
4297 if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104))
4298 continue;
4299 if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128))
4300 continue;
4301 return 1; /* invalid WEP key */
4302 }
4303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004304 if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
4305 !ssid->ext_psk)
4306 return 1;
4307
Dmitry Shmidt04949592012-07-19 12:16:46 -07004308 return 0;
4309}
4310
4311
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004312int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004313{
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004314 if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004315 return 1;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07004316 if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004317 return 0;
Dmitry Shmidt687922c2012-03-26 14:02:32 -07004318 return -1;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004319}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004320
4321
4322void wpas_auth_failed(struct wpa_supplicant *wpa_s)
4323{
4324 struct wpa_ssid *ssid = wpa_s->current_ssid;
4325 int dur;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004326 struct os_reltime now;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004327
4328 if (ssid == NULL) {
4329 wpa_printf(MSG_DEBUG, "Authentication failure but no known "
4330 "SSID block");
4331 return;
4332 }
4333
4334 if (ssid->key_mgmt == WPA_KEY_MGMT_WPS)
4335 return;
4336
4337 ssid->auth_failures++;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07004338
4339#ifdef CONFIG_P2P
4340 if (ssid->p2p_group &&
4341 (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) {
4342 /*
4343 * Skip the wait time since there is a short timeout on the
4344 * connection to a P2P group.
4345 */
4346 return;
4347 }
4348#endif /* CONFIG_P2P */
4349
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004350 if (ssid->auth_failures > 50)
4351 dur = 300;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004352 else if (ssid->auth_failures > 10)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004353 dur = 120;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004354 else if (ssid->auth_failures > 5)
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004355 dur = 90;
4356 else if (ssid->auth_failures > 3)
4357 dur = 60;
4358 else if (ssid->auth_failures > 2)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004359 dur = 30;
4360 else if (ssid->auth_failures > 1)
4361 dur = 20;
4362 else
4363 dur = 10;
4364
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08004365 if (ssid->auth_failures > 1 &&
4366 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt))
4367 dur += os_random() % (ssid->auth_failures * 10);
4368
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004369 os_get_reltime(&now);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004370 if (now.sec + dur <= ssid->disabled_until.sec)
4371 return;
4372
4373 ssid->disabled_until.sec = now.sec + dur;
4374
4375 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED
4376 "id=%d ssid=\"%s\" auth_failures=%u duration=%d",
4377 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
4378 ssid->auth_failures, dur);
4379}
4380
4381
4382void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s,
4383 struct wpa_ssid *ssid, int clear_failures)
4384{
4385 if (ssid == NULL)
4386 return;
4387
4388 if (ssid->disabled_until.sec) {
4389 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED
4390 "id=%d ssid=\"%s\"",
4391 ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
4392 }
4393 ssid->disabled_until.sec = 0;
4394 ssid->disabled_until.usec = 0;
4395 if (clear_failures)
4396 ssid->auth_failures = 0;
4397}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004398
4399
4400int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid)
4401{
4402 size_t i;
4403
4404 if (wpa_s->disallow_aps_bssid == NULL)
4405 return 0;
4406
4407 for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) {
4408 if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN,
4409 bssid, ETH_ALEN) == 0)
4410 return 1;
4411 }
4412
4413 return 0;
4414}
4415
4416
4417int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid,
4418 size_t ssid_len)
4419{
4420 size_t i;
4421
4422 if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL)
4423 return 0;
4424
4425 for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) {
4426 struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i];
4427 if (ssid_len == s->ssid_len &&
4428 os_memcmp(ssid, s->ssid, ssid_len) == 0)
4429 return 1;
4430 }
4431
4432 return 0;
4433}
4434
4435
4436/**
4437 * wpas_request_connection - Request a new connection
4438 * @wpa_s: Pointer to the network interface
4439 *
4440 * This function is used to request a new connection to be found. It will mark
4441 * the interface to allow reassociation and request a new scan to find a
4442 * suitable network to connect to.
4443 */
4444void wpas_request_connection(struct wpa_supplicant *wpa_s)
4445{
4446 wpa_s->normal_scans = 0;
4447 wpa_supplicant_reinit_autoscan(wpa_s);
4448 wpa_s->extra_blacklist_count = 0;
4449 wpa_s->disconnected = 0;
4450 wpa_s->reassociate = 1;
Dmitry Shmidt2f3b8de2013-03-01 09:32:50 -08004451
4452 if (wpa_supplicant_fast_associate(wpa_s) != 1)
4453 wpa_supplicant_req_scan(wpa_s, 0, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004454}
Dmitry Shmidtea69e842013-05-13 14:52:28 -07004455
4456
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004457void dump_freq_array(struct wpa_supplicant *wpa_s, const char *title,
4458 int *freq_array, unsigned int len)
4459{
4460 unsigned int i;
4461
4462 wpa_dbg(wpa_s, MSG_DEBUG, "Shared frequencies (len=%u): %s",
4463 len, title);
4464 for (i = 0; i < len; i++)
4465 wpa_dbg(wpa_s, MSG_DEBUG, "freq[%u]: %d", i, freq_array[i]);
4466}
4467
4468
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004469/*
4470 * Find the operating frequencies of any of the virtual interfaces that
4471 * are using the same radio as the current interface.
4472 */
4473int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
4474 int *freq_array, unsigned int len)
4475{
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004476 struct wpa_supplicant *ifs;
4477 u8 bssid[ETH_ALEN];
4478 int freq;
4479 unsigned int idx = 0, i;
4480
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004481 wpa_dbg(wpa_s, MSG_DEBUG,
4482 "Determining shared radio frequencies (max len %u)", len);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004483 os_memset(freq_array, 0, sizeof(int) * len);
4484
4485 /* First add the frequency of the local interface */
4486 if (wpa_s->current_ssid != NULL && wpa_s->assoc_freq != 0) {
4487 if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
4488 wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)
4489 freq_array[idx++] = wpa_s->current_ssid->frequency;
4490 else if (wpa_drv_get_bssid(wpa_s, bssid) == 0)
4491 freq_array[idx++] = wpa_s->assoc_freq;
4492 }
4493
4494 /* If get_radio_name is not supported, use only the local freq */
4495 if (!wpa_s->driver->get_radio_name) {
4496 freq = wpa_drv_shared_freq(wpa_s);
4497 if (freq > 0 && idx < len &&
4498 (idx == 0 || freq_array[0] != freq))
4499 freq_array[idx++] = freq;
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004500 dump_freq_array(wpa_s, "No get_radio_name", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004501 return idx;
4502 }
4503
Dmitry Shmidt01904cf2013-12-05 11:08:35 -08004504 dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
4505 radio_list) {
4506 if (wpa_s == ifs)
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004507 continue;
4508
4509 if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
4510 continue;
4511
4512 if (ifs->current_ssid->mode == WPAS_MODE_AP ||
4513 ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
4514 freq = ifs->current_ssid->frequency;
4515 else if (wpa_drv_get_bssid(ifs, bssid) == 0)
4516 freq = ifs->assoc_freq;
4517 else
4518 continue;
4519
4520 /* Hold only distinct freqs */
4521 for (i = 0; i < idx; i++)
4522 if (freq_array[i] == freq)
4523 break;
4524
4525 if (i == idx)
4526 freq_array[idx++] = freq;
4527 }
Dmitry Shmidtb96dad42013-11-05 10:07:29 -08004528
4529 dump_freq_array(wpa_s, "completed iteration", freq_array, idx);
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004530 return idx;
4531}